tags:

views:

509

answers:

4

I am trying to create a transparent PNG image from a BufferedImage in Java.

The PNG will be loaded into another piece of the software, that does not support the alpha channel.

That should be fine, because, according to Chapter 8, section 5, part 4 of the PNG book, I can achieve transparency by specifying a pixel value to be transparent. This works by creating a tRNS header in the png file.

I am unsure how to translate this technical detail to Java code. The actual image itself is monochrome; each pixel is going to be black or white. I would like to replace each white pixel with a transparent pixel, without using the alpha channel. May someone push me in the right direction please?

A: 

I don't know, but I'm sure the answer is in The png Specification. Hope this helps!

Isn't there a library for java for writing png files (java bindings for libpng perhaps?) that will do the hard work for you? (and probably save you many headaches when things don't quite work)

Autopulated
I appreciate your answer, but I am already aware of how this is handled in PNG images. I am not sure how to translate that to Java code. I think it has to do with the ColorModel of the BufferedImage, but I am not sure one bit (pun intended?). Sorry for any miscommunication.
A: 

I think youll want to use an IndexColorModel: http://java.sun.com/j2se/1.4.2/docs/api/java/awt/image/IndexColorModel.html.

prodigitalson
This confirms what I thought. I have been reading and re-reading that link for 2 days now.
Ok so if you already knew to use IndexColorModel and you were/are aware of the constructor arguments what specifically is the issue? You need to create the CM with the proper index passed in as the arg `trans`.
prodigitalson
I wasnt sure to use IndexColorModel, and even now, Im unsure how to use it. However, this link looks promising, http://mindprod.com/jgloss/indexcolormodel.html . Thanks for your confirmation, I'll accept as the answer.
Ahhh, ok that makes sense. Good luck implementing :-)
prodigitalson
A: 

Try the following:

  1. Find out the index of the first white pixel from the BufferedImage.
  2. Create an IndexColorModel with the desired parameters.
  3. Create a ColorConvertOp. You can pass null as the RenderingHints argument.
  4. Use [ColorConvertOp.createCompatibleDestImage][3] to receive a new BufferedImage instance (destination).
  5. Use [ColorConvertOp.filter][4] to perform the conversion from the source to the destination.

I'm not completely sure about this, but the ColorConvertOp seems like a good starting point. Tell us how it works out!

[3]: http://java.sun.com/javase/6/docs/api/java/awt/image/ColorConvertOp.html#createCompatibleDestImage%28java.awt.image.BufferedImage, java.awt.image.ColorModel) [4]: http://java.sun.com/javase/6/docs/api/java/awt/image/ColorConvertOp.html#filter%28java.awt.image.BufferedImage, java.awt.image.BufferedImage)

Eli Acherkan
+1  A: 

You can use the following code.

Create a monochrome and transparent BufferedImage:

public static BufferedImage createTransparentMonochromeBufferedImage(int w, int h)
{
    // The color map contains the colors black and white
    byte[] cMap = {0, 0, 0, (byte)255, (byte)255, (byte)255};
    // Create an IndexColorModel setting white as the transparent color
    IndexColorModel monochrome = new IndexColorModel(8, 2, cMap, 0, false, 1);
    // Return a new BufferedImage using that color model 
    return new BufferedImage(w, h, BufferedImage.TYPE_BYTE_INDEXED, monochrome);
}

Save the BufferedImage in a PNG file:

public static void saveBufferedImageAsPNG(BufferedImage img, String filename)
                                                             throws IOException{
    File file = new File(filename); 
    ImageIO.write(img, "png", file);
}
Alexandre Jasmin
Perfect. I found the Java API docs to be rather lacking for this class. Maybe I am just a noob.