2012-06-06 14 views
5

或者,還有更好的庫來處理壓縮?創建JPEG時,我可以更改Java ImageWriter使用的壓縮算法嗎?

讓我以我已經理解的內容作爲序言:(1)JPEG是有損的 - 它看起來不會與輸入文件相同。 (2)我可以將壓縮質量設置調整到0.0到1.0之間,正如我在下面的代碼中所做的那樣。

我正在使用BufferedImage並將其轉換爲JPEG,並且注意到Java的ImageWriter的.write()方法爲JPEG圖像(與Photoshop「Save for Web」相比)產生了低於標準的結果。

我的代碼看起來有點像這樣現在:

// img is a BufferedImage, here 
ImageWriter writer = ImageIO.getImageWritersByFormatName("jpeg").next(); 
ImageWriteParam iwp = writer.getDefaultWriteParam(); 
iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); 
iwp.setCompressionQuality(.75f); 

IIOImage image = new IIOImage(img, null, null); 
ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream(); 
writer.setOutput(ImageIO.createImageOutputStream(byteArrayOut)); 
writer.write(null, image, iwp); 
writer.dispose(); 

與壓縮質量設置播放,但即使在設定「1.0」,他們不看一樣好東西會產生不同的質量輸出I可以在創建JPEG時使用其他工具。

由於我是一個新用戶,因此無法發佈圖像... here's a webpage that demos the differences。希望我可以在某些時候讓他們永久留在這裏,以便將來可能有類似問題的用戶使用。

很顯然,這個特定的圖像不是JPEG壓縮的最佳候選(PNG小得多且無損),但它允許更容易地看到壓縮僞像。實際的圖像本質上大都是攝影。至少,這更多的是質疑Java的JPEG壓縮算法和質量,相比之下,使用更少的字節生成更接近原始圖像的圖像。

+0

剛剛完成了示例鏈接,對於任何曾經見過這種情況的人來說。 – timehat

+0

理想的做法是將更好的JPEG壓縮整合到標準Java中;採取一個開源的清潔室實施(GNU/Linux libjpeg?/尤其是GNU Classpath)並將其移植到Java。也許有一些JUG的支持,這可能是可行的。 –

回答

5

「Java的的ImageWriter的.WRITE()(相比於Photoshop的方法產生的JPEG圖像 低於標準桿成績‘另存爲網頁’,作爲一個例子)。」

發生這種情況的原因有多種,將Java imageio生成的圖像質量與專業圖像軟件(如Photoshop)進行比較是不公平的。

無論如何,讓我們看看最有可能的原因是什麼是你的圖像中的工件:通常爲軟件將圖像保存爲JPEG,它將允許用戶指定一個參數,作爲壓縮或質量,一個是另一個。此參數用於縮放量化過程中使用的量化表,這是造成JPEG損失最重要的因素。不同的編碼器可以使用不同的量化表,這部分地考慮了圖像質量差異。

但是可能存在影響壓縮和圖像質量的其他因素,其中在量化過程之前實際發生的是色度子採樣(或降採樣)。色度二次採樣是以比原始分辨率更低的分辨率對圖像中的顏色信息進行採樣的過程。爲更好的解釋,請閱讀this文章。

卡爾文哈斯提供了一個很好的JPEG阻尼工具,稱爲JPEGSnoop,它可以從http://www.impulseadventure.com下載。使用您提供的ps75.jpg圖像上這個工具,我發現下面的輸出,屬於色度抽樣:

Component[1]: ID=0x01, Samp Fac=0x11 (Subsamp 1 x 1), Quant Tbl Sel=0x00 (Lum: Y) 
Component[2]: ID=0x02, Samp Fac=0x11 (Subsamp 1 x 1), Quant Tbl Sel=0x01 (Chrom: Cb) 
Component[3]: ID=0x03, Samp Fac=0x11 (Subsamp 1 x 1), Quant Tbl Sel=0x01 (Chrom: Cr) 

這意味着沒有顏色分量進行二次抽樣。另一方面,來自100.jpg和75的子衝突部分。JPG是相同的:

Component[1]: ID=0x01, Samp Fac=0x22 (Subsamp 1 x 1), Quant Tbl Sel=0x00 (Lum: Y) 
Component[2]: ID=0x02, Samp Fac=0x11 (Subsamp 2 x 2), Quant Tbl Sel=0x01 (Chrom: Cb) 
Component[3]: ID=0x03, Samp Fac=0x11 (Subsamp 2 x 2), Quant Tbl Sel=0x01 (Chrom: Cr) 

這意味着subsamping已經通過以連續的兩個像素的平均對顏色分量水平和垂直兩個方向上進行。

當原始圖像由條形和/或方形組成時,色度子採樣對圖像質量的影響最爲顯着,您已經注意到這些工件更容易在這裏看到。

因此,對於這種特殊情況,IMO的問題來自色度子採樣而不是質量因子設置。也許我還沒有深入挖掘,但我找不到設置imageio或其後的ImageWriter採樣因子的方法(很可能是com.sun.imageio.plugins.jpeg.JPEGImageWriter),儘管似乎可以設置量化和Huffman表格供ImageWriter使用。

因此,除非您爲imageio編寫自己的ImageWriter插件,或者作爲獨立編輯器,否則不太可能會更改Java ImageWriter使用的壓縮算法。但考慮到JEPG壓縮算法的複雜性,這兩者都不是微不足道的。有一個比較容易遵循由James R. Weeks編寫的Java JpegEncoder實現,默認情況下不會進行色度二次採樣。它曾經是免費的,但你可以通過搜索網站找到原始版本。

另一個有趣的事情是:從JPEGSnoop的輸出中,由photoshop保存的75%JPEG圖像的實際品質因數實際上顯示爲92%左右。而從卡爾文海思的網站下面引用的文本將回答這個問題,爲什麼不使用二次抽樣,你的情況的Photoshop:

順便說一句,請注意,Photoshop CS2的使用取決於保存JPEG畫質設置不同色度抽樣層次:

Photoshop Save As Quality 0-6 - 2x2 Chroma Subsampling 
Photoshop Save As Quality 7-12 - 1x1 No Chroma Subsampling 
Photoshop Save For Web Quality 0-50 - 2x2 Chroma Subsampling 
Photoshop Save For Web Quality 51-100 - 1x1 No Chroma Subsampling 

檢出this也可以寫入JPEG圖像的Java圖像庫。

+0

感謝您的詳細解釋。在這種情況下,色度二次採樣比質量設置更重要。我知道,將內置系統與Photoshop比較並不完全公平,但認爲這將是一個很好的比較標準。再次感謝指針。 – timehat