本文目录导读:

我来详细介绍Java压缩本地图片的几种常用方法。
使用ImageIO(JDK自带)
基本压缩示例
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageOutputStream;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class ImageCompressExample {
public static void compressImage(String sourcePath, String targetPath, float quality) throws IOException {
// 读取原始图片
File sourceFile = new File(sourcePath);
BufferedImage originalImage = ImageIO.read(sourceFile);
// 获取输出流
FileOutputStream fos = new FileOutputStream(targetPath);
ImageOutputStream ios = ImageIO.createImageOutputStream(fos);
// 获取JPEG写入器
ImageWriter writer = ImageIO.getImageWritersByFormatName("jpg").next();
writer.setOutput(ios);
// 设置压缩参数
ImageWriteParam param = writer.getDefaultWriteParam();
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
param.setCompressionQuality(quality); // 0.0-1.0,值越小压缩越大
// 写入图像
writer.write(null, new javax.imageio.IIOImage(originalImage, null, null), param);
// 关闭资源
writer.dispose();
ios.close();
fos.close();
}
public static void main(String[] args) {
try {
compressImage("input.jpg", "output.jpg", 0.5f);
System.out.println("图片压缩完成!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
使用Thumbnails库(推荐)
添加Maven依赖
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.19</version>
</dependency>
压缩示例
import net.coobird.thumbnailator.Thumbnails;
import java.io.File;
import java.io.IOException;
public class ThumbnailsCompressExample {
/**
* 按质量压缩
*/
public static void compressByQuality(String sourcePath, String targetPath, float quality) throws IOException {
Thumbnails.of(sourcePath)
.scale(1f) // 保持原尺寸
.outputQuality(quality) // 压缩质量 0.0-1.0
.toFile(targetPath);
}
/**
* 按尺寸压缩
*/
public static void compressBySize(String sourcePath, String targetPath, int width, int height) throws IOException {
Thumbnails.of(sourcePath)
.size(width, height)
.outputQuality(0.8f)
.toFile(targetPath);
}
/**
* 按比例压缩
*/
public static void compressByScale(String sourcePath, String targetPath, double scale) throws IOException {
Thumbnails.of(sourcePath)
.scale(scale) // 0.0-1.0
.outputQuality(0.8f)
.toFile(targetPath);
}
/**
* 批量压缩
*/
public static void batchCompress(String sourceDir, String targetDir, float quality) throws IOException {
File[] files = new File(sourceDir).listFiles((dir, name) ->
name.toLowerCase().endsWith(".jpg") || name.toLowerCase().endsWith(".png")
);
if (files != null) {
for (File file : files) {
String targetPath = targetDir + File.separator + "compressed_" + file.getName();
compressByQuality(file.getAbsolutePath(), targetPath, quality);
System.out.println("压缩完成: " + file.getName());
}
}
}
public static void main(String[] args) {
try {
// 按质量压缩
compressByQuality("input.jpg", "output_quality.jpg", 0.5f);
// 按尺寸压缩
compressBySize("input.jpg", "output_size.jpg", 800, 600);
// 按比例压缩
compressByScale("input.jpg", "output_scale.jpg", 0.5);
System.out.println("压缩完成!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
完整压缩工具类
import javax.imageio.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.Iterator;
public class ImageCompressUtil {
/**
* 图片压缩综合方法
* @param sourcePath 源文件路径
* @param targetPath 目标文件路径
* @param maxSize 最大文件大小(字节)
* @param maxWidth 最大宽度
* @param maxHeight 最大高度
*/
public static void compressImage(String sourcePath, String targetPath,
long maxSize, int maxWidth, int maxHeight) throws IOException {
File sourceFile = new File(sourcePath);
File targetFile = new File(targetPath);
// 读取原始图片
BufferedImage originalImage = ImageIO.read(sourceFile);
// 计算缩放尺寸
int width = originalImage.getWidth();
int height = originalImage.getHeight();
// 限制尺寸
if (width > maxWidth) {
height = (int) (height * (double) maxWidth / width);
width = maxWidth;
}
if (height > maxHeight) {
width = (int) (width * (double) maxHeight / height);
height = maxHeight;
}
// 缩放图片
BufferedImage scaledImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g = scaledImage.createGraphics();
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.drawImage(originalImage, 0, 0, width, height, null);
g.dispose();
// 压缩质量调整
float quality = 0.8f;
String formatName = getFormatName(sourcePath);
// 获取写入器
Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(formatName);
ImageWriter writer = writers.next();
// 设置输出
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageOutputStream ios = ImageIO.createImageOutputStream(baos)) {
writer.setOutput(ios);
// 设置压缩参数
ImageWriteParam param = writer.getDefaultWriteParam();
if (param.canWriteCompressed()) {
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
param.setCompressionQuality(quality);
}
// 写入图像
writer.write(null, new IIOImage(scaledImage, null, null), param);
// 检查文件大小,如果太大则降低质量
byte[] imageBytes = baos.toByteArray();
while (imageBytes.length > maxSize && quality > 0.1f) {
quality -= 0.1f;
baos.reset();
try (ImageOutputStream ios2 = ImageIO.createImageOutputStream(baos)) {
writer.setOutput(ios2);
param.setCompressionQuality(quality);
writer.write(null, new IIOImage(scaledImage, null, null), param);
imageBytes = baos.toByteArray();
}
}
// 写入目标文件
try (FileOutputStream fos = new FileOutputStream(targetFile)) {
fos.write(imageBytes);
}
}
writer.dispose();
}
/**
* 获取格式名称
*/
private static String getFormatName(String fileName) {
String extension = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
if ("jpg".equals(extension) || "jpeg".equals(extension)) {
return "jpg";
} else if ("png".equals(extension)) {
return "png";
} else if ("gif".equals(extension)) {
return "gif";
}
return "jpg";
}
/**
* 简单的质量压缩
*/
public static void simpleCompress(String sourcePath, String targetPath, float quality) throws IOException {
BufferedImage image = ImageIO.read(new File(sourcePath));
compressImageWithQuality(image, targetPath, quality);
}
private static void compressImageWithQuality(BufferedImage image, String targetPath, float quality) throws IOException {
File targetFile = new File(targetPath);
String formatName = getFormatName(targetPath);
Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(formatName);
ImageWriter writer = writers.next();
try (FileOutputStream fos = new FileOutputStream(targetFile);
ImageOutputStream ios = ImageIO.createImageOutputStream(fos)) {
writer.setOutput(ios);
ImageWriteParam param = writer.getDefaultWriteParam();
if (param.canWriteCompressed()) {
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
param.setCompressionQuality(quality);
}
writer.write(null, new IIOImage(image, null, null), param);
}
writer.dispose();
}
public static void main(String[] args) {
try {
// 综合压缩
compressImage("input.jpg", "output.jpg",
500 * 1024, // 最大500KB
1920, // 最大宽度
1080); // 最大高度
System.out.println("压缩完成!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
推荐使用方式
对于大多数场景,推荐使用 Thumbnails库,因为它:
- API简洁易用
- 支持多种压缩方式
- 性能优秀
- 内存管理好
如果不想引入第三方依赖,可以使用JDK自带的ImageIO,但需要更多的代码来确保质量和性能。
注意事项
- 质量选择:quality值0.0-1.0,一般建议0.5-0.8
- 格式选择:JPEG适合照片,PNG适合图标和文字
- 内存管理:处理大图片时注意JVM内存设置
- 异常处理:图片损坏或格式不支持时需要捕获异常
- 线程安全:ImageWriter不是线程安全的,多线程环境下需要各自创建实例