[英]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.