0

Long story short I have premultiplied Texture. I grab a FrameBuffer, clear it with (0,0,0,0), set the blend mode to glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA), and render the Texture. Then I grab the pixels glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, byteBufferPixels); and use that:

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();
}

I also have tried BufferedImage.TYPE_INT_ARGB_PRE with no change.

The result is this:

enter image description here

How do I get a nice transparent PNG file out of premultiplied pixel data in OpenGL?

Thanks!

yesbutmaybeno
  • 1,078
  • 13
  • 31
  • I think the problem is that `setRGB` expects the input to be in non-premultiplied form regardless of the destination image type. So you need to un-multiply the pixels. – Harald K Feb 13 '23 at 08:40

1 Answers1

1

The JavaDoc for BufferedImage.setRGB(...) says:

Sets an array of integer pixels in the default RGB color model (TYPE_INT_ARGB) and default sRGB color space, into a portion of the image data.

This means that your input data argbInts needs to be in non-premultiplied form, regardless of the destination image type. It's of course possible to un-multiply the input pixel data before passing it to the setRGB method, but it's a bit tedious for an array with packed ints, so I leave that as an exercise for the reader...

Instead, it is much easier to just change the image to TYPE_INT_ARGB_PRE and set the pixel data directly with the original premultiplied pixels, like this:

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();
}
Harald K
  • 26,314
  • 7
  • 65
  • 111