不变色的方法


          文件上传时,有的图片我们并不强求的图片质量,因为图片过大的话,会占用带宽以及存储空间。因此在上传图片的时候就要对图片进行压缩处理操作,经过百度,网上普遍有两种,一种是改变图片长宽,按比例或者设置长宽对图片进行缩小,另一种是不改变图片的宽高,改变图片的质量。

关于改变长宽的做法,网上大多数用到 com.sun.image.codec.jpeg这个包下的类,但这个类在java1.7以后就被删除了,而且在使用maven打包的时候会报com.sun.image.codec.jpeg不存在的问题。这个方法待研究。

以下是对改变图片质量的实现:

package com.cjn.util;
  
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import javax.imageio.IIOImage;
 import javax.imageio.ImageIO;
 import javax.imageio.ImageWriteParam;
 import javax.imageio.ImageWriter;
 import java.awt.image.BufferedImage;
 import java.awt.image.ColorModel;
 import java.io.*;
  
 /**
  * AUTHOR cjn
  * TIME  2018-4-16 11:08
  * REMARK 图片处理类 压缩图片大小
  */
 public class ImgUtil {
  
  
     static Logger logger = LoggerFactory.getLogger(ImgUtil.class);
  
     public static File compressPictureByQality(File file,float qality) throws IOException {
  
         BufferedImage src = null;
         FileOutputStream out = null;
         ImageWriter imgWrier;
         ImageWriteParam imgWriteParams;
         logger.debug("开始设定压缩图片参数");
         // 指定写图片的方式为 jpg
         imgWrier = ImageIO.getImageWritersByFormatName("jpg").next();
         imgWriteParams = new javax.imageio.plugins.jpeg.JPEGImageWriteParam(
                 null);
         // 要使用压缩,必须指定压缩方式为MODE_EXPLICIT
         imgWriteParams.setCompressionMode(imgWriteParams.MODE_EXPLICIT);
         // 这里指定压缩的程度,参数qality是取值0~1范围内,
         imgWriteParams.setCompressionQuality(qality);
         imgWriteParams.setProgressiveMode(imgWriteParams.MODE_DISABLED);
         ColorModel colorModel =ImageIO.read(file).getColorModel();// ColorModel.getRGBdefault();
         // 指定压缩时使用的色彩模式
 //        imgWriteParams.setDestinationType(new javax.imageio.ImageTypeSpecifier(
 //                colorModel, colorModel.createCompatibleSampleModel(16, 16)));
         imgWriteParams.setDestinationType(new javax.imageio.ImageTypeSpecifier(
                 colorModel, colorModel.createCompatibleSampleModel(16, 16)));
  
         logger.debug("结束设定压缩图片参数");
         if (!file.exists()) {
             logger.error("Not Found Img File,文件不存在");
             throw new FileNotFoundException("Not Found Img File,文件不存在");
         } else {
             logger.debug("图片转换前大小"+file.length()+"字节");
             src = ImageIO.read(file);
             out = new FileOutputStream(file);
  
             imgWrier.reset();
             // 必须先指定 out值,才能调用write方法, ImageOutputStream可以通过任何
             // OutputStream构造
             imgWrier.setOutput(ImageIO.createImageOutputStream(out));
             // 调用write方法,就可以向输入流写图片
             imgWrier.write(null, new IIOImage(src, null, null),
                     imgWriteParams);
             out.flush();
             out.close();
             logger.debug("图片转换后大小"+file.length()+"字节");
             return file;
         }
     }
 }


注意:这个方法对内存有一定的要求,如果处理图片过大的时候,可能会抛出 内存溢出 的异常问题。

对此的解决办法

1.可以加内存。(但不建议,因为用户传的图片有可能无限增大,而内存加到一定值就没办法了,因为这个办法可以为临时解决办法)

2.对于上传图片的入口进行拦截,在配置文件中配置文件上传的峰值,如果上传的文件大于这个峰值,就提示不能上传,要求传的图片大小降低。

3.优化压缩图片的代码。这个我目前就不知道了,以后有机会了来补充吧!