mzy520

最近遇到自拍上传图片过大问题,很烦恼,所以自己写了一个压缩图片的工具类使用,自测效果很不错,可以压缩到KB以内,像素还可以分辨清晰

下面Java代码奉上:

 

  1 import lombok.extern.slf4j.Slf4j;
  2 import org.w3c.dom.Element;
  3 
  4 
  5 import javax.imageio.IIOImage;
  6 import javax.imageio.ImageIO;
  7 import javax.imageio.ImageTypeSpecifier;
  8 import javax.imageio.ImageWriter;
  9 import javax.imageio.metadata.IIOMetadata;
 10 import javax.imageio.plugins.jpeg.JPEGImageWriteParam;
 11 import javax.imageio.stream.ImageOutputStream;
 12 import java.awt.*;
 13 import java.awt.image.BufferedImage;
 14 import java.io.*;
 15 import java.net.HttpURLConnection;
 16 import java.net.URL;
 17 
 18 
 19 /**
 20  * @Author: Mr. Chang
 21  */
 22 @Slf4j
 23 public class ImageZipUtils {
 24 
 25     /**
 26      * 采用指定宽度、高度或压缩比例 的方式对图片进行压缩
 27      *
 28      * @param imgsrc     源图片地址
 29      * @param imgdist    目标图片地址
 30      * @param widthdist  压缩后图片宽度(当rate==null时,必传)
 31      * @param heightdist 压缩后图片高度(当rate==null时,必传)
 32      * @param rate       压缩比例
 33      */
 34     public static void reduceImg(String imgsrc, String imgdist, int widthdist,
 35                                  int heightdist, Float rate) {
 36         try {
 37             File srcfile = new File(imgsrc);
 38             // 检查文件是否存在
 39             if (!srcfile.exists()) {
 40                 return;
 41             }
 42             // 如果rate不为空说明是按比例压缩
 43             if (rate != null && rate > 0) {
 44                 // 获取文件高度和宽度
 45                 int[] results = getImgWidth(srcfile);
 46                 if (results == null || results[0] == 0 || results[1] == 0) {
 47                     return;
 48                 } else {
 49                     widthdist = (int) (results[0] * rate);
 50                     heightdist = (int) (results[1] * rate);
 51                 }
 52             }
 53             // 开始读取文件并进行压缩
 54             Image src = javax.imageio.ImageIO.read(srcfile);
 55             BufferedImage tag = new BufferedImage((int) widthdist,
 56                     (int) heightdist, BufferedImage.TYPE_INT_RGB);
 57 
 58             tag.getGraphics().drawImage(
 59                     src.getScaledInstance(widthdist, heightdist,
 60                             Image.SCALE_SMOOTH), 0, 0, null);
 61 
 62             FileOutputStream out = new FileOutputStream(imgdist);
 63 //            JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
 64 //            encoder.encode(tag);
 65 //            out.close();
 66             float per = (float) 0.85;
 67             saveAsJPEG(100, tag, per, out);
 68 
 69         } catch (IOException ex) {
 70             ex.printStackTrace();
 71         }
 72     }
 73 
 74     /**
 75      * 以JPEG编码保存图片
 76      *
 77      * @param dpi             分辨率
 78      * @param image_to_save   要处理的图像图片
 79      * @param JPEGcompression 压缩比
 80      * @param fos             文件输出流
 81      * @throws IOException
 82      */
 83     public static void saveAsJPEG(Integer dpi, BufferedImage image_to_save, float JPEGcompression, FileOutputStream fos) throws IOException {
 84         // Image writer
 85         ImageWriter imageWriter = ImageIO.getImageWritersBySuffix("jpg").next();
 86         ImageOutputStream ios = ImageIO.createImageOutputStream(fos);
 87         imageWriter.setOutput(ios);
 88         //and metadata
 89         IIOMetadata imageMetaData = imageWriter.getDefaultImageMetadata(new ImageTypeSpecifier(image_to_save), null);
 90 
 91 
 92         if (dpi != null && !dpi.equals("")) {
 93 
 94             //new metadata
 95             Element tree = (Element) imageMetaData.getAsTree("javax_imageio_jpeg_image_1.0");
 96             Element jfif = (Element) tree.getElementsByTagName("app0JFIF").item(0);
 97             jfif.setAttribute("Xdensity", Integer.toString(dpi));
 98             jfif.setAttribute("Ydensity", Integer.toString(dpi));
 99 
100         }
101 
102 
103         if (JPEGcompression >= 0 && JPEGcompression <= 1f) {
104             // new Compression
105             JPEGImageWriteParam jpegParams = (JPEGImageWriteParam) imageWriter.getDefaultWriteParam();
106             jpegParams.setCompressionMode(JPEGImageWriteParam.MODE_EXPLICIT);
107             jpegParams.setCompressionQuality(JPEGcompression);
108 
109         }
110 
111         //new Write and clean up
112         imageWriter.write(imageMetaData, new IIOImage(image_to_save, null, null), null);
113         ios.close();
114         imageWriter.dispose();
115 
116     }
117 
118 
119     /**
120      * 获取图片宽度
121      *
122      * @param file 图片文件
123      * @return 宽度
124      */
125     public static int[] getImgWidth(File file) {
126         InputStream is = null;
127         BufferedImage src = null;
128         int result[] = {0, 0};
129         try {
130             is = new FileInputStream(file);
131             src = javax.imageio.ImageIO.read(is);
132             result[0] = src.getWidth(null); // 得到源图宽
133             result[1] = src.getHeight(null); // 得到源图高
134             is.close();
135         } catch (Exception e) {
136             e.printStackTrace();
137         }
138         return result;
139     }
140 
141     public static byte[] readInputStream(InputStream inStream) throws Exception {
142         ByteArrayOutputStream outStream = new ByteArrayOutputStream();
143         //创建一个Buffer字符串
144         byte[] buffer = new byte[1024];
145         //每次读取的字符串长度,如果为-1,代表全部读取完毕
146         int len = 0;
147         //使用一个输入流从buffer里把数据读取出来
148         while ((len = inStream.read(buffer)) != -1) {
149             //用输出流往buffer里写入数据,中间参数代表从哪个位置开始读,len代表读取的长度
150             outStream.write(buffer, 0, len);
151         }
152         //关闭输入流
153         inStream.close();
154         //把outStream里的数据写入内存
155         return outStream.toByteArray();
156     }
157 
158     /**
159      * 保存自拍照片
160      * @param userId
161      * @param photo_url
162      * @param suffixFromUrl
163      * @param path
164      * @throws Exception
165      */
166     public static void saveZipImage(Integer userId, String photo_url, String suffixFromUrl, String path) throws Exception {
167 
168         //new一个URL对象
169         URL url = new URL(photo_url);
170         //打开链接
171         HttpURLConnection conn = (HttpURLConnection) url.openConnection();
172         //设置请求方式为"GET"
173         conn.setRequestMethod("GET");
174         //超时响应时间为5秒
175         conn.setConnectTimeout(5 * 1000);
176         //通过输入流获取图片数据
177         InputStream inStream = conn.getInputStream();
178         //得到图片的二进制数据,以二进制封装得到数据,具有通用性
179         byte[] data = readInputStream(inStream);
180         //new一个文件对象用来保存图片,默认保存当前工程根目录
181         File imageFile = new File(path + userId + suffixFromUrl);
182         //创建输出流
183         FileOutputStream outStream = new FileOutputStream(imageFile);
184         //写入数据
185         outStream.write(data);
186         //关闭输出流
187         outStream.close();
188 
189     }
190 
191     /**
192      * 开始压缩图片
193      * @param userId
194      * @param suffix
195      * @param path
196      * @return
197      */
198     public static String imageZipStart(Integer userId, String suffix, String path) {
199         /**
200          * d://3.jpg 源图片
201          * d://31.jpg 目标图片
202          * 压缩宽度和高度都是1000
203          *
204          */
205         String original = path + userId + suffix;
206         String target = path + userId + "target" + suffix;
207         File srcfile = new File(original);
208         log.info(userId + "用户自拍照压缩前自拍照大小:" + srcfile.length());
209         reduceImg(original, target, 888, 888, null);
210         File distfile = new File(target);
211         log.info("用户自拍照压缩后自拍照大小:" + distfile.length());
212         return target;
213     }
214 
215     /**
216      * 删除文件
217      */
218     public static void delFile(String fileName) {
219         File deFile = new File(fileName);
220         if (deFile.exists()) {
221             deFile.delete();
222         }
223     }
224 
225 }

 

如有更正,欢迎下方评论联系我,谢谢

 

分类:

技术点:

相关文章: