[图像处理] 图片压缩(Java)

发布时间 2023-05-24 09:59:12作者: 千千寰宇

1 序言

调第三方平台,太贵。还得自己有,才是真。

2 Maven 依赖

<!--图片压缩-->
<!--https://repo1.maven.org/maven2/net/coobird/thumbnailator/-->
<!--Java使用Thumbnails实现图片指定大小压缩-CSDN-https://blog.csdn.net/qq_38530648/article/details/119333058-->
<dependency>
    <groupId>net.coobird</groupId>
    <artifactId>thumbnailator</artifactId>
    <version>0.4.8</version>
</dependency>

3 示例代码

//1.先转换成jpg
Thumbnails.of(srcPath) // File / URL / InputStream / BufferedImage /
	.scale(scale)
	.outputQuality(quality)
	.toFile(desPath);

import jdk.management.resource.ResourceType;
import net.coobird.thumbnailator.Thumbnails;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author johnny-zen
 * @version v1.0
 * @description ...
 * @refrence-doc
 *  [1] Java使用Thumbnails实现图片指定大小压缩 - CSDN - https://blog.csdn.net/qq_38530648/article/details/119333058
 * @gpt-promt
 */
public class ThumbnailUtil {
    private final static Logger logger = LoggerFactory.getLogger(ThumbnailUtil.class);

    /**
     * 根据指定大小和指定经度压缩图片
     *
     * @param srcPath     源图片地址
     * @param desPath     目标图片地址
     * @param desFileSize 指定图片大小,单位kb
     * @param scale    精度,递归压缩的比率,建议小于0.9
     * @return
     */
    public static String compressPictureForScale(String srcPath, String desPath, long desFileSize, double scale,double quality, int compressCount) {
        if (StringUtils.isEmpty(srcPath) || StringUtils.isEmpty(desPath)) {
            return null;
        }
        if (!new File(srcPath).exists()) {
            return null;
        }
        try {
            File srcFile = new File(srcPath);
            long srcFileSize = srcFile.length();
            logger.info(String.format("source file : %s, size : %d kb", srcPath, srcFileSize / 1024 ));
            //1.先转换成jpg
            Thumbnails.of(srcPath) // File / URL / InputStream / BufferedImage /
                .scale(scale)
                .outputQuality(quality)
                .toFile(desPath);
            //递归压缩,直到目标文件大小小于desFileSize
            //compressPicCycle(desPath, desFileSize, accuracy, compressCount);

            File desFile = new File(desPath);
            logger.info(String.format("Success to complete file compression ! | destination file : %s, size : %d kb", desPath, (int) (desFile.length() / 1024) ));
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return desPath;
    }

    private static void compressPicCycle(String desPath, long desFileSize, double accuracy, int compressCount) throws IOException {
        File srcFileJPG = new File(desPath);
        long srcFileSizeJPG = srcFileJPG.length();
        //2.判断大小,如果小于50kb,不用压缩,如果大于等于50kb,需要压缩
        if (srcFileSizeJPG <= desFileSize * 1024) {
            logger.debug(String.format("File size is is less than %d kb, no compression optimization required.", desFileSize));
            return;
        } else {
            logger.info(String.format("%d | source file : %s, size : %d kb", compressCount, desPath, desFileSize / 1024 ));
        }
        //计算宽高
        BufferedImage bim = ImageIO.read(srcFileJPG);
        int srcWidth = bim.getWidth();
        int srcHeight = bim.getHeight();
        int destWidth = new BigDecimal(srcWidth).multiply(new BigDecimal(accuracy)).intValue();
        int destHeight = new BigDecimal(srcHeight).multiply(new BigDecimal(accuracy)).intValue();

        Thumbnails.of(desPath).size(destWidth,destHeight).outputQuality(accuracy).toFile(desPath);
//        Thumbnails.of(targetFile)
//                .scale(0.1f)//指定图片大小    0-1f  1f是原图
//                .outputQuality(1f)//图片质量  0-1f  1f是原图
//                .toFile(newFile);

        File file = new File(desPath);
        long desPathFileSize = file.length();

        compressPicCycle(desPath, desPathFileSize,accuracy, compressCount + 1);

    }

    private Map<String, Object> saveFileAndThumbnail(MultipartFile file) throws BusinessException {
        String fileUploadPath = "C:\\Users\\408675\\Desktop\\";
        // 判断文件是否为空
        if (!file.isEmpty()) {
            String root = fileUploadPath;//上传路径
            String picturePath = fileUploadPath;//保存路径
            String ext = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
            String newName = String.valueOf((new Date()).getTime()) + ext;
            File filedict = new File(root+picturePath);
            if(!filedict.exists()){
                filedict.mkdirs();
            }
            File targetFile=new File(root+picturePath+File.separator+newName);
            File newFile=new File(root+picturePath+File.separator+"s"+newName);
            try {

                file.transferTo(targetFile);
                Thumbnails.of(targetFile)
                        .scale(0.1f)//指定图片大小    0-1f  1f是原图
                        .outputQuality(1f)//图片质量  0-1f  1f是原图
                        .toFile(newFile);
                BufferedImage bimg = ImageIO.read(targetFile);
                int width = bimg.getWidth();
                int height = bimg.getHeight();
                BufferedImage thumbnail = ImageIO.read(newFile);
                int thumbnailWidth = thumbnail.getWidth();
                int thumbnailHeight = thumbnail.getHeight();
                Map<String, Object> map = new HashMap<String, Object>();
                map.put("pictureHeight",height);
                map.put("pictureWidth",width);
                map.put("picturePath",picturePath+"/"+newName);
                map.put("thumbnailHeight",thumbnailHeight);
                map.put("thumbnailWidth",thumbnailWidth);
                map.put("thumbnailPath",picturePath+"/s"+newName);
                return map;
            } catch (IllegalStateException e) {
                e.printStackTrace();
                throw new BusinessException("Fail to upload file! ");
            } catch (IOException e) {
                e.printStackTrace();
                throw new BusinessException("图片上传失败");
            } catch (Exception e) {
                e.printStackTrace();
                throw new BusinessException("图片上传失败");
            }
        }
        return null;
    }

    public static void main(String[] args) {
        Integer expectFileSize = 200;//200KB
        Double scale = 1.0;
        Double quality = 0.1;
        String srcPath = "C:\\Users\\xxxx\\Desktop\\pics\\grape.jpg";
        String coreFilename = srcPath.substring(0, srcPath.lastIndexOf("."));
        String format = srcPath.substring(srcPath.lastIndexOf(".")+1);
        String desPath = String.format("%s-%1.1f-%1.1f.%s", coreFilename, scale, quality, format);
        ThumbnailUtil.compressPictureForScale(srcPath,desPath,expectFileSize, scale,quality, 0);
    }
}