开发过程记录-----图片压缩工具类

文章介绍了Java中的ImageThumbnailUtils工具类,用于生成图片缩略图并支持根据需求进行压缩,包括OCR识别场景下的图片预处理和大小控制。
摘要由CSDN通过智能技术生成

日常开发中,会遇到图片处理,比如图片缩略图生成,图片压缩等,以下工具类提供图片压缩功能。

package com.zx.test.common.utils;


import com.drew.imaging.ImageMetadataReader;
import com.drew.metadata.Directory;
import com.drew.metadata.Metadata;
import com.drew.metadata.exif.ExifIFD0Directory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Decoder;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageOutputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Iterator;


/**
 * 图像处理工具类
 *
 * @author 
 * Create on 2023/9/11
 */
@Slf4j
public class ImageThumbnailUtils {

   

    /**
     * 用于生成缩略图以及压缩图片
     *
     * @param quality     压缩质量 范围0-1,1为最高质量
     * @param inputStream 图片输入流
     * @return
     * @throws IOException
     */
    public static byte[] createThumbnail(float quality, InputStream inputStream) throws IOException {

        log.info("生成缩略图------");
        ByteArrayOutputStream baos = cloneInputStream(inputStream);
        // 打开两个新的输入流
        InputStream streamOne = new ByteArrayInputStream(baos.toByteArray());
        InputStream streamTwo = new ByteArrayInputStream(baos.toByteArray());

        BufferedImage originalImage = ImageIO.read(streamOne);
       

        int height = originalImage.getHeight();
        int width = originalImage.getWidth();
        if (width > 1500) {
            // 定义新画布宽高
            height = (int) (height * quality);
            width = (int) (width * quality);
        }
        // 创建一个新的缩放后的图像  必须,不然png转jpg时会有背景失真
        Image tmpImage = originalImage.getScaledInstance(width, height, Image.SCALE_SMOOTH);
        BufferedImage thumbnail = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        // 在缩放后的图像上绘制原始图像
        thumbnail.getGraphics().drawImage(tmpImage, 0, 0, null);

        // 压缩 使用jpg格式压缩
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ImageIO.write(thumbnail, "jpg", byteArrayOutputStream);

        byte[] byteArray = byteArrayOutputStream.toByteArray();
        byteArrayOutputStream.close();
        return byteArray;
    }

    /**
     * 用于ocr识别图片规格压缩
     *
     * @param quality    设置的压缩质量 0-1
     * @param fileBase64 图片输入流
     * @param minLength  最短边最小长度 px
     * @param maxLength  最长边最长长度  px
     * @param size       要求的大小  kb
     * @return
     * @throws IOException
     */
    public static byte[] createThumbnailCheck(MultipartFile file, float quality, String fileBase64, int minLength, int maxLength, int size) throws IOException {
        if (file == null) {
            String base64 = BASE64DecodedMultipartFile.resolveMimeType(fileBase64);
            file = BASE64DecodedMultipartFile.base64ToMultipart(base64);
        }
        log.info("COR识别前处理图片-------------");
        long fileSize = file.getSize() / 1024;
        ByteArrayOutputStream baos = cloneInputStream(file.getInputStream());
        // 打开两个新的输入流
        InputStream streamOne = new ByteArrayInputStream(baos.toByteArray());
        InputStream streamTwo = new ByteArrayInputStream(baos.toByteArray());
        BufferedImage originalImage = ImageIO.read(streamOne);
        
        //double compressionRatio = (double) size / fileSize;
        //原图height  width
        int height = originalImage.getHeight();
        int width = originalImage.getWidth();
        log.info("图片原像素,height:{},width:{}", originalImage.getHeight(), originalImage.getWidth());
//        if (compressionRatio < 1) {
//            width = (int) (originalImage.getWidth() * Math.sqrt(compressionRatio));
//            height = (int) (originalImage.getHeight() * Math.sqrt(compressionRatio));
//        }
        // 判断原图宽高是否在最长最短范围内
        // 找到原图宽高的最长最短边,判断是否在范围内,,不是的话进行调整
//        if (height >= width) {
//            float scale = (float) maxLength * 0.5f / height;
//            // 当最长边大于maxLength 设置最长边为maxLength  width按比例缩小
//            if (height > maxLength) {
//                width = (int) (width * scale);
//                height = (int) (maxLength * 0.5);
//            }
//            if (width < minLength) {
//                width = minLength;
//            }
//        } else {
//            float scale = (float) maxLength * 0.5f / width;
//            if (width > maxLength) {
//                height = (int) (height * scale);
//                width = (int) (maxLength * 0.5);
//            }
//            if (height < minLength) {
//                height = minLength;
//            }
//        }
        float scale = (float)  828 / width;

        height = (int) (height * scale);
        width = 828;
        log.info("图片后像素,height:{},width:{}", height, width);
        // 创建一个新的缩放后的图像
        //Image tmpImage = originalImage.getScaledInstance(width, height, Image.SCALE_SMOOTH);
        BufferedImage thumbnail = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        // 在缩放后的图像上绘制原始图像
        thumbnail.getGraphics().drawImage(originalImage, 0, 0, width, height, null);
        // 压缩 使用jpg格式压缩
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        // 判断当前图片是否需要压缩
        ImageIO.write(thumbnail, "JPEG", byteArrayOutputStream);
        float size1 = (float) byteArrayOutputStream.size() / 1024;
        if (size1 < size) {
            byteArrayOutputStream.close();
            return byteArrayOutputStream.toByteArray();
        } else {
            byteArrayOutputStream.reset();
        }

        // 定义循环 按压缩比例循环,每次压缩按照设定的压缩比例循环
        float qualityRes = 1f;
        while (true) {
            qualityRes = quality * qualityRes;
            byteArrayOutputStream = createThumbnailOnly(thumbnail, qualityRes, byteArrayOutputStream);
            float size2 = (float) byteArrayOutputStream.size() / 1024;
            if (size2 <= size) {
                break;
            }
            byteArrayOutputStream.reset();
        }
        byte[] byteArray = byteArrayOutputStream.toByteArray();
        log.info("图片进行压缩,压缩前size:{}", file.getSize());
        byteArrayOutputStream.close();
        return byteArray;
    }

    /**
     * 用于ocr识别图片压缩前判别
     *
     * @param file       文件 (为null时传fileBase64)
     * @param fileBase64 base64
     * @param minLength  最短边最小长度 px
     * @param maxLength  最长边最长长度  px
     * @param size       要求的大小  kb
     * @return
     * @throws IOException
     */
    public static boolean checkImageByBase64(MultipartFile file, String fileBase64, int minLength, int maxLength, int size) throws IOException {
        if (file == null) {
            String base64 = BASE64DecodedMultipartFile.resolveMimeType(fileBase64);
            file = BASE64DecodedMultipartFile.base64ToMultipart(base64);
        }
        BufferedImage originalImage = ImageIO.read(file.getInputStream());
        // 判断是否需要压缩
        // 判断最小长度,最大长度,图片大小
        float fileSize = (float) file.getSize() / 1024;
        if (fileSize > size) {
            log.info("图片大小超过4M");
            return true;
        }
        int width = originalImage.getWidth();
        int height = originalImage.getHeight();
        if (width > maxLength || width < minLength || height > maxLength || height < minLength) {
            log.info("图片像素不符合要求");
            return true;
        }
        return false;
    }

    public static ByteArrayOutputStream createThumbnailOnly(BufferedImage thumbnail, float quality, ByteArrayOutputStream byteArrayOutputStream) throws IOException {
        ImageOutputStream imageOutputStream = ImageIO.createImageOutputStream(byteArrayOutputStream);
        ImageWriter writer = ImageIO.getImageWritersByFormatName("JPEG").next();
        writer.setOutput(imageOutputStream);
        // 设置压缩参数
        ImageWriteParam defaultWriteParam = writer.getDefaultWriteParam();
        if (defaultWriteParam.canWriteCompressed()) {
            // 指定压缩方式为MODE_EXPLICIT
            defaultWriteParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
            // 压缩程度,参数quality是取值0~1范围内
            defaultWriteParam.setCompressionQuality(quality);
        }
        writer.write(null, new IIOImage(thumbnail, null, null), defaultWriteParam);
        // 统一转换为jpg格式
        BufferedImage image = ImageIO.read(new ByteArrayInputStream(byteArrayOutputStream.toByteArray()));
        ImageIO.write(image, "JPEG", byteArrayOutputStream);
        // 确保所有更改都已写入 ImageOutputStream 中
        imageOutputStream.flush();
        // 关闭 ImageOutputStream
        imageOutputStream.close();
        byteArrayOutputStream.flush();
        return byteArrayOutputStream;
    }

    private static ByteArrayOutputStream cloneInputStream(InputStream input) {
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len;
            while ((len = input.read(buffer)) > -1) {
                baos.write(buffer, 0, len);
            }
            baos.flush();
            return baos;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }


   

   

   
}

  • 11
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值