最近遇到自拍上传图片过大问题,很烦恼,所以自己写了一个压缩图片的工具类使用,自测效果很不错,可以压缩到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 }
如有更正,欢迎下方评论联系我,谢谢
原文地址:https://www.cnblogs.com/mzy520/p/11934565.html
时间: 2024-10-20 18:21:02