背景
对于javaweb服务端开发人员,图片资源的管理总是绕不开的一环。很多网站上都会提供上传图片这个功能,而现代数码设备拍摄出来的都是高清图片,分辨率很高,占用的空间也很大。物理存储的问题还算容易解决,但是网络带宽太紧张了。一个页面动则就几十M,那加载速度就会很慢,所以图片的压缩就必不可少了。
图片压缩要求
- 压缩程度可控。
- 压缩之后图片尽可能的不失真。
- 压缩速度要快。
- 代码简单,依赖较少。
技术选型
目前处理图片主流的有两种,第一种依赖环境需要安装imageMagick和GraphicsMagick,第二种是使用Thumbnailator类库,相对来说Thumbnailator在处理图片的时候还原度没有第一种的好,不过胜在实现简单,且能满足绝大多数的情况。
Thumbnailator简介
对于图片处理,JDK中也提供了对应的工具类,不过处理起来会很麻烦,而Thumbnailator是一个Google开源的优秀图片处理的第三方Java类库,处理效果远比Java API的好。
Thumbnailator可以使用很少的代码实现图片的压缩功能,当然了,Thumbnailator也提供给图片缩放、旋转与加水印等功能。
使用方式
github地址
https://github.com/coobird/thumbnailator
maven的地址
maven引入jar文件
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.8</version>
</dependency>
示例
示例1:
在目录中创建图像文件的JPEG缩略图,将它们全部调整为最大尺寸为640像素乘480像素,同时保留原始图像的长宽比。
public static void main(String[] args) throws IOException {
String filePath = "C:\\Users\\shunli\\Desktop\\Thumbnailator";
Thumbnails.of(new File(filePath).listFiles())
.size(640, 480)
.outputFormat("jpg")
.toFiles(Rename.PREFIX_DOT_THUMBNAIL);
}
Thumbnailator提供的流畅接口简化了将缩略图制作为单个方法调用的任务!
无需访问Image I / O API并BufferedImage通过Graphics2D对象手动操作。Thumbnailator为您完成所有这些工作。
效果
示例二:
从图像文件创建缩略图:将Img1.jpg调整图片的大小,然后保存到Img1_thumbnail.jpg。
public static void main(String[] args) throws IOException {
String filePath = "C:\\Users\\shunli\\Desktop\\Thumbnailator\\Img1.jpg";
String newFilePath = "C:\\Users\\shunli\\Desktop\\Thumbnailator\\Img1_thumbnail.jpg";
Thumbnails.of(new File(filePath))
.size(640, 480)
.toFile(new File(newFilePath));
}
或者,Img1_thumbnail将接受文件名作为String。File不需要使用对象来指定图像文件:
public static void main(String[] args) throws IOException {
String filePath = "C:\\Users\\shunli\\Desktop\\Thumbnailator\\Img1.jpg";
String newFilePath = "C:\\Users\\shunli\\Desktop\\Thumbnailator\\Img1_thumbnail.jpg";
Thumbnails.of(filePath)
.size(640, 480)
.toFile(newFilePath);
在编写快速的原型代码时,或者在脚本语言中使用Thumbnailator时,此格式很有用。
示例三:
图片旋转
//scale
Thumbnails.of("原图文件的路径")
.scale(0.8)
.rotate(90)
.toFile("转换后文件的路径");
//size
Thumbnails.of(“原图文件的路径”)
.size(40,40)
.rotate(90)
.toFile(“转换后文件的路径”);
其中,
rotate(角度): 正数:顺时针 负数:逆时针
scale,size 必须有一个有值
加水印
File image = new File("水印图片地址");
Thumbnails.of("原图文件的路径")
.scale(0.8)
.watermark(Positions.BOTTOM_RIGHT, ImageIO.read(image), 0.5f)
.toFile("转换后文件的路径");
其中
Watermark:添加水印 watermark(位置,水印图,透明度)
创建带有旋转和水印的缩略图
String filePath = "C:\\Users\\shunli\\Desktop\\Thumbnailator\\Img1.jpg";
String newFilePath = "C:\\Users\\shunli\\Desktop\\Thumbnailator\\Img1_thumbnail.jpg";
String watermark = "C:\\Users\\shunli\\Desktop\\Thumbnailator\\Img2.jpg";
Thumbnails.of(new File(filePath))
.size(640, 480)
.rotate(90)//顺时针旋转90度
.watermark(Positions.BOTTOM_RIGHT, ImageIO.read(new File(watermark)), 0.7f)//水印
.outputQuality(0.8)
.toFile(new File(newFilePath));
}
在此示例中,将Img1.jpg调整图片的大小,然后将其顺时针旋转90度,然后在右下角放置半透明(0.7f)的水印,然后将其保存为Img1_thumbnail.jpg 80%的压缩质量设置。
示例四:
创建缩略图并写入 OutputStream
OutputStream os = ...;
Thumbnails.of("large-picture.jpg")
.size(200, 200)
.outputFormat("png")
.toOutputStream(os);
在此示例中,文件中的图像large-picture.jpg被调整为最大尺寸为200 x 200(保持原始图像的纵横比),并将该图像写入指定OutputStream的PNG图像中。
示例五
创建固定大小的缩略图
BufferedImage originalImage = ImageIO.read(new File("original.png"));
BufferedImage thumbnail = Thumbnails.of(originalImage)
.size(200, 200)
.asBufferedImage();
上面的代码使用拍摄图像,originalImage并使用创建一个200像素乘200像素的缩略图,并将结果存储在中thumbnail。
或者,thumbnail将接受文件名作为String。File不需要使用对象来指定图像文件:
Thumbnails.of("原图文件的路径")
.size(100, 75)
.toFile("压缩后文件的路径");
示例六:
按给定因子缩放图像
BufferedImage originalImage = ImageIO.read(new File("original.png"));
BufferedImage thumbnail = Thumbnails.of(originalImage)
.scale(0.25)
.asBufferedImage();
上面的代码将图像originalImage导入,并创建一个占原始图像25%的缩略图,并使用默认的缩放技术以制作存储在中的缩略图thumbnail。
或者,thumbnail将接受文件名作为String。File不需要使用对象来指定图像文件:
Thumbnails.of("原图文件的路径")
.scale(0.5)
.toFile("压缩后文件的路径");
示例七:
创建缩略图时旋转图像
BufferedImage originalImage = ImageIO.read(new File("original.jpg"));
BufferedImage thumbnail = Thumbnails.of(originalImage)
.size(200, 200)
.rotate(90)
.asBufferedImage();
上面的代码获取原始图像并创建一个缩略图,该缩略图将顺时针旋转90度。
示例八:
创建带有水印的缩略图
BufferedImage originalImage = ImageIO.read(new File("original.jpg"));
BufferedImage watermarkImage = ImageIO.read(new File("watermark.png"));
BufferedImage thumbnail = Thumbnails.of(originalImage)
.size(200, 200)
.watermark(Positions.BOTTOM_RIGHT, watermarkImage, 0.5f)
.asBufferedImage();
如图所示,可以通过调用该watermark方法将水印添加到缩略图。
可以从Positions枚举中选择位置。
可以通过更改最后一个参数来调整缩略图的不透明度(或相反,透明度),最后一个参数0.0f是缩略图完全透明,而1.0f水印则完全不透明。
示例九:
将缩略图写入特定目录
File destinationDir = new File("path/to/output");
Thumbnails.of("apple.jpg", "banana.jpg", "cherry.jpg")
.size(200, 200)
.toFiles(destinationDir, Rename.PREFIX_DOT_THUMBNAIL);
本示例将获取源图像,并将缩略图作为文件写到destinationDir(path/to/output目录),同时thumbnail.以文件名开头重命名它们。
因此,缩略图将作为文件写入:
path/to/output/thumbnail.apple.jpg
path/to/output/thumbnail.banana.jpg
path/to/output/thumbnail.cherry.jpg
在写入指定目录时,还可以保留原始文件名:
File destinationDir = new File("path/to/output");
Thumbnails.of("apple.jpg", "banana.jpg", "cherry.jpg")
.size(200, 200)
.toFiles(destinationDir, Rename.NO_CHANGE);
在上面的代码中,缩略图将被写入:
path/to/output/apple.jpg
path/to/output/banana.jpg
path/to/output/cherry.jpg
示例十:
设置宽高最大值,等比例缩小
Thumbnails.of("原图文件的路径")
.scale(1.0, 0.5)
.toFile("压缩后文件的路径");
设置宽为原图100%,高为原图50%,非等比例缩放
其中,
- scale: 按照比例进行缩放。范围:0.0~N。
- scale(0.5) 宽高比例都是50%缩放 , scale(1,0.5) 宽不变,高为50%缩放
- size:指定大小进行缩放 size(100, 75)
若图片宽比100小,高比75小,不变
若图片宽比100小,高比75大,高缩小到75,图片比例不变
若图片宽比100大,高比75小,宽缩小到100,图片比例不变
若图片宽比100大,高比100大,图片按比例缩小,宽缩小到100或高缩小到75,但要保证宽小于等于100,高小于等于75
修改文件格式
Thumbnails.of(“原图文件的路径”)
.scale(1f)
.outputFormat(“jpg”)
.toFile(“转换后文件的路径”);
其中,
outputFormat:设置转换后图片格式,之前听说该属性设置为png时,scale缩放属性无效,测试用0.4.8的版本已经能正常缩放了
不改变宽高,压缩大小
Thumbnails.of("原图文件的路径")
.scale(1f)
.outputQuality(0.5f)
.toFile("压缩后文件的路径");
其中,
outputQuality: 输出的图片质量,范围:0.0~1.0,1为最高质量.