最近工作中涉及图片压缩相关的操作,需求如下:
大于2MB的图片需要压缩到2MB以下,且不改变原图的尺寸
引入依赖:
dependency
groupIdnet.coobird/groupId
artifactIdthumbnailator/artifactId
version0.4.8/version
/dependency
附件实体类:
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Data
public class FileCO {
private byte[] fileContent;
private UUID attachmentOid;
}
图片实体类:
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Data
public class ImageInfo {
private byte[] imageBytes;
private Boolean compressFlag;
private Integer width;
private Integer height;
}
图片压缩工具类:
@Slf4j
public class ImageUtils {
private static final Long LEGAL_IMAGE_SIZE = 1024 * 2L;
public static ImageInfo compressImageForScale(FileCO fileCO) throws IOException {
byte[] imageBytes = fileCO.getFileContent();
UUID attachmentOid = fileCO.getAttachmentOid();
try {
BufferedImage sourceImage = ImageIO.read(new ByteArrayInputStream(imageBytes));
int height = sourceImage.getHeight();
int width = sourceImage.getWidth();
if (imageBytes.length = 0 || imageBytes.length LEGAL_IMAGE_SIZE * 1024) {
return ImageInfo.builder()
.imageBytes(imageBytes)
.width(width)
.height(height)
.compressFlag(false)
.build();
}
long srcSize = imageBytes.length;
double accuracy = getAccuracy(srcSize / 1024);
while (imageBytes.length LEGAL_IMAGE_SIZE * 1024) {
ByteArrayInputStream inputStream = new ByteArrayInputStream(imageBytes);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(imageBytes.length);
Thumbnails.of(inputStream)
.scale(1f)
.outputQuality(accuracy)
.toOutputStream(outputStream);
imageBytes = outputStream.toByteArray();
if (srcSize == imageBytes.length) {
log.warn("[图片压缩]msg=图片压缩失败,图片大小未改变!");
break;
}
}
log.info("[图片压缩]附件OID={} | 图片原大小={}kb | 压缩后大小={}kb",
attachmentOid, srcSize / 1024, imageBytes.length / 1024);
return ImageInfo.builder()
.imageBytes(imageBytes)
.width(width)
.height(height)
.compressFlag(true)
.build();
} catch (Exception e) {
log.error("[图片压缩]msg=图片压缩失败!", e);
throw e;
}
}
private static double getAccuracy(long size) {
double accuracy;
if (size = 2048 * 2) {
accuracy = 0.44;
} else {
accuracy = 0.4;
}
return accuracy;
}
}