某些图片需作下压缩处理,以便某些页面图片列表使用压缩图,从而提高页面图片的加载速度,图片压缩的时机可选在上传图片的时候(新增时)或者读取图片的时候。(对已有图片作压缩,历史数据)。访问图片的方法是在普通图片的前面加上尺寸前缀。如:http://xxx/image/100x100-compress-aaaaaaaaaaaaaaaaaaaaaaaaaaaa.jpg
图片压缩时机:
下面打开压缩图的办法是存在风险的,会导致图片无限增加。由于本项目是小圈子内的小群体使用。不存在该问题。如果要用,需要把catch里面的代码删除或者对可压缩的尺寸作下限制
public class ImageCompressionHelper {
@Autowired
private FileStoreService fileStoreService;
@Autowired
private FileInfoMapper fileInfoMapper;
public final static String COMPRESS_SEPARATOR = "-compress-";
public void compressionImage(String imgPxs, FileInfo fileInfo) {
String extName = fileInfo.getExtName();
String contextType;
if ("jpg".equalsIgnoreCase(extName)) {
contextType = MediaType.IMAGE_JPEG.toString();
} else if ("png".equalsIgnoreCase(extName)) {
contextType = MediaType.IMAGE_PNG.toString();
} else if ("jpeg".equalsIgnoreCase(extName)) {
contextType = MediaType.IMAGE_JPEG.toString();
} else {
return;
}
compressionImage(imgPxs, fileInfo, contextType);
}
public void compressionImage(String imgPxs, FileInfo fileInfo, String contextType) {
ImgCompressionPxs pxs = new ImgCompressionPxs(imgPxs);
if (ZYListUtils.isEmptyList(pxs)) {
return;
}
for (ImgCompressionPx px : pxs) {
InputStream objectStream = fileStoreService.getObjectStream(fileInfo.toFileWrapper());
if (null != objectStream) {
doCompress(objectStream, fileInfo, px, contextType);
}
}
}
private void doCompress(InputStream objectStream, FileInfo fileInfo, ImgCompressionPx px, String contextType) {
// 创建BufferedImage对象并加载原始图像数据
ByteArrayOutputStream exchangeStream = null;
InputStream expressImgInputStream = null;
try {
BufferedImage originalImage = ImageIO.read(objectStream);
// 设置目标图片大小(这里将图片按比例缩放为50%)
int targetWidth = (px.getWidth());
int targetHeight = (px.getHeight());
// 创建新的空白图像对象
BufferedImage compressedImage = new BufferedImage(targetWidth, targetHeight, originalImage.getType());
// 获得Graphics2D对象,用于操作图像55
Graphics2D g2d = compressedImage.createGraphics();
// 设置插值算法为双线性插值,提高图像质量
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
// 绘制缩放后的图像到compressedImage上
g2d.drawImage(originalImage, 0, 0, targetWidth, targetHeight, null);
g2d.dispose();
// 转成字节流,然后字节转成输入流
exchangeStream = new ByteArrayOutputStream();
ImageIO.write(compressedImage, fileInfo.getExtName(), exchangeStream);
byte[] bytes = exchangeStream.toByteArray();
expressImgInputStream = new ByteArrayInputStream(bytes);
// 包装下上传对象
FileWrapper fileWrapper = new FileWrapper();
fileWrapper.setInputStream(expressImgInputStream);
String expressImgId = px.getPx() + COMPRESS_SEPARATOR + fileInfo.getId();
fileWrapper.setId(expressImgId);
fileWrapper.setExtName(fileInfo.getExtName());
fileWrapper.setNewFileName(expressImgId + ZYStrUtils.DOT + fileInfo.getExtName());
fileWrapper.setFileSize(fileInfo.getFileSize());
fileWrapper.setOriginalFilename(fileInfo.getNewFileName());
fileWrapper.setContentType(contextType);
// 上传图片,此处用的是minio,不再展示细节了
fileStoreService.upload(fileWrapper);
// 保存文件基本信息
FileInfo compressFileInfo = new FileInfo(fileWrapper);
compressFileInfo.setIsKeepAlive(YES);
fileInfoMapper.insert(compressFileInfo);
} catch (Exception e) {
log.warn("图片压缩失败" + e.getMessage());
} finally {
IoUtil.close(objectStream);
IoUtil.close(exchangeStream);
IoUtil.close(expressImgInputStream);
}
}
}
ImgCompressionPxs 类:
@Data
public class ImgCompressionPxs extends ArrayList<ImgCompressionPx> {
public ImgCompressionPxs(String imgPxs) {
if (ZYStrUtils.isNull(imgPxs)) {
return;
}
// 100*200,200*400,400*600
List<String> pxs = ZYListUtils.str2List(imgPxs);
for (String px : pxs) {
this.add(new ImgCompressionPx(px));
}
}
}
@Data
public static class ImgCompressionPx {
private String px;
private Integer width;
private Integer height;
public ImgCompressionPx(String px) {
String[] xes = px.split("x");
if (xes.length != 2) {
throw new LocalException("压缩图片尺寸有误");
}
String widthStr = xes[0];
String heightStr = xes[1];
this.px = px;
this.width = ZYNumberUtils.toInt(widthStr);
this.height = ZYNumberUtils.toInt(heightStr);
if (null == this.width || null == this.height) {
throw new LocalException("压缩图片尺寸有误");
}
}
}