这个功能平时用不到,偶尔用到了代码写了就忘记,本地文件夹备忘录里找起来又麻烦,这里就先记录一下代码
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
public class ImageCompressionUtil {
// 主方法:压缩图片
public static void compressImage(String sourceImagePath, String targetImagePath, int targetFileSizeKB) throws IOException {
File inputFile = new File(sourceImagePath);
BufferedImage originalImage = ImageIO.read(inputFile);
// 计算缩放比例
double scale = calculateScale(inputFile.length(), targetFileSizeKB);
BufferedImage resizedImage = resizeImage(originalImage, scale);
// 使用二分法查找最佳质量
float bestQuality = findBestJPEGQuality(resizedImage, targetImagePath, targetFileSizeKB);
// 最终保存图片
saveCompressedImage(resizedImage, targetImagePath, bestQuality);
}
// 计算缩放比例
private static double calculateScale(long originalSize, int targetFileSizeKB) {
long targetSize = targetFileSizeKB * 1024;
if (originalSize <= targetSize) {
return 1.0; // 不缩放
}
double scale = Math.sqrt((double) targetSize / originalSize);
return Math.max(scale, 0.2); // 最小缩放比例,防止过小
}
// 调整图片大小
private static BufferedImage resizeImage(BufferedImage originalImage, double scale) {
int newWidth = (int) (originalImage.getWidth() * scale);
int newHeight = (int) (originalImage.getHeight() * scale);
BufferedImage resizedImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = resizedImage.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.drawImage(originalImage.getScaledInstance(newWidth, newHeight, Image.SCALE_SMOOTH), 0, 0, null);
g2d.dispose();
return resizedImage;
}
// 使用二分法查找最佳 JPEG 质量
private static float findBestJPEGQuality(BufferedImage image, String tempFilePath, int targetFileSizeKB) throws IOException {
float low = 0.05f; // 最低质量
float high = 1.0f; // 最高质量
float bestQuality = high;
long targetSize = targetFileSizeKB * 1024;
long bestFileSize = Long.MAX_VALUE;
while (high - low > 0.01f) { // 细化到 0.01
float mid = (low + high) / 2;
long compressedSize = saveTempCompressedImage(image, tempFilePath, mid);
if (Math.abs(compressedSize - targetSize) < targetSize * 0.05) {
return mid;
}
if (compressedSize > targetSize) {
high = mid;
} else {
low = mid;
}
if (compressedSize < bestFileSize) {
bestQuality = mid;
bestFileSize = compressedSize;
}
}
return bestQuality;
}
// 保存 JPEG 并返回文件大小
private static long saveTempCompressedImage(BufferedImage image, String tempFilePath, float quality) throws IOException {
File tempFile = new File(tempFilePath);
saveCompressedImage(image, tempFilePath, quality);
return tempFile.length();
}
// 保存最终压缩图片
private static void saveCompressedImage(BufferedImage image, String targetImagePath, float quality) throws IOException {
File outputFile = new File(targetImagePath);
OutputStream out = new FileOutputStream(outputFile);
ImageWriter writer = ImageIO.getImageWritersByFormatName("jpeg").next();
ImageWriteParam param = writer.getDefaultWriteParam();
// 设置 JPEG 压缩质量
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
param.setCompressionQuality(quality);
// 写入文件
writer.setOutput(ImageIO.createImageOutputStream(out));
writer.write(null, new IIOImage(image, null, null), param);
out.close();
}
}
调用如下
/**
* 压缩图片
* sourceImagePath:图片位置
* targetImagePath:图片压缩后的位置
*/
try {
String sourceImagePath = directoryPath+"/"+originalFileName;
String targetImagePath = directoryPath+"/thumbnail_"+originalFileName;
ImageCompressionUtil.compressImage(sourceImagePath, targetImagePath, 10);
}catch (Exception e){
e.printStackTrace();
}
662

被折叠的 条评论
为什么被折叠?



