Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert PNG with alpha to JPEG conserving colors using JAVA

I'm having some trouble in converting a PNG with Alpha to JPEG from Wiki.

This is the image: http://upload.wikimedia.org/wikipedia/commons/thumb/e/ee/Radio_SRF_3.svg/500px-Radio_SRF_3.svg.png

Original: enter image description here

The converted JPEG file has wrong colors. It's more grey than darker now. image result

This is how I do the conversion:

Remove alpha:

public static BufferedImage imageFillAlphaWithColor(BufferedImage image, Color fillColor) {
    if (image.getColorModel().getTransparency() == Transparency.OPAQUE) return image;

    int w = image.getWidth();
    int h = image.getHeight();
    BufferedImage newImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
    Graphics2D g = newImage.createGraphics();
    g.drawImage(image, 0, 0, fillColor, null);
    g.dispose();

    return newImage;
}

Jpeg compression:

public static byte[] compressedJpegImage(BufferedImage image, float quality) {
        byte jpegImage[] = null;
        try {
            // Find a jpeg writer
            ImageWriter writer = null;
            Iterator<ImageWriter> iter = ImageIO.getImageWritersByFormatName("jpg");
            if (iter.hasNext()) {
                writer = (ImageWriter) iter.next();
            }

            // Prepare output
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            ImageOutputStream ios = ImageIO.createImageOutputStream(os);
            writer.setOutput(ios);

            // Set the compression quality
            ImageWriteParam iwparam = writer.getDefaultWriteParam();
            iwparam.setProgressiveMode(ImageWriteParam.MODE_DEFAULT);
            iwparam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
            iwparam.setCompressionQuality(quality);

            // Write the image
            writer.write(null, new IIOImage(image, null, null), iwparam);

            // Cleanup
            ios.flush();
            writer.dispose();
            ios.close();

            jpegImage = os.toByteArray();

        } catch (IOException e) {
            e.printStackTrace();
        }

        return jpegImage;
    }

And store it to JPEG via ImageIO.

Any idea how to preserve the color space to keep the colors like they are in the original?

UPDATE

Issue was caused by ImageMagick when resized. Seems like ImageMagick did change the color space to TYPE_CUSTOM and Java is not able to handle that.

Current solution:

Remove alpha just before I start resizing the image via ImageMagick.

Still haven't found a solution to convert the color space from "CUSTOM" back to "ARGB". So this is just a "workaround" for this issue.

like image 645
Arny Avatar asked May 14 '14 12:05

Arny


1 Answers

You aren't actually removing the alpha values. Java divides the color values by the alpha when you do what you did in the imageFillAlphaWithColor method.

I recommend using the AlphaComposite class to actually remove the alpha.

Here's the Oracle tutorial on how to Composite Graphics: http://docs.oracle.com/javase/tutorial/2d/advanced/compositing.html

Without being able to test easily, I think what you need to do is this:

Graphics2D g = newImage.createGraphics();
g.setComposite(AlphaComposite.Src);
g.drawImage(image, 0, 0, fillColor, null);

If that doesn't work, read this related question: Change the alpha value of a BufferedImage?

like image 162
durron597 Avatar answered Oct 15 '22 06:10

durron597