Question

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?

Was it helpful?

Solution

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

OTHER TIPS

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

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

I also found that reading a PNG image into a BufferedImage with ImageIO (Java 6) and writing it out to a JPG "format name" corrupted the image. The image was there, but the colors looked "solarized" and almost inverted. The JPG file was much smaller than the PNG file for sure, so a lot of compression was done. I don't see how you might control the compression or color depth.

I was getting the following message in a slightly different context. Getting rid of the alpha channel solved the problem

javax.imageio.IIOException: Sample size must be <= 8
    at com.sun.imageio.plugins.jpeg.JPEGImageWriter.write(JPEGImageWriter.java:435)
    at javax.imageio.ImageWriter.write(ImageWriter.java:580)
    at com.twelvemonkeys.imageio.plugins.jpeg.JPEGImageWriter.write(Unknown Source)
    at net.sf.basedb.util.ImageTools.tiffToJpg(ImageTools.java:98)
    at net.sf.basedb.util.ImageTools.main(ImageTools.java:118)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top