【发布时间】:2010-11-11 17:06:42
【问题描述】:
在 Java SE 中将原始字节数组转换为 Image 的正确方法是什么。 数组由字节组成,每三个字节代表一个像素,每个字节对应对应的RGB分量。
谁能推荐一个代码示例?
谢谢, 迈克
【问题讨论】:
-
最终我没有找到更好的东西: for(int y=0; y
-
字节数组的维度是多少?是一维数组,二维数组,还是3维数组?
在 Java SE 中将原始字节数组转换为 Image 的正确方法是什么。 数组由字节组成,每三个字节代表一个像素,每个字节对应对应的RGB分量。
谁能推荐一个代码示例?
谢谢, 迈克
【问题讨论】:
假设您的原始数据是一维数组,例如:
byte[] imageBytes = new byte[1024];
// transform to bufferImage
BufferedImage bufferedImage = ImageIO.read(new ByteArrayInputStream(imageBytes));
// if you want to do some operations to the image, like resize,
// use the lib (net.coobird.thumbnailator)
BufferedImage image = Thumbnails.of(bufferedImage).forceSize(WIDTH, HEIGHT)
.outputFormat("bmp").asBufferedImage();
【讨论】:
您可以使用 Raster 类来做到这一点。它更好,因为它不需要迭代和复制字节数组。
byte[] raw = new byte[width*height*3]; // raw bytes of our image
DataBuffer buffer = new DataBufferByte(raw, raw.length);
//The most difficult part of awt api for me to learn
SampleModel sampleModel = new ComponentSampleModel(DataBuffer.TYPE_BYTE, width, height, 3, width*3, new int[]{2,1,0});
Raster raster = Raster.createRaster(sampleModel, buffer, null);
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
image.setData(raster);
【讨论】:
如果您的 RGB 值按 B、G、R 顺序排列,folkyatina 的方法有效,但如果它们按 R、G、B 顺序排列,我发现以下代码可以工作:
DataBuffer rgbData = new DataBufferByte(rgbs, rgbs.length);
WritableRaster raster = Raster.createInterleavedRaster(
rgbData, width, height,
width * 3, // scanlineStride
3, // pixelStride
new int[]{0, 1, 2}, // bandOffsets
null);
ColorModel colorModel = new ComponentColorModel(
ColorSpace.getInstance(ColorSpace.CS_sRGB),
new int[]{8, 8, 8}, // bits
false, // hasAlpha
false, // isPreMultiplied
ComponentColorModel.OPAQUE,
DataBuffer.TYPE_BYTE);
return new BufferedImage(colorModel, raster, false, null);
【讨论】:
有一个 setRGB 变体,它接受一个 RGBA 值的 int 数组:
BufferedImage img=new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
int[] raw = new int[data.length * 4 / 3];
for (int i = 0; i < data.length / 3; i++) {
raw[i] = 0xFF000000 |
((data[3 * i + 0] & 0xFF) << 16) |
((data[3 * i + 1] & 0xFF) << 8) |
((data[3 * i + 2] & 0xFF));
}
img.setRGB(0, 0, width, height, raw, 0, width);
性能特点类似于CoderTao的方案。
【讨论】:
假设您知道图像的高度和宽度。
BufferedImage img=new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for(int r=0; r<height; r++)
for(int c=0; c<width; c++)
{
int index=r*width+c;
int red=colors[index] & 0xFF;
int green=colors[index+1] & 0xFF;
int blue=colors[index+2] & 0xFF;
int rgb = (red << 16) | (green << 8) | blue;
img.setRGB(c, r, rgb);
}
大概。这假设像素数据被编码为一组行;并且颜色的长度是 3 * width * height (应该是有效的)。
【讨论】:
int rgb = ((int)colors[in] << 24) + ((int)colors[in+1] << 8) + (int)colors[in]
colors 是一个 RGB 数组(其中 R、G 和 B 是单独的字节),index 是否应该在每个循环中增加超过 1?