图片压缩是 Web 开发中常见的需求,用于减少图片体积、提升加载速度(尤其在移动端场景)。toolkit-image
是一款封装了 Thumbnails 工具的 Java 库,提供简洁 API 实现图片压缩、尺寸调整等功能。本文将详细讲解其依赖配置、核心用法、优化技巧及扩展场景,帮助你快速集成图片压缩功能。
工具选型与优势 toolkit-image
基于 Google 的 thumbnailator
封装,相比原生工具具有以下优势:
API 简洁 :一行代码实现压缩、尺寸调整、格式转换,无需处理复杂的 IO 流;
功能全面 :支持按尺寸、比例、质量压缩,适配常见图片格式(PNG、JPG、GIF 等);
低侵入性 :轻量级依赖,无冗余组件,易于集成到 Spring Boot、普通 Java 项目。
核心依赖说明 toolkit-image
的核心功能依赖 thumbnailator
(图片处理)和 commons-io
(IO 工具),引入时无需手动添加这些依赖(Maven 会自动传递)。
环境配置与依赖引入 Maven 依赖配置 在 pom.xml
中添加 toolkit-image
依赖:
1 2 3 4 5 <dependency > <groupId > com.siashan</groupId > <artifactId > toolkit-image</artifactId > <version > 1.1.9</version > </dependency >
版本兼容性
支持 Java 8 及以上版本;
兼容常见图片格式(PNG、JPG、BMP、GIF),其中 GIF 压缩可能损失动画效果(需特殊处理)。
核心功能:图片压缩实战 按尺寸压缩(固定宽高) 指定目标宽高压缩图片,自动保持比例(避免拉伸变形),适用于头像、缩略图等场景。
代码示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 import com.siashan.image.ToolkitImage; import net.coobird.thumbnailator.Thumbnails; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; public class ImageCompressDemo { public static void compressBySize (String inputPath, int targetWidth, int targetHeight, String outputPath, String format) { try { Thumbnails.of(inputPath) .size(targetWidth, targetHeight) .outputFormat(format) .toFile(outputPath); System.out.println("压缩完成,保存路径:" + outputPath); } catch (IOException e) { System.err.println("压缩失败:" + e.getMessage()); e.printStackTrace(); } } public static void main (String[] args) { compressBySize( "/Users/example/原图.png" , 1000 , 1000 , "/Users/example/压缩图.png" , "png" ); } }
按比例压缩(缩放比例) 按指定比例(如 50%)压缩图片,无需手动计算宽高,适用于自适应场景。
代码示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public static void compressByScale (String inputPath, double scale, String outputPath, String format) { try { Thumbnails.of(inputPath) .scale(scale) .outputFormat(format) .toFile(outputPath); } catch (IOException e) { e.printStackTrace(); } } compressByScale("/Users/example/原图.jpg" , 0.5 , "/Users/example/比例压缩.jpg" , "jpg" );
按质量压缩(控制体积) 通过 outputQuality
控制压缩质量(0.0-1.0),适用于需要严格控制图片体积的场景(如移动端上传)。
代码示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public static void compressByQuality (String inputPath, double quality, String outputPath) { try { Thumbnails.of(inputPath) .scale(1.0 ) .outputQuality(quality) .toFile(outputPath); } catch (IOException e) { e.printStackTrace(); } } compressByQuality("/Users/example/原图.jpg" , 0.5 , "/Users/example/质量压缩.jpg" );
格式转换(如 PNG 转 JPG) 压缩时可同时转换图片格式,利用不同格式的压缩特性(如 JPG 比 PNG 体积更小)。
代码示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public static void convertFormat (String inputPath, String outputPath, String format) { try { Thumbnails.of(inputPath) .size(1200 , 800 ) .outputFormat(format) .toFile(outputPath); } catch (IOException e) { e.printStackTrace(); } } convertFormat("/Users/example/原图.png" , "/Users/example/转格式.jpg" , "jpg" );
高级功能:自定义压缩策略 保持宽高比(避免拉伸) size(width, height)
方法默认按 “最短边” 缩放,确保图片不变形。若需强制固定尺寸(允许拉伸),可结合 keepAspectRatio(false)
:
1 2 3 4 5 Thumbnails.of(inputPath) .size(800 , 600 ) .keepAspectRatio(false ) .toFile(outputPath);
压缩为字节流(用于网络传输) 将压缩后的图片转为 byte[]
,适用于上传至对象存储(如 OSS)或通过接口返回:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public static byte [] compressToBytes(String inputPath, int width, int height) { try (ByteArrayOutputStream out = new ByteArrayOutputStream()) { Thumbnails.of(inputPath) .size(width, height) .toOutputStream(out); return out.toByteArray(); } catch (IOException e) { e.printStackTrace(); return null ; } } byte [] imageBytes = compressToBytes("/Users/example/原图.jpg" , 800 , 600 ); ossClient.putObject("bucket-name" , "image.jpg" , new ByteArrayInputStream(imageBytes));
批量压缩图片 遍历目录下的所有图片,批量压缩并保存到目标目录:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import java.io.File; public static void batchCompress (String inputDir, String outputDir, int targetWidth) { File dir = new File(inputDir); File[] files = dir.listFiles((file) -> { String name = file.getName().toLowerCase(); return name.endsWith(".png" ) || name.endsWith(".jpg" ) || name.endsWith(".jpeg" ); }); if (files == null ) return ; new File(outputDir).mkdirs(); for (File file : files) { String outputPath = outputDir + File.separator + file.getName(); String format = file.getName().substring(file.getName().lastIndexOf("." ) + 1 ); compressBySize(file.getPath(), targetWidth, 0 , outputPath, format); } }
常见问题与解决方案 1. PNG 压缩后体积变大
原因 :PNG 是无损压缩格式,若压缩时尺寸不变或质量设置过高,可能因编码方式导致体积略增;
解决 :结合尺寸压缩(缩小宽高)或转为 JPG 格式(牺牲透明度换取更小体积)。
2. 压缩后图片失真严重
原因 :outputQuality
设置过低(如 <0.3),或尺寸压缩比例过大;
解决 :
保持 outputQuality >= 0.5
(JPG 格式);
按比例压缩时,确保目标尺寸不小于原图的 50%。
3. GIF 动图压缩后变成静态图
原因 :thumbnailator
对 GIF 动图支持有限,默认只保留第一帧;
解决 :使用专门的 GIF 处理库(如 gif4j
),或在压缩前转为视频格式。
4. 大图片压缩耗时过长
原因 :处理 10MB 以上的高清图片时,IO 和计算开销较大;
解决 :
异步处理(如通过线程池或消息队列),避免阻塞主线程;
分阶段压缩:先按比例缩小尺寸,再调整质量。
生产环境最佳实践 压缩策略建议
场景
推荐压缩方式
参数示例
头像 / 缩略图
按尺寸压缩(固定宽高)
宽 200px,高 200px
文章配图
按比例压缩(保留清晰度)
缩放 70%,质量 80%
移动端上传
尺寸 + 质量结合(严格控体积)
宽 1200px,质量 60%
异常处理与日志
捕获 IOException
并记录详细日志(如输入路径、错误原因),便于排查问题;
压缩前校验文件是否存在、是否为图片格式,避免无效操作。
性能优化
v1.3.10