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: 在这里输入图像描述

The converted JPEG file has wrong colors. It's more grey than darker now. 图像结果

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.


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?


那这个呢?

public static void main(String[] args) throws Exception {
        Color fillColor = Color.BLUE; // just to verify
        BufferedImage bi = ImageIO.read(new File("c:temptGjhw.png"));
        BufferedImage bi2 = new BufferedImage(bi.getWidth(), bi.getHeight(),
              BufferedImage.TYPE_3BYTE_BGR);
        bi2.getGraphics().drawImage(bi, 0, 0, fillColor, null);
        // you can do a more complex saving to tune the compression  parameters
        ImageIO.write(bi2,"JPG",new File("c:temptGjhw2.jpg"));
    }

The too-light result appears to be due to a conversion from linear colorspace (gamma=1) to sRGB (gamma=1/2.2). The original doesn't contain any gamma information, so ImageMagick is free to choose its own default. Recent versions of ImageMagick handle grayscale images differently, some assuming linear and others assuming sRGB. From the commandline you'd use the "-gamma 1" option to get the darker result with all versions. You need to do the equivalent in Java.

链接地址: http://www.djcxy.com/p/20448.html

上一篇: Iptables将端口范围转发到另一主机上的另一个端口范围

下一篇: 如何使用JAVA将alpha转换为JPEG保存颜色