首页 > 技术文章 > Base64 图片压缩工具类

Dylanl 2022-06-16 18:17 原文

问题背景

服务器带宽有限,需要图片传给第三方进行业务处理,图片过大影响响应时间,需要进行压缩

具体实现

import net.coobird.thumbnailator.Thumbnails;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.compress.utils.IOUtils;
import org.springframework.util.StringUtils;

import java.io.*;
import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 * @author : liuxinchi
 * @date :2022/6/16 16:51
 * @description : 图片工具类
 */
public class ImageUtils {

    /**
     * 根据图片的base64数据缩放图片20kb
     *
     * @param base64ImagStr 原图的base64字符换
     * @param imageType     图片类型
     * @return base64数据缩放图片
     */
    public static String scaleImage(String base64ImagStr, String imageType, int targetSize) {
        if (StringUtils.hasLength(base64ImagStr) && !"0".equals(base64ImagStr)) {
            try {
                byte[] imageBytes = Base64.decodeBase64(base64ImagStr);
                ByteArrayInputStream imageStream = new ByteArrayInputStream(imageBytes);

                ByteArrayOutputStream stream = new ByteArrayOutputStream();
                Thumbnails.of(imageStream).scale(0.7).outputFormat(imageType).toOutputStream(stream);

                String resultBase64Str = Base64.encodeBase64String(stream.toByteArray());
                Integer imageSizeBase64 = imageSize(resultBase64Str);
                if (imageSizeBase64 > targetSize) {
                    resultBase64Str = scaleImage(resultBase64Str, imageType, targetSize);
                }
                return resultBase64Str;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return base64ImagStr;
    }

    /**
     * 计算图片的大小,返回单位为KB
     *
     * @param imageBase64Str 图片base64数据
     * @return 图片大小
     */
    public static Integer imageSize(String imageBase64Str) {

        //1.找到等号,把等号也去掉(=用来填充base64字符串长度用)
        int equalIndex = imageBase64Str.indexOf("=");
        if (imageBase64Str.indexOf("=") > 0) {
            imageBase64Str = imageBase64Str.substring(0, equalIndex);
        }
        //2.原来的字符流大小,单位为字节
        int strLength = imageBase64Str.length();

        //3.计算后得到的文件流大小,单位为字节
        int size = strLength - (strLength / 8) * 2;
        return bytesToKB(size);
    }

    /**
     * byte(字节)根据长度转成kb(千字节)
     *
     * @param bytes 字节
     * @return 大小
     */
    public static Integer bytesToKB(long bytes) {
        BigDecimal filesize = new BigDecimal(bytes);
        BigDecimal kilobyte = new BigDecimal(1024);
        float returnValue = filesize.divide(kilobyte, 1, RoundingMode.DOWN).floatValue();
        return (int) returnValue;
    }

    /**
     * 图片压缩
     * @param base64Str base46字符串
     * @param targetSize 目标大小
     * @return
     * @throws IOException
     */
    public static String pictureCompression(String base64Str, int targetSize) throws IOException {
        Integer size = imageSize(base64Str);
        if (size > targetSize) {
            ByteArrayInputStream imageStream = new ByteArrayInputStream(Base64.decodeBase64(base64Str));
            ByteArrayOutputStream stream = new ByteArrayOutputStream();
            Thumbnails.of(imageStream).scale(1f).outputFormat("jpeg").toOutputStream(stream);

            base64Str = Base64.encodeBase64String(stream.toByteArray());
            Integer jpegSize = imageSize(base64Str);
            if (jpegSize > targetSize) {
                base64Str = scaleImage(base64Str, "jpeg", targetSize);
            }
        }
        return base64Str;
    }

    public static void main(String[] args) throws Exception {
        String base64Str = Base64.encodeBase64String(IOUtils.toByteArray(new FileInputStream("C:\\Users\\LIUXINCHI-A\\Pictures\\Saved Pictures\\20220607101728.jpg")));
        base64Str = pictureCompression(base64Str, 100);
        System.out.println(imageSize(base64Str));
    }

}

引入maven依赖包

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

<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.6</version>
</dependency>

推荐阅读