java - 将 8 位灰度图像字节数组转换为 BufferedImage

标签 java image type-conversion bufferedimage

我有一个字节数组,其中包含原始灰度 8 位图像的数据,我需要将其转换为 BufferedImage。我尝试过这样做:

BufferedImage image = ImageIO.read(new ByteArrayInputStream(bytes));

但是,生成的 image 对象为 null,这意味着我在这里做错了。

进行此类转换的正确方法是什么?

最佳答案

有两种好方法可以做到这一点,具体取决于您的用例。

创建一个新的灰色图像,并将数据复制到其中。这将使图像保持“受管理”,这可能会带来更好的渲染性能(即在屏幕上)。但它需要两倍的内存,并将数据从输入复制到图像。

另一种方法是直接“围绕”现有像素数据创建灰度图像。这会更快,并且几乎不使用额外的堆,因为它避免了复制像素数据。但图像不会被管理(因为支持数组是公开的且可变的)。

这两个选项如下所示:

int w = 640;
int h = 480;

byte[] imageBytes = new byte[w * h];

// 1 Keeps the image "managed" at the expense of twice the memory + a large array copy
BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_GRAY);
image.getRaster().setDataElements(0, 0, w, h, imageBytes);

System.out.println("image: " + image);

// 2 Faster, and uses less memory, but will make the image "unmanaged"
ColorModel cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_GRAY), false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
WritableRaster raster = Raster.createInterleavedRaster(new DataBufferByte(imageBytes, imageBytes.length), w, h, w, 1, new int[]{0}, null);
BufferedImage image2 = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);

System.out.println("image2: " + image2);

如果图像数据不在线性灰色空间中,则可以使用 IndexColorModel 将输入映射到您想要的任何范围:

// Alternate, using IndexColorModel, if your input isn't in linear gray color space
int[] cmap = new int[256]; // TODO: Add ARGB packed colors here...
IndexColorModel icm = new IndexColorModel(8, 256, cmap, 0, false, -1, DataBuffer.TYPE_BYTE);

// As 1
BufferedImage image3 = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_INDEXED, icm);
image3.getRaster().setDataElements(0, 0, w, h, imageBytes);
System.out.println("image3: " + image3);

// As 2
BufferedImage image4 = new BufferedImage(icm, raster, cm.isAlphaPremultiplied(), null);

System.out.println("image4: " + image4);

关于java - 将 8 位灰度图像字节数组转换为 BufferedImage,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54252367/

相关文章:

java - SAPUI5 servlet 调用 pdf

java - 整数到十六进制字符串 NumberformatException

python - ValueError : Error when checking input: expected time_distributed_46_input to have 5 dimensions, 但得到形状为 (200, 200, 3) 的数组

c++ - 将 double 转换为 LSBF (little Endian) 十六进制字符串

Ruby:4 字节数组到 int32

c# - 是否有理由先转换为一个类型然后再转换为可空类型?

java - 在 AsyncTask 中使用 ListenableFuture Azure 调用

java - 获取与 JSP 的 ServletContext 连接

javascript - 如何从 IMG 元素获取图像内容(不是 url)?

image - 尝试使用opencv使Photoshop达到色彩平衡