最近遇到自拍上傳圖片過大問題,很煩惱,因此本身寫了一個壓縮圖片的工具類使用,自測效果很不錯,能夠壓縮到KB之內,像素還能夠分辨清晰java
下面Java代碼奉上:ios
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 }
若有更正,歡迎下方評論聯繫我,謝謝app