简体   繁体   English

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

[英]Convert 8bit Grayscale image byte array to a BufferedImage

I have a byte array containing data of the raw grayscale 8bit image, which I need to convert to a BufferedImage.我有一个包含原始灰度 8 位图像数据的字节数组,我需要将其转换为 BufferedImage。 I've tried doing:我试过这样做:

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

However, the resulting image object is null which means I'm doing something wrong here.但是,生成的image对象为空,这意味着我在这里做错了。

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). 但是将无法管理映像(因为后备阵列是暴露的且易变的)。

Both options are demonstrated below: 这两个选项如下所示:

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);

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: 如果图像数据不在线性灰色空间中,则可以使用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);

I've managed to did the conversion for the 640x480 resolution the following way: 我设法通过以下方式对640x480分辨率进行了转换:

BufferedImage image = new BufferedImage(640,480,BufferedImage.TYPE_BYTE_INDEXED);

int i = 0;
for(int y = 0; y < 480; y++)
{
    for(int x = 0; x < 640; x++)
    {
        int g = imageBytes[i++] & 0xFF;
        image.setRGB(x,y,new Color(g,g,g).getRGB());
    }
}

EDIT: removed useless code (thanks to Marco13) 编辑:删除了无用的代码(感谢Marco13)

Java爪哇

 BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
 image.getRaster().setDataElements(0, 0, width, height, array));

Kotlin科特林

val image = BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY)
image.raster.setDataElements(0, 0, width, height, byteArray )

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 从Java中包含8bit(灰度)或1bit(二进制)数据的字节数组创建图像(bmp左右) - Create an image (bmp or so) from byte array containing 8bit(grayscale) or 1bit(binary) data in Java Java / SWT显示字节数组中的8位灰度图像 - Java/SWT displaying an 8bit grayscaling Image from a byte array Java中的GrayScale(每像素8位)图像像素处理 - GrayScale (8bit per pixel) Image Pixel Manipulation in Java OpenGL - 当tryint将字节数组转换为BufferedImage时,Image == null - OpenGL - Image == null when tryint to convert byte array to BufferedImage 在Android中的8位字节数组上存储16位音频 - Storing 16Bit Audio on a 8bit byte array in android 32位灰度的BufferedImage? - 32-bit grayscale BufferedImage? 将原始像素数据(作为字节数组)转换为BufferedImage - Convert raw pixel data (as byte array) to BufferedImage java.awt.image.BufferedImage使用自定义ColorSpace进行24位RGB到8位灰度转换 - java.awt.image.BufferedImage 24-bit RGB to 8-bit Grayscale conversion using custom ColorSpace 将数据类型TYPE_4BYTE_ABGR的字节数组转换为BufferedImage - Convert byte array of data type TYPE_4BYTE_ABGR to BufferedImage 如何将BufferedImage转换为8位? - How to convert a BufferedImage to 8 bit?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM