我正在使用下面给出的代码对jpeg图像进行图像压缩。

File input = new File("digital_image_processing.jpg");
BufferedImage image = ImageIO.read(input);

File compressedImageFile = new File("compress.jpg");
OutputStream os = new FileOutputStream(compressedImageFile);

 Iterator<ImageWriter>writers = ImageIO.getImageWritersByFormatName("jpg");
 ImageWriter writer = (ImageWriter) writers.next();

 ImageOutputStream ios = ImageIO.createImageOutputStream(os);
 writer.setOutput(ios);

 ImageWriteParam param = writer.getDefaultWriteParam();

 param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
 param.setCompressionQuality(0.05f);

 writer.write(null, new IIOImage(image, null, null), param);


但是当我尝试通过更改ImageIO.getImageWritersByFormatName(“ png”)获得PNG格式时;
它给我的错误是不支持压缩。

那么我应该如何修改上面的代码,以支持所有图像格式压缩

最佳答案

代码的问题是您使用了ImageWriter.getDefaultWriteParam()。从ImageWriter.java的以下引用中:


  公共ImageWriteParam getDefaultWriteParam()
  
  返回与此类型合适的新ImageWriteParam对象
  包含默认值的文件格式,即默认值
  如果未指定ImageWriteParam对象,则将使用此参数。这是
  可以用作调整一些参数的起点,并且
  否则,将保留默认设置。
  
  默认实现构造并返回一个新的
  不允许平铺的ImageWriteParam对象,渐进式
  编码或压缩,并且将针对当前
  区域设置(即致电new会得到什么
  ImageWriteParam(getLocale())。
  
  各个插件可能会返回ImageWriteParam的实例,其中包含
  启用了其他可选功能,否则它们可能会返回一个实例
  ImageWriteParam的特定于插件的子类。


实际行为取决于特定ImageWriteParam的单独实现。我相信JPG图像起作用的原因是JPG的ImageWriteParam为默认的ImageWriteParam设置了canWriteCompressed受保护的字段,但为PNG图像设置了受保护的字段,出于某种原因,它不这样做。

如果查看com.sun.imageio.plugins.png.PNGImageWriteParam.java,您会发现它确实没有设置它。

为了使您的代码正常工作,您可以这样做:

  File input = new File("digital_image_processing.jpg");
  BufferedImage image = ImageIO.read(input);

  File compressedImageFile = new File("compress.jpg");
  OutputStream os = new FileOutputStream(compressedImageFile);

  Iterator<ImageWriter>writers = ImageIO.getImageWritersByFormatName("jpg");
  ImageWriter writer = (ImageWriter) writers.next();

  ImageOutputStream ios = ImageIO.createImageOutputStream(os);
  writer.setOutput(ios);

  ImageWriteParam param = writer.getDefaultWriteParam();
  // Check if canWriteCompressed is true
  if(param.canWriteCompressed()) {
     param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
     param.setCompressionQuality(0.05f);
  }
  // End of check
  writer.write(null, new IIOImage(image, null, null), param);


更新:我正在尝试为您提供一种在ImageIO框架内微调PNG图像压缩的方法。但是不幸的是,考虑到当前的实现,这似乎几乎是不可能的。 Java PNG writer插件具有固定的过滤-自适应过滤和固定的deflater级别-9,这是它可以做的最好的事情。

09-10 09:04