Leif Sabellek
Leif Sabellek

Reputation: 173

How to create BufferedImage with BITMASK Transparency?

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?

Upvotes: 0

Views: 1658

Answers (2)

Harald K
Harald K

Reputation: 27074

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

Upvotes: 1

MadProgrammer
MadProgrammer

Reputation: 347194

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...

Upvotes: 2

Related Questions