从RGB字节数组创建BufferedImage

3

我有一个带有RGB值的byte[]数组。我想创建BufferedImage,而不需要逐个设置像素,因为图像可能很大。我找到了以下代码片段:

        byte[] frame = ...;
        BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
        img.setData(Raster.createRaster(img.getSampleModel(), new DataBufferByte(frame, frame.length), new Point() ) );

这种方法很好用,但有一个小问题;-) TYPE_3BYTE_BGR 需要按相反的顺序来处理字节。

所以问题是:

  1. 是否可能以不创建具有期望顺序的新字节数组的方式加载我的数组?
  2. 如果不可能,那么除了使用 for 循环从 RGB 格式复制数据到 BGR 之外,是否有更好的方法?

为什么不能创建第二个数组或重新分配编辑后的数组到“frame”? - MAO3J1m0Op
选项2有什么问题吗?(如果您在现有的字节数组中就地更改顺序)您的计算机不会抱怨这很繁琐 - 这是计算机擅长的工作类型。 - Erwin Bolwidt
@ErwinBolwidt觉得复制75000000个项目(给定5000x5000图像)然后再加载到缓冲图像中并不是最好的解决方案。如果必须要做,我会去完成它,但我更愿意避免这种情况。 - marxin
你应该查看BufferedImage.setData的实现,因为它会逐行从你传入的光栅数据中复制数据。如果你非常关注性能,那么BufferedImage.getRaster().setDataElements似乎是你应该使用的方法。(而且你只有在频繁执行此操作,比如每秒多次时才需要关注性能) - Erwin Bolwidt
如果我不经常这样做,我就不会烦恼了。setData可能做的事情与手动循环相同,但速度更快,我不知道为什么。setDataElements期望不同的格式,所以又是同样的问题。现在我会选择循环解决方案,因为至少它能工作,稍后再回来处理这个问题。 - marxin
显示剩余2条评论
2个回答

3

试试这段代码

BufferedImage img = create3ByteRGBImage(int width, int height, new int[] {8, 8, 8},
                                     new int[] {0, 1, 2});    

private BufferedImage create3ByteRGBImage(width, height, int[] nBits, int[] bOffs) {
            ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
            ColorModel colorModel =
                new ComponentColorModel(cs, nBits,
                                        false, false,
                                        Transparency.OPAQUE,
                                        DataBuffer.TYPE_BYTE);
            WritableRaster raster =
                Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
                                               width, height,
                                               width*3, 3,
                                               bOffs, null);
            return new BufferedImage(colorModel, raster, false, null);
        }

太好了 ;) 所以我编辑了答案,只留下第一个建议,因为它运行良好。 - Diego Marin Santos

0
前面的答案是正确的,但可以简化以提高可读性:
ColorSpace colorSpace = ColorSpace.getInstance(ColorSpace.CS_sRGB);

ColorModel model = new ComponentColorModel(
    colorSpace, 
    false,
    true, 
    Transparency.OPAQUE, 
    DataBuffer.TYPE_BYTE
);

WritableRaster raster = Raster.createInterleavedRaster(
    DataBuffer.TYPE_BYTE, 
    width, 
    height, 
    3, 
    null
);

BufferedImage image = new BufferedImage(model, raster, true, null);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接