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