Java图片压缩工具

工具类使用场景

  1. 公司做人脸识别项目时候需要上传学生、家长、教师、访客的正面照图片,但是人脸识别机器有限制只接收200KB-1M的图片,所以必须做图片压缩到指定范围大少。
  2. APP上传使用产品的评价附件图片,手机直接拍照上传的图片过大,直接存储导致文件服务器存储容量递减,所以要压缩到指定范围大少。

注意事项

  1. 最大递归压缩深度默认为20,一般情况下JVM支持1000~2000的栈,所以请勿设置过大的递归深度,否则会抛出:stackoverflowerror.
  2. 质量比与尺寸比默认均为0.85去压缩,压缩出来的图片少于期待范围时候,会自动递增质量比与尺寸比去压缩。
  3. 图片压缩比较耗时和性能,能异步的话建议异步处理来消峰。本机压缩6M图片到600KB时候耗时3秒。

依赖关系

       <dependency><groupId>net.coobird</groupId><artifactId>thumbnailator</artifactId><version>0.4.14</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.29</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.12</version><scope>provided</scope></dependency>

核心代码

1.压缩类

import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;/*** @author huangrusheng* @version 1.0* @date 2021/5/20 15:27*/
@Slf4j
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public final class ImageCompressUtil {/*** @param imageSource 图片源* @param outputStream 压缩后的图片输出地* @return* @throws IOException*/public static boolean compress(ImageSource imageSource, OutputStream outputStream) throws IOException{boolean result = compress(imageSource);if(result){outputStream.write(imageSource.getSource());}return result;}public static boolean compress(ImageSource imageSource) throws IOException {if(imageSource.getNumberOfCompressions() == 0){imageSource.setStartTime(System.currentTimeMillis());imageSource.setOriginalSource(imageSource.getSource());}if( imageSource.getSource().length>=imageSource.getMinCompressToByteSize()&&   imageSource.getSource().length <= imageSource.getMaxCompressToByteSize()) {log.info("成功完成图片压缩,总耗时:{}秒 , 压缩次数:{} , 压缩前大少:{} KB ,压缩后大少:{}KB.",(System.currentTimeMillis() - imageSource.getStartTime()) / 1000, imageSource.getNumberOfCompressions(),imageSource.getByteSizeBeforeCompress() / 1024, imageSource.getSource().length / 1024);return true;}if(imageSource.getNumberOfCompressions() > imageSource.getRecursionDepth()){log.warn("图片过大,导致递归压缩次数超出:{},请尝试上传其他较小的图片.",imageSource.getNumberOfCompressions());return false;}//如果压缩小于期待值减少,增加下质量与尺寸比例if(imageSource.getSource().length < imageSource.getMinCompressToByteSize()){log.warn("压缩过度重新压缩,总耗时:{}秒 , 压缩次数:{} , 压缩前大少:{} KB ,压缩后大少:{}KB.",(System.currentTimeMillis()-imageSource.getStartTime())/1000   ,imageSource.getNumberOfCompressions(),imageSource.getByteSizeBeforeCompress()/1024, imageSource.getSource().length/1024 );imageSource.setScale(imageSource.getScale() + imageSource.getIncrementCompressQuality());imageSource.setQuality(imageSource.getQuality() + imageSource.getIncrementCompressQuality());imageSource.setSource(imageSource.getOriginalSource());}ByteArrayOutputStream byteArrayOutputStream =new ByteArrayOutputStream(imageSource.getMaxCompressToByteSize());Thumbnails.of(new ByteArrayInputStream(imageSource.getSource())).scale(imageSource.getScale()).outputQuality(imageSource.getQuality()).outputFormat(imageSource.getImageFormat()).toOutputStream(byteArrayOutputStream);imageSource.setSource(byteArrayOutputStream.toByteArray());imageSource.increaseNumberOfCompressions();return compress(imageSource);}}

2.压缩参数POJO类

import lombok.Data;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
/*** @author huangrusheng* @version 1.0* @date 2021/5/20 15:16*/
@Data
public class ImageSource {/*** 需压缩的图片,转为字节*/private  byte[] source;/*** 记录压缩前的图片,转为字节*/private  byte[] originalSource;/*** 当前图片压缩的次数*/private int  numberOfCompressions = 0;private long startTime ;/*** 未执行压缩前,图片的字节大少*/private int byteSizeBeforeCompress ;/*** 压缩质量*/private double quality = 0.85;/*** 压缩尺寸比例*/private double scale = 0.85;private double incrementCompressQuality = 0.05;/*** 需压缩到最大容许的字节数,默认为1M*/private int maxCompressToByteSize = 1024*1024*1;/*** 需压缩到最小容许的字节数,默认为200KB*/private long minCompressToByteSize = 1024*200;/*** 压缩后的图片格式,默认JPG*/private  String imageFormat = "jpg";/*** 最大递归压缩深度*/private  int  recursionDepth = 20;public ImageSource(byte[] source){this.initSource(source);}public ImageSource(InputStream inputStream) throws IOException {this(inputStream,null);}public ImageSource(InputStream inputStream,Long inputByteSize ) throws IOException{ByteArrayOutputStream byteArrayOutputStream= new ByteArrayOutputStream(inputByteSize == null ? 2 * 1024 * 1024 : inputByteSize.intValue());int n ;byte [] buffer = new byte[1024 * 100];while (  -1 != ( n = inputStream.read(buffer))){byteArrayOutputStream.write(buffer,0,n);}this.initSource(byteArrayOutputStream.toByteArray());}private void initSource(byte[] source){this.source = source;this.byteSizeBeforeCompress = this.source.length;}public void  increaseNumberOfCompressions(){this.numberOfCompressions = this.numberOfCompressions + 1;}
}

单元测试用例

import cn.hutool.core.io.IoUtil;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import java.io.FileInputStream;
import java.io.FileOutputStream;
/*** @author huangrusheng* @version 1.0* @date 2021/5/20 16:05*/
@RunWith(JUnit4.class)
public class ImageCompressTest {@Testpublic void testCompress() throws Exception{FileInputStream fileInputStream = null ;FileOutputStream fileOutputStream = null;try {fileInputStream = new FileInputStream("D:\\image_source.jpg");fileOutputStream = new FileOutputStream("D:\\image_compress.jpg");ImageSource imageSource = new ImageSource(fileInputStream);imageSource.setMinCompressToByteSize(300*1024);imageSource.setMaxCompressToByteSize(800*1024);imageSource.setImageFormat("jpg");ImageCompressUtil.compress(imageSource,fileOutputStream);}finally {IoUtil.close(fileInputStream);IoUtil.flush(fileOutputStream);IoUtil.close(fileOutputStream);}}
}

压缩前

压缩后

Java图片压缩工具类(递归压缩到指定大小范围)相关推荐

  1. java图片压缩工具类

    java图片压缩工具类 PicCompressUtil.java import java.io.ByteArrayInputStream; import java.io.ByteArrayOutput ...

  2. java图片压缩工具类(指定压缩大小)

    1:先导入依赖 <!--thumbnailator图片处理--><dependency><groupId>net.coobird</groupId>&l ...

  3. android图片压缩工具类

    好久没写博客了,一方面是因为最近找了家实习单位,很累基本上下班后就没有打不起精神去学习,另一方面我自己觉得写博客确实有点耗时间,趁着周六周日想花点时间研究下fresco,picass,Glide等框架 ...

  4. 一个好用的android图片压缩工具类

    <span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255) ...

  5. java图片的导出,并压缩

    java图片的导出,并压缩 java 压缩包jar包使用的是commons-compress-1.6.jar /*** 导出图片* @param request* @param response*/@ ...

  6. JAVA图片裁剪工具类

    JAVA图片裁剪工具类: <span style="font-size:14px;">package org.oms.avatar.util;import java.a ...

  7. java zip 压缩工具类

    java zip 压缩工具类 目录结构 环境依赖 zip压缩工具类 遇到的问题 环境依赖 <!--这里作者使用的是 springboot 2.3.2.RELEASE 版本--> <d ...

  8. 整合的图片压缩工具类ImageTools

    根据网上找的资料和自己用到的地方进行修改的图片压缩工具类,有什么不对的地方请见谅,源码如下: public final class ImageTools {/*** Transfer drawable ...

  9. python更改图片存储大小_python不改变图片尺寸压缩到指定大小

    python不改变图片尺寸压缩到指定大小 import base64 import io import os from PIL import Image from PIL import ImageFi ...

最新文章

  1. SharePoint Online 创建和使用栏
  2. CF1446F-Line Distance【计算几何,树状数组,二分】
  3. Lighttpd 的安装配置(web服务器软件)
  4. RabbitMQ事务和Confirm发送方消息确认——深入解读
  5. MPLS 次末跳弹出配置_weblogic的安装与配置
  6. Android开源框架:Universal-Image-Loader解析(四)TaskProcess
  7. interface接口_Java程序设计--接口interface(笔记)
  8. 自动修改mysql5.7初始化密码
  9. GitLab oauth2.0 第三方登录 单点登录
  10. 关于Google Chrome浏览器离线安装包下载方法
  11. tomcat 官网下载
  12. alook浏览器哪个好 夸克浏览器_简单搜索、X浏览器、夸克浏览器、Via几款极简浏览器,到底哪个最好用?...
  13. 新华文娱数据发布年度白皮书 口碑成观影首要驱动力
  14. 移动端使用fiddler抓包步骤
  15. 某某客户的一次勒索病毒应急响应
  16. 假期错过的...条AI新闻都在这里了
  17. 和sar比起来,其他Linux命令都是猹---ing
  18. B-004 LC滤波器的基础知识
  19. 【文献管理软件Zotero】Zotfile插件及云同步的使用技巧
  20. 微信公众平台开发(PHP)(五) 天气预报功能开发

热门文章

  1. 50000字,数仓建设保姆级教程,离线和实时一网打尽(理论+实战) 上
  2. “微信身份证”来了!安全吗?要是手机丢了咋办…
  3. 区域环评项目(Vue3 PC)实现验证码等功能 问题记录
  4. iOS点击短信中的链接跳转到App
  5. 稀疏数组——实现五子棋存盘和续上盘功能
  6. html图片居中自适应,解决img图片自适应居中问题
  7. pycharm配置sqlite
  8. csgo内置服务器文件夹,[服务器架设] CSGO 服务器架设新手全教程(WIN)(带图) | 视频迟些送上...
  9. 微信小程序 - 页面事件
  10. BZOJ1746 DP