java範例解析之1M圖片壓縮優化到100kb

2022-07-27 18:02:10
本篇文章給大家帶來了關於的相關知識,主要為大家介紹了java實現1M圖片壓縮優化到100kb範例詳解,影象壓縮是資料壓縮技術在數位影像上的應用,有需要的朋友可以借鑑參考下,希望能夠有所幫助。

推薦學習:《》

一、影象壓縮

影象壓縮是資料壓縮技術在數位影像上的應用,目的是減少影象資料中的冗餘資訊,從而用更加高效的格式儲存和傳輸資料。

影象壓縮可以是有損資料壓縮,也可以是無失真資料壓縮。

怎麼樣?

是不是感覺影象壓縮技術沒有想象中那麼簡單了?

二、Java數位影像處理

作為這次「20 多萬外包專案」的「主力開發人員」,我這裡就給大家介紹下 Java 數位影像處理技術吧,一開始我就是用它來處理圖片的。

數位影像處理(Digital Image Processing)是通過計算機對影象進行去除噪聲、增強、復原、分割、提取特徵等處理的方法和技術。

輸入的是影象訊號,然後經過 DIP 進行有效的演演算法處理後,輸出為數位訊號。

為了壓縮影象,我們需要讀取影象並將其轉換成 BufferedImage 物件,BufferedImage 是 Image 類的一個子類,描述了一個具有可存取的影象資料緩衝區,由 ColorModel 和 Raster 的影象資料組成。

廢話我就不多說了,直接進入實戰吧!

三、影象壓縮實戰

剛好我本地有一張之前用過的封面圖,離 1M 只差 236 KB,可以拿來作為測試用。

這其中要用到 ImageIO 類,這是一個靜態類,提供了一系列方法用來讀和寫影象,同時還可以對影象進行簡單的編碼和解碼。

比如說通過 ImageIO.read() 可以將影象讀取到 BufferedImage 物件:

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

比如說通過 ImageIO.getImageWritersByFormatName() 可以返回一個Iterator,其中包含了通過命名格式對影象進行編碼的 ImageWriter。

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

比如說通過 ImageIO.createImageOutputStream() 可以建立一個影象的輸出流物件,有了該物件後就可以通過 ImageWriter.setOutput() 將其設定為輸出流。

File compressedImageFile = new File("bbcompress.jpg");
OutputStream os =new FileOutputStream(compressedImageFile);
ImageOutputStream ios = ImageIO.createImageOutputStream(os);
writer.setOutput(ios);

緊接著,可以對 ImageWriter 進行一些引數設定,比如說壓縮模式,壓縮品質等等。

ImageWriteParam param = writer.getDefaultWriteParam();
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
param.setCompressionQuality(0.01f);

壓縮模式一共有四種,MODE_EXPLICIT 是其中一種,表示 ImageWriter 可以根據後續的 set 的附加資訊進行平鋪和壓縮,比如說接下來的 setCompressionQuality() 方法。

setCompressionQuality() 方法的引數是一個 0-1 之間的數,0.0 表示盡最大程度壓縮,1.0 表示保證影象品質很重要。對於有失真壓縮方案,壓縮品質應該控制檔案大小和影象品質之間的權衡(例如,通過在寫入 JPEG 影象時選擇量化表)。 對於無失真方案,壓縮品質可用於控制檔案大小和執行壓縮所需的時間之間的權衡(例如,通過優化行過濾器並在寫入 PNG 影象時設定 ZLIB 壓縮級別)。

整體程式碼如下所示:

public class Demo {
    public static void main(String[] args) {
        try {
            File input = new File("ceshi.jpg");
            BufferedImage image = ImageIO.read(input);
            Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("jpg");
            ImageWriter writer = (ImageWriter) writers.next();
            File compressedImageFile = new File("bbcompress.jpg");
            OutputStream os = new FileOutputStream(compressedImageFile);
            ImageOutputStream ios = ImageIO.createImageOutputStream(os);
            writer.setOutput(ios);
            ImageWriteParam param = writer.getDefaultWriteParam();
            param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
            param.setCompressionQuality(0.01f);
            writer.write(null, new IIOImage(image, null, null), param);
            os.close();
            ios.close();
            writer.dispose();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

執行壓縮後,可以看到圖片的大小壓縮到了 19 KB:

可以看得出,品質因子為 0.01f 的時候圖片已經有些失真了,可以適當提高品質因子比如說 0.5f,再來看一下。

圖片品質明顯提高了,但大小依然只有 64 KB,壓縮效果還是值得信賴的。

四、其他開源庫

接下來,推薦一些可以輕鬆整合到專案中的影象處理庫吧,它們全都是免費的。

1)ImageJ,用 Java 編寫的,可以編輯、分析、處理、儲存和列印影象。

2)Apache Commons Imaging,一個讀取和寫入各種影象格式的庫,包括快速解析影象資訊(如大小,顏色,空間,ICC組態檔等)和後設資料。

3)ImageMagick,可以讀取和寫入超過100種格式的影象,包括DPX、EXR、GIF、JPEG、JPEG-2000、PDF、PNG、Postscript、SVG和TIFF。還可以調整大小、翻轉、映象、旋轉、扭曲、剪下和變換影象,調整影象顏色,應用各種特殊效果,包括繪製文字、線條、多邊形、橢圓和貝塞爾曲線。

4)OpenCV,由BSD許可證釋出,可以免費學習和商業使用,提供了包括 C/C++、Python 和 Java 等主流程式語言在內的介面。OpenCV 專為計算效率而設計,強調實時應用,可以充分發揮多核處理器的優勢。

這裡就以 OpenCV 為例,來演示一下影象壓縮。當然了,OpenCV 用來壓縮影象屬於典型的大材小用。

第一步,新增 OpenCV 依賴到我們的專案當中,以 Maven 為例。

<dependency>
	<groupId>org.openpnp</groupId>
	<artifactId>opencv</artifactId>
	<version>4.5.1-2</version>
</dependency>

第二步,要想使用 OpenCV,需要先初始化。

OpenCV.loadShared();

第三步,使用 OpenCV 讀取圖片。

Mat src = Imgcodecs.imread(imagePath);

第四步,使用 OpenCV 壓縮圖片。

MatOfInt dstImage = new MatOfInt(Imgcodecs.IMWRITE_JPEG_QUALITY, 1);
Imgcodecs.imwrite("resized_image.jpg", sourceImage, dstImage);

MatOfInt 的構造引數是一個可變引數,第一個引數 IMWRITE_JPEG_QUALITY 表示對圖片的品質進行改變,第二個是品質因子,1-100,值越大表示品質越高。

執行程式碼後得到的圖片如下所示:

借這個機會,來對比下 OpenCV 和 JDK 原生 API 在壓縮影象時所使用的時間。

這是我本機的設定情況,早年買的頂配 iMac,也是我的主力機。一開始只有 16 G 記憶體,後來加了一個 16 G 記憶體條,不過最近半年電腦突然宕機重新啟動的頻率明顯提高了,不知道是不是 Big Sur 這個作業系統的問題還是電腦硬體老了。

結果如下所示:

opencvCompress壓縮完成,所花時間:1070
jdkCompress壓縮完成,所花時間:322

壓縮後的圖片大小差不多,都是 19 KB,並且品質因子都是最低值。

推薦學習:《》

以上就是java範例解析之1M圖片壓縮優化到100kb的詳細內容,更多請關注TW511.COM其它相關文章!