views:

430

answers:

3

Hi there,

I'm having problems converting a simple PNG into a JPEG format. I'm using the following code:

...

    File png = new File(filePath);
    try {
        SeekableStream s = new FileSeekableStream(png);
        PNGDecodeParam pngParams = new PNGDecodeParam();
        ImageDecoder dec = ImageCodec.createImageDecoder("png", s, pngParams);
        RenderedImage pngImage = dec.decodeAsRenderedImage();
        JPEGEncodeParam jparam = new JPEGEncodeParam();
        jparam.setQuality(0.50f); // e.g. 0.25f
        File jpeg = new File("jpeg.jpeg");
        FileOutputStream out = new FileOutputStream(jpeg);

        ImageEncoder encoder = ImageCodec.createImageEncoder("JPEG", out, jparam); 

        encoder.encode(pngImage);

        s.close();

    } catch (IOException e) {
        ok = false;
        e.printStackTrace();
    }

    return ok;
}

...

I end up with an JAI exception -> java.lang.RuntimeException: Only 1, or 3-band byte data may be written. at com.sun.media.jai.codecimpl.JPEGImageEncoder.encode(JPEGImageEncoder.java:148) ...

Ran out of options. Any suggestion?

+3  A: 

It might be easier to use ImageIO to read the PNG into a BufferedImage and write the image out in JPEG format.

Addendum: In this approach, the conversion is handled transparently by the writer's ImageTranscoder.

BufferedImage img = ImageIO.read(new File("image.png"));
ImageIO.write(img, "jpg", new File("image.jpg"));
trashgod
I guess the your solution is the same as the above suggested. It also works.
Norberto
`ImageIO`'s read/write conversion is implicit; the conversion in Trevor Harrison's example is informatively explicit.
trashgod
+1 quite cool technique
stacker
+1  A: 

I suppse that JAI reads the PNG image with an indexed colour model and is only able to write 8-bit grayscale or 24-bit colour images as JPEG files.

If you are not required to use JAI for this task, you should be able to use ImageIO instead:

ImageIO.write(ImageIO.read(new File("in.png")), "JPEG", new File("out.jpg"));
jarnbjo
I've tried this before and it doesn't work.
Norberto
+1 @Norberto: Can you elaborate? Looking closer, this is similar to what I've used before.
trashgod
The above implementation doesn't perform as expected. I'm not implying that this does not work at all. In my case (images that I'm working with) this doesn't work. Fails to create the expected file and the output is a false value. Apparently it can't find any suitable writer for the JPEG. I find it rather strange but I have no time to try to figure out why exactly it isn't working. I'm going to have closer look in the future but for know I'm keeping with what works.
Norberto
If "JPEG" doesn't work, try with "jpg" ...
Photodeus
+3  A: 

you probably have alpha channel in the png that you need to get rid of before trying to write the jpg.

Create a new BufferedImage with type TYPE_INT_RGB (not TYPE_INT_ARGB), and then write your source image (pngImage) onto the new blank image.

Something like this (warning, not tested code):

BufferedImage newImage = new BufferedImage( pngImage.getWidth(), pngImage.getHeight(), BufferedImage.TYPE_INT_RGB);
newImage.createGraphics().drawImage( pngImage, 0, 0, Color.BLACK, null);
Trevor Harrison
Elegant solution. It worked perfectly for me.
Norberto