前言
下面介绍了两种获取图片缩略图的方式,全都不是一次性压缩,如果没有达到设置的压缩范围,图片会循环压缩,大家根据自己的需求,可以自己调节最大缩略图的大小范围。
经过测试第二种方式效率更高,但是对于压缩率只是初步设置一个大致范围,还需要更精细化的调试
一、使用Base64编码方式
此方式全都需要使用到基本方法,基本方法如下,自行复制
1、基本方法
/**
* 按照宽高比例压缩
*
* @param srcImgData 待压缩图片输入流
* @param scale 压缩刻度
* @return
* @throws IOException
* @author CY
* @date 2020年11月18日
*/
private static byte[] compress(byte[] srcImgData, double scale) throws IOException {
try {
BufferedImage bi = ImageIO.read(new ByteArrayInputStream(srcImgData));
int width = (int) (bi.getWidth() * scale); // 源图宽度
int height = (int) (bi.getHeight() * scale); // 源图高度
Image image = bi.getScaledInstance(width, height, Image.SCALE_SMOOTH);
BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics g = tag.getGraphics();
g.setColor(Color.RED);
g.drawImage(image, 0, 0, null); // 绘制处理后的图
g.dispose();
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
ImageIO.write(tag, "JPEG", bOut);
return bOut.toByteArray();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
2、压缩本地图片保存到本地
/**
* 压缩本地图片保存到本地
*
* @param path 保存文件的路径,精确到最后一个文件夹
* @param localPhotoUrl 本地图片路径,精确到文件
* @param fileName 新的文件名
* @return
*/
public static String localImageCompress(String path, String localPhotoUrl, String fileName) {
try {
// 读取文件并转换成字节数组
Path filePath = Paths.get(localPhotoUrl);
byte[] picByte = Files.readAllBytes(filePath);
// 对图片进行压缩
byte[] finalCompressPic = compress(picByte, 0.9);
BigDecimal filesize = new BigDecimal(finalCompressPic.length);
BigDecimal kilobyte = new BigDecimal(1024);
float returnValue = filesize.divide(kilobyte, 2, BigDecimal.ROUND_UP).floatValue();
// 输出压缩后的图片大小
System.out.println("图片的字节数:" + finalCompressPic.length + "图片的大小:" + returnValue + "KB");
// 如果图片大小超过149KB,则继续压缩,直到图片大小小于或等于149KB
if (returnValue > 150) {
for (int i = 0; i < 9; i++) {
double scale = (i + 1) * 0.1;
scale = 0.9 - scale;
finalCompressPic = compress(finalCompressPic, scale);
filesize = new BigDecimal(finalCompressPic.length);
kilobyte = new BigDecimal(1024);
returnValue = filesize.divide(kilobyte, 2, BigDecimal.ROUND_UP).floatValue();
System.out.println("继续压缩图片的字节数:" + finalCompressPic.length + "图片的大小:" + returnValue + "KB");
if (returnValue > 150) {
continue;
} else {
break;
}
}
}
// 对字节数组Base64编码
Base64.Encoder encoder = Base64.getEncoder();
String png_base64 = encoder.encodeToString(finalCompressPic);
// 将Base64编码后的字符串转换成字节数组并保存到文件中
byte[] decodedBytes = Base64.getDecoder().decode(png_base64);
File outputFile = new File(path, fileName);
OutputStream outputStream = new FileOutputStream(outputFile);
outputStream.write(decodedBytes);
// 返回生成的缩略图路径
return outputFile.getAbsolutePath();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
3、压缩网络图片到图片服务器
//压缩网络图片保存到图片服务器
public static String netImageCompress(String photoUrl) {
try {
byte[] picByte = ImgBase64Util.imgToByte(photoUrl);
byte[] compressPic = compress(picByte, 0.9);
byte[] finalCompressPic = compressPic;
BigDecimal filesize = new BigDecimal(compressPic.length);
BigDecimal kilobyte = new BigDecimal(1024);
float returnValue = filesize.divide(kilobyte, 2, BigDecimal.ROUND_UP).floatValue();
//输出
System.out.println("图片的字节数:" + compressPic.length + "图片的大小:" + returnValue + "KB");
if (returnValue > 149) {
for (int i = 0; i < 10; i++) {
double scale = (i + 1) * 0.1;
scale = 0.9 - scale;
finalCompressPic = compress(finalCompressPic, scale);
BigDecimal filesize2 = new BigDecimal(finalCompressPic.length);
BigDecimal kilobyte2 = new BigDecimal(1024);
float returnValue2 = filesize2.divide(kilobyte2, 2, BigDecimal.ROUND_UP).floatValue();
System.out.println("循环i=" + i + "的图片的字节数:" + finalCompressPic.length + "图片的大小:" + returnValue2 + "KB");
if (returnValue2 > 149) {
continue;
} else {
break;
}
}
}
Base64.Encoder encoder = Base64.getEncoder();
String png_base64 = encoder.encodeToString(finalCompressPic);
File file = ImgBase64Util.base64ToFile(png_base64);
FileInputStream input = new FileInputStream(file);
MultipartFile multipartFile = new MockMultipartFile("file", file.getName(), "text/plain", input);
Map param = new HashMap();
param.put("source", "system");
param.put("type", "img");
HttpUtils httpUtils = new HttpUtils();
HttpResult httpResult = httpUtils.doFilePost("https://test.com/upload", multipartFile, param);
Integer httpCode = httpResult.getCode();
if (httpCode == 200) {
JSONObject result = JSONObject.parseObject(httpResult.getBody());
Integer code = result.getInteger("code");
if (code == 0) {
String url = result.getString("data");
System.out.println("compress pic url:" + url);
return url;
}
}
return null;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
二、使用thumbnailator工具方式
此方式需要导入依赖,依赖如下
1、导入依赖
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.19</version>
</dependency>
2、压缩本地图片保存到本地
/**
* 压缩本地图片保存到本地
*
* @param path 保存文件的路径,精确到最后一个文件夹
* @param localPhotoUrl 本地图片路径,精确到文件
* @param fileName 新的文件名
* @return
*/
public static String localImageCompress(String path, String localPhotoUrl, String fileName) {
try {
File f = new File(localPhotoUrl);
long sourceImgValue = f.length() / 1024;
BufferedImage sourceImg = ImageIO.read(new FileInputStream(f));
int width = sourceImg.getWidth();//原图宽度
int height = sourceImg.getHeight();//原图高度
int hightValue = width;//宽度和高度的最大值
if (height > width) hightValue = height;
double scale111 = 0.5;
if (1000 <= hightValue && hightValue < 2000) scale111 = 0.3;
if (2000 <= hightValue && hightValue < 3000) scale111 = 0.2;
if (3000 <= hightValue && hightValue < 4000) scale111 = 0.1;
if (4000 <= hightValue) scale111 = BigDecimal.valueOf(500L)
.divide(BigDecimal.valueOf(hightValue), 2, BigDecimal.ROUND_UP).doubleValue();
System.out.println("最终scale为:" + scale111);
/**
* 图片小于5M,压缩图片最大尺寸为512K
* 大于5M,小于10M,压缩图片最大尺寸为1M
* 大于10M,压缩图片最大尺寸为2M
*/
int maxSize = 512;//压缩图片的最大尺寸
if (sourceImgValue < 5 * 1024) maxSize = 512;
if (5 * 1024 <= sourceImgValue && sourceImgValue < 10 * 1024) maxSize = 1024;
if (10 * 1024 <= sourceImgValue) maxSize = 2 * 1024;
String thumbnailPath = path + fileName;
Thumbnails.of(localPhotoUrl)
.scale(scale111)
.outputQuality(0.9)
.toFile(thumbnailPath);
File f1 = new File(thumbnailPath);
long returnValue = f1.length() / 1024;
System.out.println("第一次生成图片缩略图,大小为:" + returnValue + "KB");
// 如果图片大小超过1M,则继续压缩,直到图片大小小于或等于149KB
if (returnValue > maxSize) {
for (int i = 0; i < 4; i++) {
double scale = (i + 1) * 0.1;
double scaleQuality = 0.9 - scale * 2;
if (scale111 > scale) scale111 = scale111 - scale;
System.out.println("最终scale为:" + scale111);
System.out.println("最终scaleQuality为:" + scaleQuality);
Thumbnails.of(localPhotoUrl)
.scale(scale111)
.outputQuality(scaleQuality)
.toFile(thumbnailPath);
File f2 = new File(thumbnailPath);
returnValue = f2.length() / 1024;
System.out.println("继续压缩图片大小:" + returnValue + "KB");
if (returnValue > maxSize) {
continue;
} else {
break;
}
}
}
return thumbnailPath;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}