소스 검색

图片压缩工具类

xiari 10 달 전
부모
커밋
e5e935a892
1개의 변경된 파일175개의 추가작업 그리고 0개의 파일을 삭제
  1. 175 0
      ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/file/PicCompressor.java

+ 175 - 0
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/file/PicCompressor.java

@@ -0,0 +1,175 @@
+package org.dromara.common.core.utils.file;
+
+import cn.hutool.core.io.FileUtil;
+import net.coobird.thumbnailator.Thumbnails;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.*;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public class PicCompressor {
+    //以下是常量,按照阿里代码开发规范,不允许代码中出现魔法值
+    private static final Logger logger = LoggerFactory.getLogger(PicCompressor.class);
+    private static final Integer ZERO = 0;
+    private static final Integer ONE_ZERO_TWO_FOUR = 1024;
+    private static final Integer NINE_ZERO_ZERO = 900;
+    private static final Integer THREE_TWO_SEVEN_FIVE = 3275;
+    private static final Integer TWO_ZERO_FOUR_SEVEN = 2047;
+    private static final Double ZERO_NINE = 0.9;
+    private static final Double ZERO_SIX = 0.6;
+    private static final Double ZERO_FOUR_FOUR = 0.44;
+    private static final Double ZERO_FOUR = 0.4;
+
+    /**
+     * 根据指定大小压缩图片
+     *
+     * @param imageBytes  源图片字节数组
+     * @param desFileSize 指定图片大小,单位kb
+     * @return 压缩质量后的图片字节数组
+     */
+    public static byte[] compressPicForScale(byte[] imageBytes, long desFileSize) {
+        if (imageBytes == null || imageBytes.length <= ZERO || imageBytes.length < desFileSize * ONE_ZERO_TWO_FOUR) {
+            return imageBytes;
+        }
+        long srcSize = imageBytes.length;
+        double accuracy = getAccuracy(srcSize / ONE_ZERO_TWO_FOUR);
+        ByteArrayInputStream inputStream = null;
+        ByteArrayOutputStream outputStream = null;
+        try {
+            while (imageBytes.length > desFileSize * ONE_ZERO_TWO_FOUR) {
+                inputStream = new ByteArrayInputStream(imageBytes);
+                outputStream = new ByteArrayOutputStream(imageBytes.length);
+                Thumbnails.of(inputStream)
+                    // 缩放比例
+                    .scale(accuracy)
+                    // 图片质量
+                    .outputQuality(accuracy)
+                    .toOutputStream(outputStream);
+                imageBytes = outputStream.toByteArray();
+                accuracy = getAccuracy(imageBytes.length/ONE_ZERO_TWO_FOUR);
+            }
+            logger.info("图片原大小={}kb | 压缩后大小={}kb",
+                srcSize / ONE_ZERO_TWO_FOUR, imageBytes.length / ONE_ZERO_TWO_FOUR);
+        } catch (Exception e) {
+            logger.error("【图片压缩】msg=图片压缩失败!", e);
+        }finally {
+            closeStream(inputStream, outputStream);
+        }
+        return imageBytes;
+    }
+
+    static void closeStream(ByteArrayInputStream inputStream, ByteArrayOutputStream outputStream) {
+        if(inputStream != null){
+            try {
+                inputStream.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+        if(outputStream != null){
+            try {
+                outputStream.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    /**
+     * 自动调节精度(经验数值)
+     *
+     * @param size 源图片大小
+     * @return 图片压缩质量比
+     */
+    private static double getAccuracy(long size) {
+        double accuracy;
+        if (size < ONE_ZERO_TWO_FOUR) {
+            accuracy = ZERO_NINE;
+        } else if (size < TWO_ZERO_FOUR_SEVEN) {
+            accuracy = ZERO_SIX;
+        } else if (size < THREE_TWO_SEVEN_FIVE) {
+            accuracy = ZERO_FOUR_FOUR;
+        } else {
+            accuracy = ZERO_FOUR;
+        }
+        return accuracy;
+    }
+
+
+
+    public static void main(String[] args) throws IOException {
+       /* File file = new File("C:\\Users\\LENOVO\\Downloads\\avatar-photo\\avatar\\StuBaseinfo\\20200930\\2020022004.JPG");
+        // 获取file的 bytes数组
+        byte[] bytes = FileUtil.readBytes(file);
+        //压缩图片到指定200K以内,不管你的图片有多少兆,都不会超过200kb,精度还算可以,不会模糊
+        byte[] compressed = compressPicForScale(bytes, 200);
+        //生成保存在服务器的图片名称,统一修改原后缀名为:jpg
+        String newFileName = "2020022004" + ".jpg";
+        File fOut = new File("C:\\Users\\LENOVO\\Desktop\\" + newFileName);
+        FileOutputStream fileOutputStream = new FileOutputStream(fOut);
+        fileOutputStream.write(compressed);
+        fileOutputStream.close();*/
+
+        tempCompress();
+
+    }
+
+
+    public static void tempCompress() throws IOException {
+//        String SOURCE_DIR = "C:\\Users\\LENOVO\\Downloads\\avatar-photo";
+//        String TARGET_DIR = "C:\\Users\\LENOVO\\Downloads\\avatar-photo-copy";
+        String SOURCE_DIR = "C:\\Users\\LENOVO\\Desktop\\test-photo";
+        String TARGET_DIR = "C:\\Users\\LENOVO\\Desktop\\test-photo-copy";
+        Path sourcePath = Paths.get(SOURCE_DIR);
+        Path targetPath = Paths.get(TARGET_DIR);
+
+        // 创建目标目录
+        Files.createDirectories(targetPath);
+
+        // 遍历源目录中的所有文件
+        Files.walk(sourcePath)
+            .filter(Files::isRegularFile)
+            .filter(path -> isImageFile(path.toString()))
+            .forEach(sourceFile -> {
+                try {
+                    Path relativePath = sourcePath.relativize(sourceFile);
+                    Path targetFile = targetPath.resolve(relativePath);
+
+                    // 创建目标文件的父目录
+                    Files.createDirectories(targetFile.getParent());
+
+                    File sfile = sourceFile.toFile();
+                    // 获取file的 bytes数组
+                    byte[] sbytes = FileUtil.readBytes(sfile);
+                    if(sbytes.length <= 200*1024){
+                        Files.copy(sourceFile, targetFile);
+                        logger.info("图片大小小于200KB,不进行压缩");
+                    }else{
+                        //压缩图片到指定200K以内,不管你的图片有多少兆,都不会超过200kb,精度还算可以,不会模糊
+                        byte[] compressed = compressPicForScale(sbytes, 200);
+
+                        FileOutputStream fileOutputStream = new FileOutputStream(targetFile.toFile());
+                        fileOutputStream.write(compressed);
+                        fileOutputStream.close();
+
+                        System.out.println("已处理: " + relativePath + " (" + sourceFile.toFile().length()/1024 + "KB -> " + targetFile.toFile().length()/1024 + "KB)");
+                    }
+                } catch (IOException e) {
+                    System.err.println("处理文件失败: " + sourceFile + " - " + e.getMessage());
+                }
+            });
+
+    }
+
+    private static boolean isImageFile(String fileName) {
+        String lowerFileName = fileName.toLowerCase();
+        return lowerFileName.endsWith(".jpg") || lowerFileName.endsWith(".jpeg") ||
+            lowerFileName.endsWith(".png") || lowerFileName.endsWith(".bmp") ||
+            lowerFileName.endsWith(".gif") || lowerFileName.endsWith(".webp");
+    }
+
+
+}