在Java中将预乘数据渲染为透明PNG文件

pgvzfuti  于 2023-02-14  发布在  Java
关注(0)|答案(1)|浏览(160)

长话短说,我有预乘纹理,我抓取一个FrameBuffer,用(0,0,0,0)清除它,设置混合模式为glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA),渲染纹理,然后我抓取像素glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, byteBufferPixels);并使用它:

BufferedImage screenshot = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
screenshot.setRGB(0, 0, width, height, argbInts, 0, width);
try {
    ImageIO.write(screenshot, "png", file);
} catch (IOException e) {
    e.printStackTrace();
}

我也试过BufferedImage.TYPE_INT_ARGB_PRE,没有任何变化。
结果是这样的:

如何在OpenGL中从预乘像素数据中得到一个漂亮的透明PNG文件?
谢谢!

erhoui1w

erhoui1w1#

BufferedImage.setRGB(...)的JavaDoc说明:
将默认RGB颜色模型(TYPE_INT_ARGB)和默认sRGB颜色空间中的整数像素数组设置为图像数据的一部分。
这意味着输入数据argbInts必须是 non-premultiplied form,不管目标图像类型是什么。当然,在将输入像素数据传递给setRGB方法之前,可以先将其解乘,但对于一个包含压缩int的数组来说,这有点繁琐,所以我将其留给读者作为练习......😉
相反,将图像更改为TYPE_INT_ARGB_PRE并直接使用原始预乘像素设置像素数据要容易得多,如下所示:

BufferedImage screenshot = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB_PRE);

// Safe cast for  TYPE_INT_*
int[] imageData = ((DataBufferInt) screenshot.getRaster().getDataBuffer()).getData(); 
System.arraycopy(argbInts, 0, imageData, 0, argbInts.length));

try {
    ImageIO.write(screenshot, "PNG", file);
} catch (IOException e) {
    e.printStackTrace();
}

相关问题