2015-02-10 153 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