前言
业务场景,需要把图片服务器的图片通过http请求发送到客户系统,客户要求单个图片不能超过2M,而我们的图片大多数大于2M。所以需要对图片进行压缩并生成一个输入流作为参数上传
https://blog.csdn.net/qq_25508039/article/details/82257436
一、Thumbnails?
Thumbnails可以对图片操作
- 按指定宽高进行缩放图片
- 按比例缩放图片
- 添加水印
- 转化图片格式
- 旋转
- 裁剪等
我们这只要是介绍把图片的字节数组缩放到指定大小以下,输出到输入输出流或本地文件,其他功能请参考引用
二、使用步骤
1.引入maven
代码如下(示例):
<!-- 图片缩略图 -->
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.8</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.7</version>
</dependency>
2.自定义工具类ThumbnailsUtils
代码如下:
import net.coobird.thumbnailator.Thumbnails;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
/**
* 图片压缩工具
* 创建人 LITAO
* 创建时间 2021年4月16日
*/
public class ThumbnailsUtils {
private static Logger logger = LoggerFactory.getLogger(ThumbnailsUtils.class);
/**
* 按文件大小压缩一个输入流返回一个输出流
* @param imageBytes 图片字节数组
* @param confineSize 限制文件大小 kb
* @param imageName 图片名称
* @return
*/
public static ByteArrayOutputStream compressToOut(byte[] imageBytes, int confineSize, String imageName){
try {
byte[] bytes = compressPicForScaleToBytes(imageBytes, confineSize, imageName);
ByteArrayInputStream in = new ByteArrayInputStream(bytes);
ByteArrayOutputStream out = new ByteArrayOutputStream();
//把输入流拷贝到输出流
IOUtils.copy(in,out);
in.close();
return out;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
}
return null;
}
/**
* 按文件大小压缩一个图片字节数组返回一个输入流
* @param imageBytes 图片字节数组
* @param confineSize 限制文件大小 kb
* @param imageName 图片名称
*/
public static ByteArrayInputStream compressIn(byte[] imageBytes, int confineSize, String imageName){
try {
byte[] bytes = compressPicForScaleToBytes(imageBytes, confineSize, imageName);
ByteArrayInputStream in = new ByteArrayInputStream(bytes);
return in;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 按文件大小压缩一个图片字节数组到本地文件
* @param imageBytes 图片字节数组
* @param toFile 目标文件名称路径
* @param confineSize 限制文件大小 kb
* @param imageName 图片名称
* @return
*/
public static void compressFile(byte[] imageBytes, String toFile, int confineSize, String imageName){
try {
byte[] bytes = compressPicForScaleToBytes(imageBytes, confineSize, imageName);
OutputStream out = new FileOutputStream(toFile);
out.write(bytes);
out.flush();
IOUtils.closeQuietly(out);
out = null;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 根据指定大小压缩图片
*
* @param imageBytes 源图片字节数组
* @param desFileSize 指定图片大小,单位kb
* @param imageName 影像名称
* @return 压缩质量后的图片字节数组
*/
public static byte[] compressPicForScaleToBytes(byte[] imageBytes, long desFileSize, String imageName) {
if (imageBytes == null || imageBytes.length <= 0 || imageBytes.length < desFileSize * 1024) {
return imageBytes;
}
long srcSize = imageBytes.length;
double quality = getQuality(srcSize / 1024);
try {
while (imageBytes.length > desFileSize * 1024) {
ByteArrayInputStream inputStream = new ByteArrayInputStream(imageBytes);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(imageBytes.length);
Thumbnails.of(inputStream)
.scale(quality)
.outputQuality(quality)
.toOutputStream(outputStream);
imageBytes = outputStream.toByteArray();
//关闭流
IOUtils.closeQuietly(inputStream,outputStream);
inputStream = null;
outputStream = null;
}
logger.info("【图片压缩】imageName={} | 图片原大小={}kb | 压缩后大小={}kb",
imageName, srcSize / 1024, imageBytes.length / 1024);
} catch (Exception e) {
logger.error("【图片压缩】msg=图片压缩失败!", e);
}
return imageBytes;
}
/**
* 自动调节精度(经验数值)
*
* @param size 源图片大小 kb
* @return 图片压缩质量比
*/
private static double getQuality(long size) {
if (size < 900) {
return 0.85;
} else if (size < 2047) {
return 0.6;
} else if (size < 3275) {
return 0.44;
}
return 0.4;
}
}