很多時候,不快樂並不是因為快樂的條件沒有齊備,而是因為活得還不夠簡單。
本篇文章主要講的是通過Java SDK實現對圖片的質量壓縮,即圖片尺寸不變,壓縮圖片文件大小。而在本例中主要是徵對PNG圖片而言,再說Java SDK實現圖片質量壓縮之前,要先了解常見圖片的一些特性。
JPG格式
可支持有隕壓縮不支持透明不支持動畫非矢量
JPG圖片其實一生成出來就已經是有損的了,它是把一些不打算存儲的數據抹擦掉,它的色彩還原度比較好,可以支持適當壓縮後保持比較好的色彩度,如果你圖片顏色很多的,建議使用這個圖片格式,可以使生成的圖片大小比較小而不會使圖片看起來很模糊(失真) 。
JPEG格式
可支持有隕壓縮不支持透明不支持動畫非矢量
與jpg格式相似,經常在拷相片的時候看到得,但我們製作圖片的時候一般是保存jpg,該種圖片格式是文件相對jpg大,因為裡面存儲了很多相機裡的拍攝參數,像色相、飽和度、對比度等,可用於直接列印和印刷(相對於jpg要好) 。
PNG格式
不支持壓縮支持透明、半透明、不透明不支持動畫非矢量
網頁設計中為了使圖片下面的背景顏色顯示出來,我們經常會使用png24透明的圖片, png8是類似gif的透明度,有帶半透明(alpha為50%)的地方的時候以不透明處理。
png圖片如果色彩較多或複雜,則圖片生成後的格式是很大的,相比較jpg的放有5~6倍之多,所以沒特別要求不能以png替代jpg的使用。png圖片多用於網頁中的圖標設計。
IE6不支持png透明特性,有png的地方會以灰色底顯示,相當難看,不過ie6已經慢慢淡出了我們的視線,相信png的應用會得到更廣泛。
GIF格式
可支持有隕壓縮不支持全透明、半透明支持動畫非矢量
該格式的圖片位深相對較底,只支持web色顏色種類有限,無法過渡平滑。使用該格式的場景:網頁背景、小圖標、色彩度低的小切片、動畫圖片;
BMP格式
可支持有隕壓縮不支持透明不支持動畫非矢量
Windows格式,windows作業系統特有的圖片,該圖片保存了大量的圖片數據,所以圖片相對是比較大的,色彩度很真實,windows的桌面就是bmp格式的,通過設了桌面背景後,會在系統生成張bmp的圖片用於保存該桌面壁紙,缺點:圖片格式較大。
TIFF格式
不支持壓縮不支持透明不支持動畫非矢量
印刷格式,色彩真實,支持保存圖層(像psd,但像路徑、蒙版等不可保存),通常發給印刷公司的圖片就是用這種格式的。了解了常見格式圖片的一些特性之後,接下來就是本講的重點:Java SDK實現圖片質量壓縮。
分析
一、讀取文件:圖片文件是保存在內存當中,要想對其進行操作,首先要讀取它在內存中的數據,如果連數據都獲取不到,那就更別提壓縮處理了,這裡就牽扯到流,在javax.imageio.*包下提供了一個ImageIO類,該類提供ImageReader和ImageWriter來實現對圖片的讀取和寫入。
二、轉碼:通過上面介紹,可以知道能夠支持壓縮的圖片格式並不是很多,而jpeg能夠支持各種格式程度的壓縮方式,壓縮效果好。所以在不明確源文件格式的情況下,先轉碼成jpeg格式是一個不錯的選擇。
三、質量壓縮:ImageWriteParam這個對象提供setCompressionQuality可以對圖片進行壓縮,最後對壓縮之後的數據進行合成成圖片。
實現
首先要獲取圖片的BufferedImage流,即讀取圖片內存數據。
File file = new File(imagePath);// imagePath源文件路徑 BufferedImage bufferedImage = ImageIO.read(file);// 獲取BufferedImage流
其次獲取圖片文件的ImageWriter,來實現圖片文件的重構。
// 得到指定Format圖片的writer Iterator iter = ImageIO.getImageWritersByFormatName("jpeg");// 得到迭代器 ImageWriter writer = (ImageWriter) iter.next(); // 得到writer
接下來就是比較核心的內容,壓縮圖片。
// 得到指定writer的輸出參數設置(ImageWriteParam) ImageWriteParam iwp = writer.getDefaultWriteParam(); iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); // 設置可否壓縮 iwp.setCompressionQuality(quality); // 設置壓縮質量參數,0~1,1為最高質量 iwp.setProgressiveMode(ImageWriteParam.MODE_DISABLED); ColorModel colorModel = ColorModel.getRGBdefault(); // 指定壓縮時使用的色彩模式 iwp.setDestinationType(new ImageTypeSpecifier(colorModel, colorModel.createCompatibleSampleModel(16, 16))); // 開始打包圖片,寫入byte[] ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); // 取得內存輸出流 IIOImage iIamge = new IIOImage(bufferedImage, null, null); // 此處因為ImageWriter中用來接收write信息的output要求必須是ImageOutput // 通過ImageIo中的靜態方法,得到byteArrayOutputStream的ImageOutput writer.setOutput(ImageIO.createImageOutputStream(byteArrayOutputStream)); writer.write(null, iIamge, iwp);
最後獲取壓縮圖片的ByteArrayOutputStream,轉化成圖片文件。
// 獲取壓縮後的btye byte[] tempByte = byteArrayOutputStream.toByteArray(); // 創建輸出文件,outputPath輸出文件路徑,imgStyle目標文件格式(png) File outFile = new File(outputPath + "." + imgStyle); FileOutputStream fos = new FileOutputStream(outFile); fos.write(tempByte); fos.close();
到這裡圖片壓縮就已經全部完成,不過該方式壓縮對GIF的壓縮並不是很好,所以不適用於GIF。