首页 > 解决方案 > 使用 Graphics2D 绘制 TYPE_INT_ARGB_PRE 类型的 BufferedImage 时遇到问题

问题描述

在我的程序中,我得到了预乘 ARGB 格式的图像数据。我正在执行以下操作来创建 BufferedImage,将其绘制到画布上,然后将其渲染为 PNG 图像,但生成的图像颜色错误:

    IntBuffer imageData = ....;
    BufferedImage renderedFrame = createBufferedImage(surface.getWidth(), surface.getHeight(), imageData);
    DataBufferInt rasterData = (DataBufferInt)renderedFrame.getData().getDataBuffer();
    imageData.get(rasterData.getData());
    ImageIO.write(renderedFrame, "PNG", new File("/tmp/renderedFrame.png")); // the image is rendered, but the colors are all off

    final BufferedImage canvasImage = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
    final Graphics2D g = canvasImage.createGraphics();
    g.setColor(Color.WHITE);
    g.fillRect(0, 0, surface.getWidth(), surface.getHeight());
    g.setComposite(AlphaComposite.SrcOver);
    g.drawImage(renderedFrame, 0, 0, width, height, null, null);
    ImageIO.write(canvasImage, "PNG", new File("/tmp/canvasImage.png")); // the image is rendered, but the colors are all off

我已经验证图像数据是正确的,它来自 rlottie ( https://github.com/Samsung/rlottie )。我只需要将它合成到另一个图像上。

对于createBufferedImageDirectDataBufferInt从 jogl 库中使用的第一种方法:https ://github.com/JogAmp/jogl/blob/master/src/nativewindow/classes/com/jogamp/nativewindow/awt/DirectDataBufferInt.java以便图像DataBuffer 由 NIO 缓冲区支持。下面是createBufferedImage方法的内容:

private BufferedImage createBufferedImage(int width, int height, ByteBuffer buffer) {
    DirectDataBufferInt intBuffer = new DirectDataBufferInt(buffer, width * height);
    return DirectDataBufferInt.createBufferedImage(width, height, intBuffer, BufferedImage.TYPE_INT_ARGB_PRE, null, null);
}

这是在白色背景上渲染的源图像:

sampleImageRenderedElsewhere.jpg

这是渲染的帧(renderedFrame.png):

渲染帧.png

这是我用上面的代码()渲染它时的样子canvasImage.png

画布图像.png

它们看起来一样,但事实并非如此。透明canvasImage.png时有白色背景。renderedFrame.png

标签: javaimagegraphics2dlottie

解决方案


所以这是我的错。由于我从未验证传入的格式,我最终让自己陷入了一场追逐。基本上,rlottie 文档说的是ARGB32_Premultiplied格式。但是字节被存储(按出现顺序):BGRA。所以我基本上是在混淆我的频道。我猜是因为他们使用 uint32 作为缓冲区,我应该意识到这一点?无论如何 - 问题解决了。感谢大家的帮助。


推荐阅读