说明:以下压缩图片的方式,可以指定压缩的大小,比如指定压缩到 512kb 以下,并且能保留原始图片尺寸大小不变,改变的是图片的质量、清晰度

引入的依赖

<dependency>
     <groupId>net.coobird</groupId>
     <artifactId>thumbnailator</artifactId>
     <version>0.4.17</version>
 </dependency>

实现的工具类

package com.yuhuofei.utils;

import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;

import java.io.*;
import java.util.Objects;

/**
 * @Description 保留图片尺寸大小,通过压缩图片质量的方式压缩图片大小
 * @ClassName PictureUtils
 * @Author yuhuofei
 * @Date 2022/7/29 22:42
 * @Version 1.0
 */
@Slf4j
public class PictureUtils {

    /**
     * 利用递归方式,不断检索多层文件夹中的图片,并压缩
     *
     * @param sourceFolderPath 文件夹路径
     */
    public static void checkFolder(String sourceFolderPath) {

        File sourceFolder = new File(sourceFolderPath);
        String[] sourceFilePathList = sourceFolder.list();
        String tempFileString;
        if (null != sourceFilePathList) {
            for (String filePath : sourceFilePathList) {
                tempFileString = sourceFolderPath + "/" + filePath;
                File currentFile = new File(tempFileString);
                //递归检索
                if (currentFile.isDirectory()) {
                    log.info("当前处理文件夹:{}", tempFileString);
                    checkFolder(tempFileString);
                }
                //如果是.jpg图片或者.JPG图片,调用压缩方法压缩处理
                if (currentFile.isFile() && (filePath.contains(".jpg") || filePath.contains(".JPG"))) {
                    compressPicForScale(Objects.requireNonNull(fileSwitchToByte(currentFile)), 512, tempFileString);
                }
            }
        }
    }

    /**
     * 根据指定大小压缩图片
     *
     * @param imageBytes     原图片字节数组大小
     * @param targetFileSize 要压缩的大小
     * @param picturePath    图片绝对路径
     */
    public static void compressPicForScale(byte[] imageBytes, long targetFileSize, String picturePath) {

        long srcSize = imageBytes.length;
        if (srcSize > targetFileSize * 1024) {
            log.info("当前压缩的图片是:{}", picturePath);
            File file = new File(picturePath);
            long tempSize = srcSize;
            double accuracy = getAccuracy(srcSize / 1024);
            try {
                while (tempSize > targetFileSize * 1024) {
                    ByteArrayInputStream inputStream = new ByteArrayInputStream(imageBytes);
                    FileOutputStream fileOutputStream = new FileOutputStream(file);
                    Thumbnails.of(inputStream)
                            .scale(accuracy)
                            .outputQuality(accuracy)
                            .toOutputStream(fileOutputStream);
                    tempSize = file.length();
                }
            } catch (Exception e) {
                log.error("====压缩图片失败====", e);
            }
        }
    }

    /**
     * 校准压缩精度
     *
     * @param size 源图片大小
     * @return 图片压缩质量比
     */
    private static double getAccuracy(long size) {
        double accuracy;
        if (size < 900) {
            accuracy = 0.85;
        } else if (size < 2047) {
            accuracy = 0.6;
        } else if (size < 3275) {
            accuracy = 0.44;
        } else {
            accuracy = 0.4;
        }
        return accuracy;
    }

    /**
     * 将文件对象转换为字节数组
     *
     * @param file 文件对象
     * @return byte[]
     */
    public static byte[] fileSwitchToByte(File file) {
        FileInputStream fileInputStream = null;
        ByteArrayOutputStream bs = null;
        try {
            fileInputStream = new FileInputStream(file);
            bs = new ByteArrayOutputStream();
            byte[] b = new byte[2048];
            int len;
            while ((len = fileInputStream.read(b)) != -1) {
                bs.write(b, 0, len);
            }
            return bs.toByteArray();
        } catch (IOException e) {
            log.error("字节数组转换失败" + e);
        } finally {
            try {
                if (fileInputStream != null) {
                    fileInputStream.close();
                }
                if (bs != null) {
                    bs.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    //测试方式
    public static void main(String[] args) {

        log.info("====开始检索文件夹中的图片,并压缩====");
        String folderPath = "C:/Users/yuhuofei/Desktop/data/材料";
        checkFolder(folderPath);
        log.info("====文件夹中的图片,压缩处理完成====");
    }
}

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐