簡體   English   中英

從 BufferedImage 獲取 RGBA 字節數組 Java

[英]Getting a RGBA byte array from a BufferedImage Java

我有一個 BufferedImage 並希望獲得格式為 R GBA 的字節數組(每個字節一個通道)。 我怎樣才能做到這一點?

簡單的方法是使用BufferedImage.getRGB (盡管它的名稱為您提供 ARGB 值),並將打包的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 ,它由 RGBA 格式的byte[]支持,如下所示:

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 用戶多年的已知問題......

最終我只是使用 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);

BufferedImage#getRGB開始,無論圖像的ColorModel是什么,它都會返回ARGB值 - 請查看其文檔

然后使用ColorModel默認實例來獲取組件( getRed()getGreen() 、...)或獲取組件的int數組(例如getComponents() )。 或者只是拆分getRGB()返回的值,格式在ColorModel#getRGBdefault中描述。

最終圖像(或其柵格數據)可以轉換為TYPE_4BYTE_ABGR,因此可以直接使用柵格數據(只是猜測,我從來沒有做過)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM