导出图片压缩
This commit is contained in:
@ -72,13 +72,13 @@ public class ImageCompressUtil {
|
||||
}
|
||||
|
||||
// 先尝试质量压缩
|
||||
byte[] compressedData = compressImageQuality(originalImage, formatName, 0.8f);
|
||||
byte[] compressedData = compressImageQuality(originalImage, formatName, 0.7f);
|
||||
|
||||
// 如果质量压缩后仍大于目标大小,则进行尺寸压缩
|
||||
if (compressedData.length > maxSize) {
|
||||
// 计算缩放比例
|
||||
double scale = Math.sqrt((double) maxSize / compressedData.length);
|
||||
scale = Math.max(scale, 0.5); // 最小缩放到原来的一半
|
||||
scale = Math.max(scale, 0.2); // 最小缩放到原来的20%
|
||||
|
||||
// 尺寸压缩
|
||||
compressedData = compressImageByScale(originalImage, scale, formatName);
|
||||
@ -86,20 +86,36 @@ public class ImageCompressUtil {
|
||||
|
||||
// 如果压缩后还是太大,继续压缩
|
||||
int attempts = 0;
|
||||
while (compressedData.length > maxSize && attempts < 5) {
|
||||
while (compressedData.length > maxSize && attempts < 15) { // 增加尝试次数到15次
|
||||
// 优先降低质量
|
||||
float quality = Math.max(0.1f, 0.8f - attempts * 0.1f);
|
||||
float quality = Math.max(0.01f, 0.7f - attempts * 0.1f); // 最低质量降至0.01
|
||||
compressedData = compressImageQuality(originalImage, formatName, quality);
|
||||
|
||||
// 如果质量压缩不够,再缩小尺寸
|
||||
if (compressedData.length > maxSize) {
|
||||
double scale = 0.9 - attempts * 0.1; // 逐步缩小尺寸
|
||||
scale = Math.max(scale, 0.5);
|
||||
double scale = 0.8 - attempts * 0.15; // 更积极地缩小尺寸
|
||||
scale = Math.max(scale, 0.1); // 最小缩放到原来的10%
|
||||
compressedData = compressImageByScale(originalImage, scale, formatName);
|
||||
}
|
||||
attempts++;
|
||||
}
|
||||
|
||||
// 如果经过多次尝试仍然大于目标大小,则强制压缩到目标大小以下
|
||||
if (compressedData.length > maxSize) {
|
||||
// 强制尺寸压缩到目标大小
|
||||
double finalScale = Math.sqrt((double) maxSize / compressedData.length) * 0.8; // 留一些余量
|
||||
finalScale = Math.max(finalScale, 0.05); // 至少保留5%的尺寸
|
||||
compressedData = compressImageByScale(originalImage, finalScale, formatName);
|
||||
|
||||
// 如果仍然太大,强制质量压缩
|
||||
if (compressedData.length > maxSize) {
|
||||
// 计算需要的质量值
|
||||
float finalQuality = (float) maxSize / compressedData.length * 0.7f; // 留一些余量
|
||||
finalQuality = Math.max(finalQuality, 0.005f); // 至少保留0.5%的质量
|
||||
compressedData = compressImageQuality(originalImage, formatName, finalQuality);
|
||||
}
|
||||
}
|
||||
|
||||
log.info("图片压缩完成,原始大小: {} bytes, 压缩后大小: {} bytes, 压缩率: {}%",
|
||||
imageData.length, compressedData.length,
|
||||
String.format("%.2f", (1.0 - (double) compressedData.length / imageData.length) * 100));
|
||||
@ -110,6 +126,12 @@ public class ImageCompressUtil {
|
||||
return imageData;
|
||||
}
|
||||
|
||||
// 特殊处理:如果目标大小是50KB或更小,确保最终结果符合要求
|
||||
if (maxSize <= 50 * 1024 && compressedData.length > maxSize) {
|
||||
// 使用更强力的压缩策略
|
||||
compressedData = forceCompressToSize(originalImage, formatName, maxSize);
|
||||
}
|
||||
|
||||
return compressedData;
|
||||
} catch (Exception e) {
|
||||
log.error("图片压缩失败: {}", e.getMessage(), e);
|
||||
@ -117,6 +139,63 @@ public class ImageCompressUtil {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 强制压缩到指定大小
|
||||
*
|
||||
* @param originalImage 原始图片
|
||||
* @param formatName 图片格式
|
||||
* @param maxSize 目标大小
|
||||
* @return 压缩后的图片数据
|
||||
*/
|
||||
private static byte[] forceCompressToSize(BufferedImage originalImage, String formatName, int maxSize) throws IOException {
|
||||
byte[] result = null;
|
||||
int width = originalImage.getWidth();
|
||||
int height = originalImage.getHeight();
|
||||
|
||||
// 通过不断缩小尺寸来达到目标大小
|
||||
double scale = 0.9;
|
||||
do {
|
||||
int newWidth = (int) (width * scale);
|
||||
int newHeight = (int) (height * scale);
|
||||
|
||||
// 创建缩放后的图片
|
||||
Image scaledImage = originalImage.getScaledInstance(newWidth, newHeight, Image.SCALE_SMOOTH);
|
||||
BufferedImage bufferedImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB);
|
||||
Graphics2D g2d = bufferedImage.createGraphics();
|
||||
|
||||
// 绘制缩放后的图片
|
||||
g2d.drawImage(scaledImage, 0, 0, null);
|
||||
g2d.dispose();
|
||||
|
||||
// 以最低质量压缩
|
||||
result = compressImageQuality(bufferedImage, formatName, 0.01f);
|
||||
|
||||
if (result.length <= maxSize) {
|
||||
break;
|
||||
}
|
||||
|
||||
scale -= 0.1;
|
||||
} while (scale > 0.1 && result.length > maxSize);
|
||||
|
||||
// 如果还是太大,强制调整大小
|
||||
if (result.length > maxSize) {
|
||||
// 计算精确的缩放比例
|
||||
double targetScale = Math.sqrt((double) maxSize / result.length) * 0.9;
|
||||
int newWidth = Math.max((int) (width * targetScale), 5);
|
||||
int newHeight = Math.max((int) (height * targetScale), 5);
|
||||
|
||||
Image scaledImage = originalImage.getScaledInstance(newWidth, newHeight, Image.SCALE_SMOOTH);
|
||||
BufferedImage bufferedImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB);
|
||||
Graphics2D g2d = bufferedImage.createGraphics();
|
||||
g2d.drawImage(scaledImage, 0, 0, null);
|
||||
g2d.dispose();
|
||||
|
||||
result = compressImageQuality(bufferedImage, formatName, 0.005f);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 按比例缩放图片
|
||||
*
|
||||
@ -130,6 +209,10 @@ public class ImageCompressUtil {
|
||||
int width = (int) (originalImage.getWidth() * scale);
|
||||
int height = (int) (originalImage.getHeight() * scale);
|
||||
|
||||
// 确保最小尺寸不小于5像素
|
||||
width = Math.max(width, 5);
|
||||
height = Math.max(height, 5);
|
||||
|
||||
// 创建缩放后的图片
|
||||
Image scaledImage = originalImage.getScaledInstance(width, height, Image.SCALE_SMOOTH);
|
||||
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
|
||||
|
||||
Reference in New Issue
Block a user