问题背景。
典型的情景:Nemo社区中,用户上传的图片免不了要在某处给用户做展示。
如用户上传的头像,那么其他用户在浏览该用户信息的时候,就会需要回显头像信息了。
用户上传的原图可能由于清晰度较高而体积也相对较大,考虑用户流量带宽,一般而言我们都不会直接体积巨大的原图直接丢给用户让用户慢慢下载。
这时候通常我们会在服务器对图片进行压缩,然后把压缩后的图片内容回显给用户。
压缩方案:
这里主要找了两个java中常用的图片压缩工具库:Graphics和Thumbnailator。
1、Graphics:
/**
* compressImage
*
* @param imageByte
* Image source array
* @param ppi
* @return
*/
public static byte[] compressImage(byte[] imageByte, int ppi) {
byte[] smallImage = null;
int width = 0, height = 0;
if (imageByte == null)
return null;
ByteArrayInputStream byteInput = new ByteArrayInputStream(imageByte);
try {
Image image = ImageIO.read(byteInput);
int w = image.getWidth(null);
int h = image.getHeight(null);
// adjust weight and height to avoid image distortion
double scale = 0;
scale = Math.min((float) ppi / w, (float) ppi / h);
width = (int) (w * scale);
width -= width % 4;
height = (int) (h * scale);
if (scale >= (double) 1)
return imageByte;
BufferedImage buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
buffImg.getGraphics().drawImage(image.getScaledInstance(width, height, Image.SCALE_SMOOTH), 0, 0, null);
ByteArrayOutputStream out = new ByteArrayOutputStream();
ImageIO.write(buffImg, "png", out);
smallImage = out.toByteArray();
return smallImage;
} catch (IOException e) {
log.error(e.getMessage());
throw new RSServerInternalException("");
}
}
重点在于:
BufferedImage buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
buffImg.getGraphics().drawImage(image.getScaledInstance(width, height, Image.SCALE_SMOOTH), 0, 0, null);
2、Thumbnailator:
/**
* compressImage
*
* @param path
* @param ppi
* @return
*/
public static byte[] compressImage(String path, int ppi) {
byte[] smallImage = null;
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
Thumbnails.of(path).size(ppi, ppi).outputFormat("png").toOutputStream(out);
smallImage = out.toByteArray();
return smallImage;
} catch (IOException e) {
log.error(e.getMessage());
throw new RSServerInternalException("");
}
}
实际测试中,批量的情境下,后者较前者更快一些。