2015-02-10 126 views
2

我使用下面给出的jpeg图像压缩图像的代码。针对任何图像格式(jpg,PNG,gif)的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(); 

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

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

但是当我通过改变ImageIO.getImageWritersByFormatName( “PNG”),试图为PNG格式; 它给我的错误,不支持压缩。

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

+1

可能的重复[我如何写一个BufferedImage作为一个PNG没有压缩?](http://stackoverflow.com/questions/15318677/how-do-i-write-a-bufferedimage-as-a- png-with-no-compression) – immibis 2015-02-10 18:36:38

+0

这不是一个重复的,它是一个完全不同的问题 – dragon66 2015-02-10 19:23:24

+0

@ dragon66您使用的代码几乎完全一样,并且获得相同的错误,即使您使用该代码的原因不同 – immibis 2015-02-11 04:49:42

回答

1

与您的代码的问题是,你使用的ImageWriter.getDefaultWriteParam()。从ImageWriter.java以下报价:

公众的ImageWriteParam getDefaultWriteParam()

返回相应类型的新的ImageWriteParam对象包含默认值这个 文件格式,也就是说,这些值是 会在没有指定ImageWriteParam对象时使用。这是 作为调整一些参数和 的起点是有用的,否则单独保留默认设置。

默认实现构造并返回一个新 的ImageWriteParam对象不允许平铺,逐步 编码或压缩,并且将被本地化为当前 区域设置(即,你会通过调用new 的ImageWriteParam得到(的getLocale())。

单个插件可以返回的ImageWriteParam的实例,该 附加的可选功能启用,或者他们可能会返回一个插件的ImageWriteParam的具体子类的实例 。

实际行为取决于特定ImageWriteParam的单独实现。我相信JPG图像工作的原因是,ImageWriteParam for JPG将canWriteCompressed保护字段设置为默认ImageWriteParam,但对于PNG图像,由于某些原因,它不会这样做。

如果你看看com.sun.imageio.plugins.png.PNGImageWriteParam.java,你会发现它确实没有设置它。框架内我试图找出一个方法可以让你微调PNG图像压缩:

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

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。但不幸的是,鉴于目前的实施,似乎几乎不可能。 Java PNG Writer插件具有固定的过滤 - 自适应过滤和固定的deflater级别 - 9,这是它可以做的最好的事情。

+0

我试着用上面的代码,但在png图像的情况下,而不是减小大小,图像的大小增加 – 2015-02-12 06:31:51

+0

@AkshayYaduvanshi:上述代码只是一个例外的解决方法。与压缩相关的设置对PNG图像没有影响。控制PNG文件大小的两个因素是:过滤原始数据的第一阶段,然后是压缩过滤数据的第二阶段。有四种类型的过滤选项,您甚至可以自适应混合四种。对于放气压缩,可以从0-9设置放气水平。压缩率越高,压缩率越高,但速度越慢。 – dragon66 2015-02-12 14:56:03

+0

@AkshayYaduvanshi:您阅读的原始图像可能已经使用其他工具进行了优化(您会发现很多用于此目的的工具)。当您使用默认设置将其保存回PNG时,尺寸很可能会增加。 – dragon66 2015-02-12 14:58:58