如何使用JAVA将带有alpha的PNG转换为JPEG保存颜色

时间:2014-05-14 12:36:57

标签: java colors png jpeg alpha

我在使用Alpha将PNG转换为JPEG时遇到了一些麻烦。

这是图片:http://upload.wikimedia.org/wikipedia/commons/thumb/e/ee/Radio_SRF_3.svg/500px-Radio_SRF_3.svg.png

原件: enter image description here

转换后的JPEG文件颜色错误。它现在更灰暗而不是更暗。 image result

这是我进行转换的方式:

删除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压缩:

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

并通过ImageIO将其存储为JPEG格式。

知道如何保留色彩空间以保持原色中的色彩吗?

更新

问题是由ImageMagick调整大小时造成的。看起来像ImageMagick确实将颜色空间更改为TYPE_CUSTOM而Java无法处理。

目前的解决方案:

在我开始通过ImageMagick调整图像大小之前删除alpha。

仍然没有找到将色彩空间从“CUSTOM”转换回“ARGB”的解决方案。 所以这只是这个问题的“解决方法”。

3 个答案:

答案 0 :(得分:3)

您实际上并未移除Alpha值。当您执行imageFillAlphaWithColor方法中的操作时,Java会将颜色值除以alpha。

我建议使用AlphaComposite class来实际删除alpha。

这是关于如何使用复合图形的Oracle教程:http://docs.oracle.com/javase/tutorial/2d/advanced/compositing.html

如果不能轻松测试,我认为你需要做的是:

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

如果这不起作用,请阅读以下相关问题:Change the alpha value of a BufferedImage?

答案 1 :(得分:0)

这个怎么样?

public static void main(String[] args) throws Exception {
        Color fillColor = Color.BLUE; // just to verify
        BufferedImage bi = ImageIO.read(new File("c:\\temp\\tGjhw.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:\\temp\\tGjhw2.jpg"));
    }

答案 2 :(得分:0)

太亮的结果似乎是由于从线性色彩空间(gamma = 1)到sRGB(gamma = 1 / 2.2)的转换。原始版本不包含任何伽玛信息,因此ImageMagick可以自由选择自己的默认值。最近版本的ImageMagick处理灰度图像的方式不同,有些假设是线性的,而其他版本则假设为sRGB。从命令行,您可以使用&#34; -gamma 1&#34;选项以获得所有版本的更暗的结果。你需要在Java中做同等的事情。