Java 图片压缩的两种方式

Java 图片压缩的两种方式

1. 问题背景

    在客户端和服务器中,不可避免的会遇到客户端从服务器获取图片数据用于显示的情形。在实际使用中,由于原图清晰度高,考虑到效率问题,我们不可能拿原图进行显示,服务端一般都要对图片进行压缩处理,然后发送给客户端显示。那么如何进行压缩呢?这里提供了两种解决方案:Java Graphics类和Thumbnailator.

2. Graphics

Graphics类提供基本绘图方法,Graphics类提供基本的几何图形绘制方法,主要有:画线段、画矩形、画圆、画带颜色的图形、画椭圆、画圆弧、画多边形、画字符串等。 这里不做一一赘述, 进重点介绍一下,利用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);

详细情形请查阅Graphics源代码。

3. Thumbnailator

第二种方案就是使用google thumbnailator jar包,主要是Thumbnails类, 大家可以去maven仓库里去下载。还是直接上代码,大家可以发现编码变得更加容易,而且宽高都是自适应的,另外Thumbnails还提供批量压缩方法,功能十分强大,效率也更高。
        /**
	 * 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("");
	    }
	}

4. 效率测试

既然上述两种方式都可以压缩图片,那么哪一种效率更高呢?为此我特意做了一下实验,准备了74张图片进行压缩,ppi均为125

通过实验发现Graphics压缩74张图片大约需要3.409秒,而thumbnail仅需要0.943秒,当然试验时间与图片大小有关系。


你可能感兴趣的:(spring,MVC)