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秒,当然试验时间与图片大小有关系。


  • 4
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Java压缩图片时,如果要保持图片的清晰度不变,可以考虑使用以下两种方法: 1. 调整输出图片的质量 可以使用Java中的ImageIO类来读取和写入图片,其中可以设置输出图片的格式和质量。通过设置输出图片的格式为JPEG,然后设置压缩质量为100%,可以实现对图片的无损压缩。以下是一个示例代码: ```java File inputFile = new File("input.jpg"); File outputFile = new File("output.jpg"); BufferedImage inputImage = ImageIO.read(inputFile); // 设置输出图片的格式为JPEG ImageWriter writer = ImageIO.getImageWritersByFormatName("jpg").next(); ImageWriteParam writeParam = writer.getDefaultWriteParam(); ImageTypeSpecifier typeSpecifier = ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_RGB); writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); writeParam.setCompressionQuality(1.0f); // 写入输出图片 FileOutputStream outputStream = new FileOutputStream(outputFile); writer.setOutput(outputStream); IIOImage outputImage = new IIOImage(inputImage, null, null); writer.write(null, outputImage, writeParam); outputStream.close(); ``` 2. 调整输出图片的尺寸 将图片的尺寸缩小也可以实现压缩图片的效果,同时保持图片的清晰度。这种方式需要注意的是,缩小图片的尺寸不应该过小,否则会导致图片模糊或失真。以下是一个示例代码: ```java File inputFile = new File("input.jpg"); File outputFile = new File("output.jpg"); BufferedImage inputImage = ImageIO.read(inputFile); // 计算输出图片的尺寸 int outputWidth = 800; int outputHeight = (int) (inputImage.getHeight() * ((double) outputWidth / inputImage.getWidth())); // 缩小图片的尺寸 Image outputImage = inputImage.getScaledInstance(outputWidth, outputHeight, Image.SCALE_SMOOTH); // 写入输出图片 BufferedImage bufferedOutputImage = new BufferedImage(outputWidth, outputHeight, BufferedImage.TYPE_INT_RGB); Graphics2D g2d = bufferedOutputImage.createGraphics(); g2d.drawImage(outputImage, 0, 0, null); g2d.dispose(); ImageIO.write(bufferedOutputImage, "jpg", outputFile); ``` 希望这些信息能对您有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值