简介

我们在项目中经常会遇到图片上传的需求,如商品图片,但图片太大的话,在客户端加载太慢影响用户体验,所有一般会将图片进行压缩。

实现

原图


添加依赖

net.coobird

thumbnailator

0.4.8

按质量压缩

import java.io.File;
import java.io.FileOutputStream;
import net.coobird.thumbnailator.Thumbnails;
public class Client {
public static void main(String[] args) throws Exception {
Thumbnails.of(new File("D:/showqrcode.jpg"))
.scale(1f) //图片大小(长宽)压缩比例 从0-1,1表示原图
.outputQuality(0.5f) //图片质量压缩比例 从0-1,越接近1质量越好
.toOutputStream(new FileOutputStream("D:/showqrcode_50.jpg"));
}
}

压缩后图片


图片大小从665KB压缩到了77KB。

按比例缩放

import java.io.File;
import java.io.FileOutputStream;
import net.coobird.thumbnailator.Thumbnails;
public class Client2 {
public static void main(String[] args) throws Exception {
Thumbnails.of(new File("D:/showqrcode.jpg"))
.scale(0.5f) //图片大小(长宽)压缩 从0按照
.outputQuality(0.5f) //图片质量压缩比例 从0-1,越接近1质量越好
.toOutputStream(new FileOutputStream("D:/showqrcode_50%.jpg"));
}
}


按大小和比例缩放

import java.io.File;
import java.io.FileOutputStream;
import net.coobird.thumbnailator.Thumbnails;
public class Client21 {
public static void main(String[] args) throws Exception {
Thumbnails.of(new File("D:/showqrcode.jpg"))
.size(500, 300) // 图片比例不变
.toOutputStream(new FileOutputStream("D:/showqrcode_500_300.jpg"));
}
}


按大小缩放

import java.io.File;
import java.io.FileOutputStream;
import net.coobird.thumbnailator.Thumbnails;
public class Client22 {
public static void main(String[] args) throws Exception {
Thumbnails.of(new File("D:/showqrcode.jpg"))
.forceSize(500, 300) //不保持图片比例
.toOutputStream(new FileOutputStream("D:/showqrcode_500_300.jpg"));
}
}


旋转

import java.io.File;
import java.io.FileOutputStream;
import net.coobird.thumbnailator.Thumbnails;
public class Client3 {
public static void main(String[] args) throws Exception {
Thumbnails.of(new File("D:/showqrcode.jpg"))
.forceSize(500, 300)
.rotate(90f) //向右旋转
.toOutputStream(new FileOutputStream("D:/showqrcode+90.jpg"));
}
}


加水印

水印图片


import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.geometry.Positions;
public class Client4 {
public static void main(String[] args) throws IOException {
Thumbnails.of("D:/showqrcode.jpg")
.size(1280, 1024)
.watermark(Positions.BOTTOM_RIGHT, ImageIO.read(new File("D:/watermark.jpg")),
0.5f) //位置,水印来源,透明度
.outputQuality(0.8f)
.toFile("D:/showqrcode_watermark_bottom_right.jpg");
}
}


裁剪

import java.io.IOException;
import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.geometry.Positions;
public class Client5 {
public static void main(String[] args) throws IOException {
Thumbnails.of("D:/showqrcode.jpg")
.sourceRegion(Positions.CENTER, 800, 600) //位置,宽,高
.size(800, 600)
.keepAspectRatio(false)
.toFile("D:/showqrcode_region_center.jpg");
}
}


拼接

import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import javax.imageio.ImageIO;
public class Client6 {
public static void main(String[] args) throws Exception {
byte[] bytes = joinImages(false, new File("D:/showqrcode.jpg"), new File("D:/showqrcode.jpg"));
if (Objects.nonNull(bytes)) {
new ByteArrayInputStream(bytes).transferTo(new FileOutputStream("D:/showqrcode_join.jpg"));
}
}
/**
* 将多张图片拼接成一张
*
* @param horizontal 是否为水平拼接
* @param files 文件列表
* @return 拼接后的文件字节数组
*/
private static byte[] joinImages(boolean horizontal, File... files) throws IOException {
if (Objects.isNull(files) || files.length == 0) {
return null;
}
List imageList = new ArrayList<>();
for (File file : files) {
BufferedImage image = ImageIO.read(file);
imageList.add(image);
}
int height = imageList.get(0).getHeight();
int width = imageList.get(0).getWidth();
if (horizontal) {
width = imageList.stream().mapToInt(BufferedImage::getWidth).sum();
} else {
height = imageList.stream().mapToInt(BufferedImage::getHeight).sum();
}
//创建拼接后的图片画布,参数分别为宽,高,类型,这里我们使用RGB3元色类型
BufferedImage resultImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics graphics = resultImage.getGraphics();
int previousWidth = 0;
int previousHeight = 0;
for (BufferedImage image : imageList) {
//向画布上画图片
graphics.drawImage(image, previousWidth, previousHeight, null);
if (horizontal) {
previousWidth += image.getWidth();
} else {
previousHeight += image.getHeight();
}
}
ByteArrayOutputStream output = new ByteArrayOutputStream();
ImageIO.write(resultImage, "jpg", output);
return output.toByteArray();
}
}


更多用法请参考官方文档

总结

图片经过以上处理之后都会去除EXIF信息,关于EXIF详情,请查看java获取图片的GPS信息