图片压缩主要分为两种类型:有损压缩和无损压缩
- 有损压缩:有损压缩通过减少图片中的几余数据来减小图片文件的大小,但会损失定的图片质量。常见的有损压缩算法有JPEG、WebP等。
- 无损压缩:无损压缩通过优化图片的编码算法来减小图片文件的大小,但不会损失任何图片质量。常见的无损压缩算法有PNG、GIF等
对于需要压缩至指定大小的需求,我们可以使用有损压缩算法,并通过不断尝试不同的压缩质量来达到目标大小。
官网地址
参考地址
net.coobird
thumbnailator
0.4.19
要使用thumbnailtor,主要使用Thumbnails类,该类采用建造者模式设计,类中提供了很多返回Builder的静态方法。
正如下图所示,Thumbnails提供了通过字符串图片地址、File对象、URI对象等方式创建Thumbnails对象的方式。
* =============of方法=============
* scale 代表缩放
* toFile是输出图片的方法
*/
@Test
public void test() throws IOException {
//参数是本地文件路径,支持多参数
Thumbnails.of("C:\\Users\\Administrator\\Desktop\\新建文件夹\\1.png")
.scale(1D)
.toFile("C:\\Users\\Administrator\\Desktop\\新建文件夹\\3.png");
}
@Test
public void test2() throws IOException {
// File类型的参数,支持多参数
Thumbnails.of(new File("C:\\Users\\Administrator\\Desktop\\新建文件夹\\1.png"))
.scale(1D)
.toFile(new File("C:\\Users\\Administrator\\Desktop\\新建文件夹\\4.png"));
}
@Test
public void test3() throws IOException {
// BufferedImage类型参数
BufferedImage bufferedImage = ImageIO.read(new File("C:\\Users\\Administrator\\Desktop\\新建文件夹\\1.png"));
Thumbnails.of(bufferedImage)
.scale(1D)
.toFile(new File("C:\\Users\\Administrator\\Desktop\\新建文件夹\\5.jpg"));
}
@Test
public void test4() throws IOException {
// FileInputStream类型
InputStream inputStream = new FileInputStream(new File("C:\\Users\\Administrator\\Desktop\\新建文件夹\\1.png"));
Thumbnails.of(inputStream)
.scale(1D)
.toFile(new File("C:\\Users\\Administrator\\Desktop\\新建文件夹\\7.jpg"));
}
@Test
public void test5() throws IOException {
// 网络图片
URL url = new URL("https://img1.baidu.com/it/u=1546227440,2897989905&fm=253&fmt=auto&app=138&f=JPEG?w=889&h=500");
Thumbnails.of(url)
.scale(1D)
.toFile(new File("C:\\Users\\Administrator\\Desktop\\新建文件夹\\8.jpg"));
}
/**
* =============fromImages方法。批量处理BufferedImage类型的图片 =============
* scale 代表缩放
* toFile是输出图片的方法
*/
@Test
public void test8() throws IOException {
// 参数是本地文件路径,支持多参数
URL url = new URL("https://lmg.jj20.com/up/allimg/1114/0406210Z024/2104060Z024-5-1200.jpg");
URL url2 = new URL("https://lmg.jj20.com/up/allimg/4k/s/02/210924233115O14-0-lp.jpg");
BufferedImage bufferedImage1 = ImageIO.read(url);
BufferedImage bufferedImage2 = ImageIO.read(url2);
List<BufferedImage> list = new ArrayList<>();
list.add(bufferedImage1);
list.add(bufferedImage2);
File file = new File("C:\\Users\\Administrator\\Desktop\\新建文件夹\\listD\\11.png");
File file2 = new File("C:\\Users\\Administrator\\Desktop\\新建文件夹\\listD\\22.png");
List<File> files = new ArrayList<>();
files.add(file);
files.add(file2);
Thumbnails.fromImages(list)
.scale(1D)
// 这里必须使用`toFiles`,因为处理的是多图
.toFiles(files);//Rename.SUFFIX_HYPHEN_THUMBNAIL 这里用这个会报错,注意.
}
/**
* =============fromInputStreams 方法。批量处理InputStream类型的图片。 =============
* scale 代表缩放
* toFile是输出图片的方法
*/
@Test
public void test9() throws IOException, URISyntaxException {
// 参数是本地文件路径,支持多参数
FileInputStream fileInputStream1 = new FileInputStream(new File("C:\\Users\\Administrator\\Desktop\\新建文件夹\\listD\\11.png"));
FileInputStream fileInputStream2 = new FileInputStream(new File("C:\\Users\\Administrator\\Desktop\\新建文件夹\\listD\\22.png"));
List<InputStream> list = new ArrayList<>();
list.add(fileInputStream1);
list.add(fileInputStream2);
File file = new File("C:\\Users\\Administrator\\Desktop\\新建文件夹\\listD\\111.png");
File file2 = new File("C:\\Users\\Administrator\\Desktop\\新建文件夹\\listD\\222.png");
List<File> files = new ArrayList<>();
files.add(file);
files.add(file2);
Thumbnails.fromInputStreams(list)
.scale(1D)
// 这里必须使用`toFiles`,因为处理的是多图
.toFiles(files);//Rename.SUFFIX_HYPHEN_THUMBNAIL 这里用这个会报错,注意.
}
图片尺寸控制可以通过width、height,size, forceSize,scale方法控制。
比如原图高大于宽,则 size宽设置失效,否则相反
@Test
//等比例缩放,
//源:宽:681,长:563,长宽比:0.8267254038 压缩结果:宽:110,高:91,长宽比:0.8272727273
public void test10() throws IOException {
//参数是本地文件路径,支持多参数
Thumbnails.of("C:\\Users\\Administrator\\Desktop\\新建文件夹\\1.png")
.size(110, 900)
.toFile("C:\\Users\\Administrator\\Desktop\\新建文件夹\\44.png");
}
@Test
//forceSize方法
//源:宽:681,长:563,长宽比:0.8267254038 压缩到:宽:50,
public void test11() throws IOException {
//参数是本地文件路径,支持多参数
Thumbnails.of("C:\\Users\\Administrator\\Desktop\\新建文件夹\\1.png")
.forceSize(50, 50)
.toFile("C:\\Users\\Administrator\\Desktop\\新建文件夹\\test11.png");
}
@Test
//scale 方法
//源:宽:681,长:563,长宽比:0.8267254038 压缩到:宽681/2 ,高563/2,
public void test12() throws IOException {
//参数是本地文件路径,支持多参数
Thumbnails.of("C:\\Users\\Administrator\\Desktop\\新建文件夹\\1.png")
.scale(0.5)
.toFile("C:\\Users\\Administrator\\Desktop\\新建文件夹\\test22.png");
}
@Test
//rotate 方法
//源:宽:681,长:563,长宽比:0.8267254038 压缩到:宽681/2 ,高563/2,
public void test13() throws IOException {
//参数是本地文件路径,支持多参数
Thumbnails.of("C:\\Users\\Administrator\\Desktop\\新建文件夹\\1.png")
.rotate(30) // 旋转30度
.scale(0.5)
.toFile("C:\\Users\\Administrator\\Desktop\\新建文件夹\\test22.png");
}
@Test
//watermark 方法
public void test14() throws IOException {
//参数是本地文件路径,支持多参数
Thumbnails.of("C:\\Users\\Administrator\\Desktop\\新建文件夹\\1.png")
// 水印放到右下角
.watermark(Positions.BOTTOM_RIGHT, ImageIO.read(new File("C:\\Users\\Administrator\\Desktop\\新建文件夹\\watermark.jpg")), 0.5f)
.scale(1D)
.toFile("C:\\Users\\Administrator\\Desktop\\新建文件夹\\test14.png");
}
outputFormat控制输出格式
outputQuality(float quality)设置输出质量,参数介于0和1之间,支持小数,数字越小质量越差
@Test
/**
* outputFormat 方法
* outputFormat(String format)方法用于设置输出文件格式。支持的格式可以通过ImageIO.getWriterFormatNames()获取。
* 常用: JPG jpg tiff bmp BMP gif GIF WBMP png PNG JPEG tif TIF TIFF jpeg wbmp。
*
* outputQuality(float quality)设置输出质量,参数介于0和1之间,支持小数,数字越小质量越差。
*/
public void test15() throws IOException {
//参数是本地文件路径,支持多参数
Thumbnails.of("C:\\Users\\Administrator\\Desktop\\新建文件夹\\1.png")
// 如果不设置默认跟原图片一致
.outputFormat("jpg")
// 设置质量 0.1F-1F之间
.outputQuality(0.1F)
.scale(1D)
.toFile("C:\\Users\\Administrator\\Desktop\\新建文件夹\\test15");
}
toFile方法,将处理后的文件输出到指定文件,参数是文件路径,不是必须要指定文件后缀。
toFile要求文件读入的时候必须是单个源,例如如果是Thumbnails.of(“input/logo.jpg”,“input/logo2.jpg”),使用toFile输出会抛出异常。
public void toFiles(File destinationDir, Rename rename) throws IOException // ①
public void toFiles(Rename rename) throws IOException // ②
public void toFiles(Iterable iterable) throws IOException { // ③
/**
* public void toFiles(File destinationDir, Rename rename) throws IOException // **********只有file类型输入才可以用************
* 第一个参数是文件夹路径,第二个参数是文件名处理类型
* NO_CHANGE:文件名不修改。
* PREFIX_DOT_THUMBNAIL:追加 thumbnail.到文件名的开头。例如,给定 picture.jpg,结果为thumbnail.picture.jpg。
* SUFFIX_DOT_THUMBNAIL:.thumbnail追加到文件扩展名之前的文件名。例如,给定 picture.jpg,结果为 picture.thumbnail.jpg
* SUFFIX_HYPHEN_THUMBNAIL:-thumbnail追加到文件扩展名之前的文件名。例如,给定 picture.jpg,结果为 picture-thumbnail.jpg。
*
*
* public void toFiles(Rename rename) throws IOException // ②
* 此方法是①的简化,等价于①中的第一个参数destinationDir为空。
*
* public void toFiles(Iterable iterable) throws IOException { // ③
* 参数是Iterable类型,也就是说可以给每个文件设置输出文件名。
*/
@Test
//输出到多输出流
public void toOutPUtStreamTest2() throws IOException {
OutputStream os = new FileOutputStream("C:\\Users\\Administrator\\Desktop\\新建文件夹\\55.png");
OutputStream os2 = new FileOutputStream("C:\\Users\\Administrator\\Desktop\\新建文件夹\\66.png");
List<OutputStream> list=new ArrayList<>();
list.add(os);
list.add(os2);
Thumbnails.of("C:\\Users\\Administrator\\Desktop\\新建文件夹\\1.png")
.scale(1D)
.toOutputStreams(list);
}
toFiles有三种多态方法
ByteArrayOutputStream
ByteArrayInputStream
@Test
//输出到内存输出流
public void toOutPUtStreamTest3() throws IOException {
ByteArrayOutputStream os = new ByteArrayOutputStream();//内存输出流
Thumbnails.of("F:\\company2\\浙江\\02-需求开发\\23年12月\\图片附件上传问题\\2.jpg")
.scale(1D)
.toOutputStream(os);
// os.writeTo(new FileOutputStream(new File("C:\\Users\\Administrator\\Desktop\\新建文件夹\\66.png")));//直接输出
ByteArrayInputStream inputStream = new ByteArrayInputStream(os.toByteArray());//转化为内存输入流
Thumbnails.of(inputStream)
.size(200,220)
.outputQuality(1D)
.toFile("F:\\company2\\浙江\\02-需求开发\\23年12月\\图片附件上传问题\\99");
}