0

The BufferedImage class implements Transparency, which has three values:

OPAQUE means no transparency.

TRANSLUCENT means every pixel has an Alpha value between 0 and 1.

BITMASK means every pixel is either opaque or completely transparent.

I can check this value with the getTransparency() method. In my case, I have a PNG file with transparency:

pic = ImageIO.read(new File(filename));
int transparency = pic.getTransparency(); // returns Transparency.TRANSLUCENT

Now I read that images with Transparency.BITMASK can be drawn much faster than those with Transparency.TRANSLUCENT and in my case BITMASK would be enough. I would just color all transparent pixels in one specific color and then save the png without transparency.

Question: How to create a BufferedImage object, which has Transparency.BITMASK from an existing BufferedImage by just defining one color as transparent?

Leif Sabellek
  • 173
  • 1
  • 9

2 Answers2

2

You mean something like...

// Create the buffered image
GraphicsDevice gs = ge.getDefaultScreenDevice();
GraphicsConfiguration gc = gs.getDefaultConfiguration();

BufferedImage bimage = gc.createCompatibleImage(width, height, Transparency.BITMASK);

Things to note:

  • If you're PNG contains alpha values > 0 and < 255, they are likely to be rounded to either 0 or 1, possibly making the PNG appear jagged...
  • If you use Transparency.TRANSLUCENT instead, the color mode of the BufferedImage will be compatible with the GraphicsDevice, making it faster to render

I did an animated sequence a few years ago which was made up of 5 separate images, layered on top of each other and played back at separate speeds all on top of a transparent window...When I first tried running it the, the playback was terrible and jumped about the place.

After some playing around, I found that using Transparency.TRANSLUCENT to convert the images to a compatible color model for the GraphicsDevice worked like a charm...

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Ok, and how to paint a png on this BufferedImage, such that a specific color will be transparent? – Leif Sabellek Nov 30 '14 at 21:02
  • You use `bimage.createGraphics()` to create a `Graphics2D` instance and paint the `png` image to it, disposing of the `Graphics2D` instance when you are done... – MadProgrammer Nov 30 '14 at 21:03
  • I know how to draw on a BufferedImage in general. My question was referring more to deciding the transparency color. If I just paint the png on it, it wont have any transparent pixels yet, since the png does not have transparency. For example, all pixels with color #ff00ff should become the transparent pixels. How to do that? – Leif Sabellek Nov 30 '14 at 21:08
  • That's kind of the point, you don't. The API is likely to round the alpha to either 0 or 1... – MadProgrammer Nov 30 '14 at 21:24
  • Oh, that's great, I didn't expect it to work like this. Thank you very much! – Leif Sabellek Nov 30 '14 at 21:35
1

Nothing wrong with the accepted answer, just providing an alternative for completeness (and I think it will work in headless mode). :-)

The transparency of a BufferedImage is controlled by its ColorModel.

So to create a BufferedImage with a given Transparency constant, you can use code like this:

// Use default RGB color space, no discrete alpha channel, 
ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
ColorModel colorModel = new ComponentColorModel(cs, true, false, Transparency.BITMASK, DataBuffer.TYPE_BYTE);

WritableRaster raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, w, h, 4, null);

BufferedImage image = new BufferedImage(colorModel, raster, colorModel.isAlphaPremultiplied(), null);
Harald K
  • 26,314
  • 7
  • 65
  • 111