从BuffereImage java获取rgba字节数组

5cg8jx4n  于 2021-06-27  发布在  Java
关注(0)|答案(3)|浏览(419)

我有一个bufferedimage,并希望得到一个字节数组的格式r g b a(一个通道每字节)。我该怎么做?

rpppsulh

rpppsulh1#

最后,我只是使用java库pngj来加载它,并以rgba格式相应地加载每一行:

for(int j = 0; j < reader.imgInfo.rows;j++) {
        IImageLine row = reader.readRow();
        for(int b = 0; b < reader.imgInfo.cols; b++) { 
                int argb = ch == 3 ? ImageLineHelper.getPixelRGB8(row, b) : ch == 4 ? ImageLineHelper.getPixelARGB8(row, b) : 0xFF000000;

然后我转入rgba:

pixels.write((argb & 0x00FF0000) >> 16);
pixels.write((argb & 0x0000FF00) >> 8 );
pixels.write((argb & 0x000000FF) >> 0 );//neatness lol
pixels.write((argb & 0xFF000000) >> 24);
euoag5mw

euoag5mw2#

从…开始 BufferedImage#getRGB 它回来了 ARGB 价值观 ColorModel 检查imgage的文档。
然后使用 ColorModel 要么得到组件( getRed() , getGreen() ,…)或获得 int 组件阵列(例如。 getComponents() ). 或者只是将 getRGB() ,格式如中所述 ColorModel#getRGBdefault .
最终,图像(或其光栅数据)可以转换为类型4byte\u abgr,因此光栅数据可以直接使用(只是猜测,我从来没有做过)

1dkrff03

1dkrff033#

简单的方法是使用 BufferedImage.getRGB (尽管它的名称为rgba值),并转换压缩的 int[]byte[] 四倍长。输入可以是任何文件 ImageIO 可以阅读,一个png就可以了。

public static void main(String[] args) throws IOException {
    BufferedImage image = ImageIO.read(new File(args[0]));

    int[] argb = image.getRGB(0, 0, image.getWidth(), image.getHeight(), null, 0, image.getWidth());
    byte[] rgba = intARGBtoByteRGBA(argb);
}

private static byte[] intARGBtoByteRGBA(int[] argb) {
    byte[] rgba = new byte[argb.length * 4];

    for (int i = 0; i < argb.length; i++) {
        rgba[4 * i    ] = (byte) ((argb[i] >> 16) & 0xff); // R
        rgba[4 * i + 1] = (byte) ((argb[i] >>  8) & 0xff); // G
        rgba[4 * i + 2] = (byte) ((argb[i]      ) & 0xff); // B
        rgba[4 * i + 3] = (byte) ((argb[i] >> 24) & 0xff); // A
    }

    return rgba;
}

一个稍微有趣一点的方法,是创建一个 BufferedImage 这是由一个 byte[] 已经是rgba格式,如下所示:

public static void main(String[] args) throws IOException {
    BufferedImage image = ImageIO.read(new File(args[0]));

    ComponentColorModel colorModel = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE);
    WritableRaster raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, image.getWidth(), image.getHeight(), image.getWidth() * 4, 4, new int[] {0, 1, 2, 3}, null); // R, G, B, A order
    BufferedImage imageToo = new BufferedImage(colorModel, raster, colorModel.isAlphaPremultiplied(), null);

    // This array will be in the same R, G, B, A order
    byte[] rgbaToo = ((DataBufferByte) raster.getDataBuffer()).getData();

    // Draw the image onto the RGBA buffer, which will be updated immediately
    Graphics2D g = imageToo.createGraphics();
    try {
        g.setComposite(AlphaComposite.Src);
        g.drawImage(image, 0, 0, null);
    }
    finally {
        g.dispose();
    }
}

上面哪一个例子更适合使用,取决于用例。
如果你只需要一次转换,第一次可能更容易推理和工作得很好。
如果需要多次更新缓冲区,第二种方法可能会产生更好的性能。
ps:我对所有的测试输入都使用两种方法得到完全相同的结果,除了那些原始输入是灰度的(使用 ColorSpace.CS_GRAY ). 我相信这是一个困扰java2d用户多年的已知问题。。。

相关问题