问题描述
我有一个包含原始灰度 8 位图像数据的字节数组,我需要将其转换为 BufferedImage.我试过这样做:
I have a byte array containing data of the raw grayscale 8bit image, which I need to convert to a BufferedImage. I've tried doing:
BufferedImage image = ImageIO.read(new ByteArrayInputStream(bytes));
然而,结果 image
对象为空,这意味着我在这里做错了.
However, the resulting image
object is null which means I'm doing something wrong here.
进行此类转换的正确方法是什么?
What's the correct way of making such a conversion?
推荐答案
有两种很好的方法可以做到这一点,具体取决于您的用例.
There are two good ways to do this, depending on your use case.
要么创建一个新的灰色图像,然后将数据复制到其中.这将保持图像管理",这可能会导致更好的渲染性能(即在屏幕上).但它需要两倍的内存,并将输入中的数据复制到图像中.
Either create a new, gray image, and copy the data into it. This will keep the image "managed", which may lead to better rendering performance (ie. on screen). But it will need twice as much memory, and copy the data from your input to the image.
另一种方法是直接围绕"现有像素数据创建灰度图像.这会更快,并且几乎不使用额外的堆,因为它避免了复制像素数据.但是图像不会被管理(因为后备数组是公开的并且是可变的).
The other, is to create the gray image directly "around" your existing pixel data. This will be faster, and use almost no extra heap, as it avoids copying the pixel data. But the image will not be managed (as the backing array is exposed and mutable).
这两个选项如下所示:
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
将输入映射到您想要的任何范围:
If the image data isn't in linear gray color space, one could use an IndexColorModel
to map the input into whatever range you want:
// 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);
这篇关于将 8 位灰度图像字节数组转换为 BufferedImage的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!