如何解决从 BufferedImage Java 获取 RGBA 字节数组
我有一个 BufferedImage 并且想要获得一个格式为 R G B A 的字节数组(每字节一个通道)。我该怎么做?
解决方法
简单的方法是使用 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,image.getWidth(),image.getHeight(),null,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() * 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,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,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
开始,无论图像的 ARGB
是什么,它都会返回 ColorModel
值 - 检查其 documentation。
然后使用 ColorModel
的 default 实例来获取组件 (getRed()
,getGreen()
,...) 或获取 {{1} }} 组件数组(例如int
)。或者只是分割getComponents()
返回的值,格式在getRGB()
中描述。
最终可以将图像(或其栅格数据)转换为TYPE_4BYTE_ABGR,因此可以直接使用栅格数据(只是猜测,我从未做过)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。