参考博文:
http://blog.csdn.net/kobejayandy/article/details/44346809
http://blog.csdn.net/shixing_11/article/details/6897871
http://blog.csdn.net/cuihailiang/article/details/52037389
问题现象:
Java上传图片时,对某些图片进行缩放、裁剪或者生成缩略图时会蒙上一层红色,经过检查只要经过ImageIO.read()方法读取后再保存,该图片便已经变成红图。因此,可以推测直接原因在于ImageIO.read()方法加载图片的过程存在问题。
1 public static BufferedImage getImages(byte[] data) throws IOException { 2 ByteArrayInputStream input = new ByteArrayInputStream(data); 3 return ImageIO.read(input); 4 }
经过查阅得知ImageIO.read()方法读取图片时可能存在不正确处理图片ICC信息的问题,ICC为JPEG图片格式中的一种头部信息,导致渲染图片前景色时蒙上一层红色。
解决方案:
1、使用awt Toolkit
不再使用ImageIO.read()方法加载图片,而使用JDK中提供的Image src=Toolkit.getDefaultToolkit().getImage
Image src = Toolkit.getDefaultToolkit().getImage(file.getPath()); BufferedImage image = BufferedImageBuilder.toBufferedImage(src);//Image to BufferedImage
或者Toolkit.getDefaultToolkit().createImage
1 Image imageTookit = Toolkit.getDefaultToolkit().createImage(bytes); 2 BufferedImage cutImage = BufferedImageBuilder.toBufferedImage(imageTookit);
BufferedImageBuilder源码:
public static BufferedImage toBufferedImage(Image image) { if (image instanceof BufferedImage) { return (BufferedImage) image; } // This code ensures that all the pixels in the image are loaded image = new ImageIcon(image).getImage(); BufferedImage bimage = null; GraphicsEnvironment ge = GraphicsEnvironment .getLocalGraphicsEnvironment(); try { int transparency = Transparency.OPAQUE; GraphicsDevice gs = ge.getDefaultScreenDevice(); GraphicsConfiguration gc = gs.getDefaultConfiguration(); bimage = gc.createCompatibleImage(image.getWidth(null), image.getHeight(null), transparency); } catch (HeadlessException e) { // The system does not have a screen } if (bimage == null) { // Create a buffered image using the default color model int type = BufferedImage.TYPE_INT_RGB; bimage = new BufferedImage(image.getWidth(null), image.getHeight(null), type); } // Copy image to buffered image Graphics g = bimage.createGraphics(); // Paint the image onto the buffered image g.drawImage(image, 0, 0, null); g.dispose(); return bimage; }
如果该方法在Windows平台下使用正常,而在Linux平台上总是报异常,这种解决方式可以参考:http://blog.csdn.net/shixing_11/article/details/6897871/
2、使用阿里巴巴的SImpleImage
主要依赖以下jar包:commons-io-2.4.jar、commons-lang.jar、commons-logging-1.1.1.jar、jai_codec-1.1.3.jar、jai_core-1.1.3.jar
SimpleImage github地址:相关jar包下载:测试代码:
1 package com.sup.test; 2 3 import java.io.File; 4 import java.io.FileInputStream; 5 import java.io.FileOutputStream; 6 7 import org.apache.commons.io.IOUtils; 8 9 import com.alibaba.simpleimage.ImageRender;10 import com.alibaba.simpleimage.SimpleImageException;11 import com.alibaba.simpleimage.render.ReadRender;12 import com.alibaba.simpleimage.render.ScaleParameter;13 import com.alibaba.simpleimage.render.ScaleRender;14 import com.alibaba.simpleimage.render.WriteRender;15 16 public class Example {17 18 public static void compressPicAlibaba (String srcFilePath, String descFilePath) {19 File in = new File(srcFilePath); //原图片 20 File out = new File(descFilePath); //目的图片 21 ScaleParameter scaleParam = new ScaleParameter();22 23 FileInputStream inStream = null; 24 FileOutputStream outStream = null; 25 WriteRender wr = null; 26 try { 27 inStream = new FileInputStream(in); 28 outStream = new FileOutputStream(out); 29 ImageRender rr = new ReadRender(inStream); 30 ImageRender sr = new ScaleRender(rr, scaleParam); 31 wr = new WriteRender(sr, outStream); 32 33 wr.render(); //触发图像处理 34 } catch(Exception e) { 35 e.printStackTrace(); 36 } finally { 37 IOUtils.closeQuietly(inStream); //图片文件输入输出流必须记得关闭 38 IOUtils.closeQuietly(outStream); 39 if (wr != null) { 40 try { 41 wr.dispose(); //释放simpleImage的内部资源 42 } catch (SimpleImageException ignore) { 43 // skip ... 44 } 45 } 46 } 47 }48 49 public static void main(String[] args) {50 51 String srcFilePath = "F:\\qw.jpg";52 String descFilePath = "F:\\qw2.jpg";53 compressPicAlibaba(srcFilePath, descFilePath);54 55 }56 57 }