最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

java實(shí)現(xiàn)1M圖片壓縮優(yōu)化到100kb實(shí)現(xiàn)示例

 更新時(shí)間:2022年07月14日 16:06:24   作者:沉默王二  
這篇文章主要為大家介紹了java實(shí)現(xiàn)1M圖片壓縮優(yōu)化到100kb示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

引言

坦白從寬吧,我就是那個(gè)花了兩天兩夜把 1M 圖片優(yōu)化到 100kb 的家伙——王小二!

自從因?yàn)橐黄獔?bào)道登上熱搜后,我差點(diǎn)抑郁,每天要靠 50 片安眠藥才能入睡。

網(wǎng)絡(luò)上曝光的那些關(guān)于一碼通的消息,有真有假,我這里就不再澄清了。就說說我是怎么把圖片從  1M 優(yōu)化到 100kb 的故事吧。

是的,由于系統(tǒng)群體規(guī)模和訪問規(guī)模的特殊性,每一行代碼、每一張圖片、每一個(gè)技術(shù)文檔都反復(fù)核準(zhǔn),優(yōu)化再優(yōu)化,精益求精。為確保系統(tǒng)運(yùn)行得更高效,我們將一張圖片從1MB壓縮到500KB,再從500KB優(yōu)化到100KB。

這樣的工作在外人看起來,簡單到就好像悄悄給學(xué)妹塞一張情書就能讓她做我女朋友一樣簡單。

但殊不知,這其中蘊(yùn)含著極高的技術(shù)含量!

不信,我給你們普及下。

一、圖像壓縮

圖像壓縮是數(shù)據(jù)壓縮技術(shù)在數(shù)字圖像上的應(yīng)用,目的是減少圖像數(shù)據(jù)中的冗余信息,從而用更加高效的格式存儲(chǔ)和傳輸數(shù)據(jù)。

圖像壓縮可以是有損數(shù)據(jù)壓縮,也可以是無損數(shù)據(jù)壓縮。

怎么樣?

是不是感覺圖像壓縮技術(shù)沒有想象中那么簡單了?

更多關(guān)于圖像壓縮的資料可參考以下鏈接。

http://m.fzitv.net/article/150789.htm

二、Java數(shù)字圖像處理

作為這次“20 多萬外包項(xiàng)目”的“主力開發(fā)人員”,我這里就給大家介紹下 Java 數(shù)字圖像處理技術(shù)吧,一開始我就是用它來處理圖片的。

數(shù)字圖像處理(Digital Image Processing)是通過計(jì)算機(jī)對(duì)圖像進(jìn)行去除噪聲、增強(qiáng)、復(fù)原、分割、提取特征等處理的方法和技術(shù)。

輸入的是圖像信號(hào),然后經(jīng)過 DIP 進(jìn)行有效的算法處理后,輸出為數(shù)字信號(hào)。

為了壓縮圖像,我們需要讀取圖像并將其轉(zhuǎn)換成 BufferedImage 對(duì)象,BufferedImage 是 Image 類的一個(gè)子類,描述了一個(gè)具有可訪問的圖像數(shù)據(jù)緩沖區(qū),由 ColorModel 和 Raster 的圖像數(shù)據(jù)組成。

廢話我就不多說了,直接進(jìn)入實(shí)戰(zhàn)吧!

三、圖像壓縮實(shí)戰(zhàn)

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

這其中要用到 ImageIO 類,這是一個(gè)靜態(tài)類,提供了一系列方法用來讀和寫圖像,同時(shí)還可以對(duì)圖像進(jìn)行簡單的編碼和解碼。

比如說通過 ImageIO.read() 可以將圖像讀取到 BufferedImage 對(duì)象:

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

比如說通過 ImageIO.getImageWritersByFormatName() 可以返回一個(gè)Iterator,其中包含了通過命名格式對(duì)圖像進(jìn)行編碼的 ImageWriter。

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

比如說通過 ImageIO.createImageOutputStream() 可以創(chuàng)建一個(gè)圖像的輸出流對(duì)象,有了該對(duì)象后就可以通過 ImageWriter.setOutput() 將其設(shè)置為輸出流。

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

緊接著,可以對(duì) ImageWriter 進(jìn)行一些參數(shù)配置,比如說壓縮模式,壓縮質(zhì)量等等。

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

壓縮模式一共有四種,MODE_EXPLICIT 是其中一種,表示 ImageWriter 可以根據(jù)后續(xù)的 set 的附加信息進(jìn)行平鋪和壓縮,比如說接下來的 setCompressionQuality() 方法。

setCompressionQuality() 方法的參數(shù)是一個(gè) 0-1 之間的數(shù),0.0 表示盡最大程度壓縮,1.0 表示保證圖像質(zhì)量很重要。對(duì)于有損壓縮方案,壓縮質(zhì)量應(yīng)該控制文件大小和圖像質(zhì)量之間的權(quán)衡(例如,通過在寫入 JPEG 圖像時(shí)選擇量化表)。 對(duì)于無損方案,壓縮質(zhì)量可用于控制文件大小和執(zhí)行壓縮所需的時(shí)間之間的權(quán)衡(例如,通過優(yōu)化行過濾器并在寫入 PNG 圖像時(shí)設(shè)置 ZLIB 壓縮級(jí)別)。

整體代碼如下所示:

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();
        }
    }
}

執(zhí)行壓縮后,可以看到圖片的大小壓縮到了 19 KB:

可以看得出,質(zhì)量因子為 0.01f 的時(shí)候圖片已經(jīng)有些失真了,可以適當(dāng)提高質(zhì)量因子比如說 0.5f,再來看一下。

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

四、其他開源庫

接下來,推薦一些可以輕松集成到項(xiàng)目中的圖像處理庫吧,它們?nèi)际敲赓M(fèi)的。

1)ImageJ,用 Java 編寫的,可以編輯、分析、處理、保存和打印圖像。

2)Apache Commons Imaging,一個(gè)讀取和寫入各種圖像格式的庫,包括快速解析圖像信息(如大小,顏色,空間,ICC配置文件等)和元數(shù)據(jù)。

3)ImageMagick,可以讀取和寫入超過100種格式的圖像,包括DPX、EXR、GIF、JPEG、JPEG-2000、PDF、PNG、Postscript、SVG和TIFF。還可以調(diào)整大小、翻轉(zhuǎn)、鏡像、旋轉(zhuǎn)、扭曲、剪切和變換圖像,調(diào)整圖像顏色,應(yīng)用各種特殊效果,包括繪制文本、線條、多邊形、橢圓和貝塞爾曲線。

4)OpenCV,由BSD許可證發(fā)布,可以免費(fèi)學(xué)習(xí)和商業(yè)使用,提供了包括 C/C++、Python 和 Java 等主流編程語言在內(nèi)的接口。OpenCV 專為計(jì)算效率而設(shè)計(jì),強(qiáng)調(diào)實(shí)時(shí)應(yīng)用,可以充分發(fā)揮多核處理器的優(yōu)勢。

這里就以 OpenCV 為例,來演示一下圖像壓縮。當(dāng)然了,OpenCV 用來壓縮圖像屬于典型的大材小用。

第一步,添加 OpenCV 依賴到我們的項(xiàng)目當(dāng)中,以 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 的構(gòu)造參數(shù)是一個(gè)可變參數(shù),第一個(gè)參數(shù) IMWRITE_JPEG_QUALITY 表示對(duì)圖片的質(zhì)量進(jìn)行改變,第二個(gè)是質(zhì)量因子,1-100,值越大表示質(zhì)量越高。

執(zhí)行代碼后得到的圖片如下所示:

借這個(gè)機(jī)會(huì),來對(duì)比下 OpenCV 和 JDK 原生 API 在壓縮圖像時(shí)所使用的時(shí)間。

這是我本機(jī)的配置情況,早年買的頂配 iMac,也是我的主力機(jī)。一開始只有 16 G 內(nèi)存,后來加了一個(gè) 16 G 內(nèi)存條,不過最近半年電腦突然死機(jī)重啟的頻率明顯提高了,不知道是不是 Big Sur 這個(gè)操作系統(tǒng)的問題還是電腦硬件老了。

結(jié)果如下所示:

opencvCompress壓縮完成,所花時(shí)間:1070
jdkCompress壓縮完成,所花時(shí)間:322

壓縮后的圖片大小差不多,都是 19 KB,并且質(zhì)量因子都是最低值。

五、一點(diǎn)點(diǎn)心聲

經(jīng)過上面的技術(shù)分析后,相信你們都明白了,把1M圖片優(yōu)化到100kb實(shí)在是一件“不太容易”的事情。。。。

100KB 很小了吧?只有原來的 1/10。

要知道,我可是連續(xù)加班了兩天兩夜,不眠不休。

累到最后,我趴在電腦上都睡著了。

沒想到哈喇子直接給電腦整短路了,我這才算是從夢里面嚇醒來了!

??,生活不易,且行且珍惜吧~

GitHub https://github.com/itwanger/toBeBetterJavaer

以上就是java實(shí)現(xiàn)1M圖片壓縮優(yōu)化到100kb實(shí)現(xiàn)示例的詳細(xì)內(nèi)容,更多關(guān)于java 1M圖片壓縮到100kb的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java使用Socket判斷某服務(wù)能否連通代碼實(shí)例

    Java使用Socket判斷某服務(wù)能否連通代碼實(shí)例

    這篇文章主要介紹了Java使用Socket判斷某服務(wù)能否連通代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11
  • 關(guān)于Java中Bean的生命周期詳解

    關(guān)于Java中Bean的生命周期詳解

    這篇文章主要介紹了關(guān)于Java中Bean的生命周期詳解,所謂的?命周期指的是?個(gè)對(duì)象從誕?到銷毀的整個(gè)?命過程,我們把這個(gè)過程就叫做?個(gè)對(duì)象的?命周期,需要的朋友可以參考下
    2023-08-08
  • mybatis中批量插入的兩種方式(高效插入)

    mybatis中批量插入的兩種方式(高效插入)

    MyBatis是一個(gè)支持普通SQL查詢,存儲(chǔ)過程和高級(jí)映射的優(yōu)秀持久層框架。這篇文章主要介紹了mybatis中批量插入的兩種方式(高效插入)的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,感興趣的朋友一起看看吧
    2016-09-09
  • Java中字符串替換的4種方法代碼舉例

    Java中字符串替換的4種方法代碼舉例

    這篇文章主要介紹了Java中四種字符串替換方法,分別是String.replace()、String.replaceAll()、String.replaceFirst()和StringBuilder.replace(),并對(duì)比了它們的特點(diǎn)和適用場景,需要的朋友可以參考下
    2025-02-02
  • Java Stream中自定義Collector實(shí)現(xiàn)復(fù)雜數(shù)據(jù)收集的方法

    Java Stream中自定義Collector實(shí)現(xiàn)復(fù)雜數(shù)據(jù)收集的方法

    Java Stream API中的Collector接口是一個(gè)強(qiáng)大的工具,它允許我們自定義數(shù)據(jù)收集、轉(zhuǎn)換和聚合的過程,,本文介紹了Java Stream中自定義Collector實(shí)現(xiàn)復(fù)雜數(shù)據(jù)收集方法,需要的朋友可以參考下
    2024-08-08
  • WebSocket無法注入屬性的問題及解決方案

    WebSocket無法注入屬性的問題及解決方案

    這篇文章主要介紹了WebSocket無法注入屬性的問題及解決方法,本文通過示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-09-09
  • Java struts2 validate用戶登錄校驗(yàn)功能實(shí)現(xiàn)

    Java struts2 validate用戶登錄校驗(yàn)功能實(shí)現(xiàn)

    這篇文章主要為大家詳細(xì)介紹了Java struts2 validate用戶登錄校驗(yàn)功能實(shí)現(xiàn)的具體步驟,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-05-05
  • java枚舉enum,根據(jù)value值獲取key鍵的操作

    java枚舉enum,根據(jù)value值獲取key鍵的操作

    這篇文章主要介紹了java枚舉enum,根據(jù)value值獲取key鍵的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02
  • SpringBoot?MP簡單的分頁查詢測試實(shí)現(xiàn)步驟分解

    SpringBoot?MP簡單的分頁查詢測試實(shí)現(xiàn)步驟分解

    好久沒水后端的東西了,最近在做vue項(xiàng)目寫前端的代碼,所以cloud也停進(jìn)度了,吃完飯突然記得我沒有在博客里寫分頁的東西,雖然項(xiàng)目中用到了,但是沒有拎出來,這里就拎出來看看
    2023-04-04
  • 基于kafka實(shí)現(xiàn)Spring Cloud Bus消息總線

    基于kafka實(shí)現(xiàn)Spring Cloud Bus消息總線

    消息總線是一種通信工具,可以在機(jī)器之間互相傳輸消息、文件等,這篇文章主要介紹了如何利用kafka實(shí)現(xiàn)SpringCloud Bus消息總線,感興趣的可以學(xué)習(xí)一下
    2022-04-04

最新評(píng)論

砀山县| 富平县| 如皋市| 额济纳旗| 漯河市| 广饶县| 启东市| 石嘴山市| 东安县| 清流县| 乌拉特中旗| 辉南县| 阿鲁科尔沁旗| 化德县| 临邑县| 香港 | 卓资县| 永川市| 海安县| 榆林市| 广东省| 友谊县| 普兰县| 台州市| 平远县| 吉木萨尔县| 张家界市| 沙田区| 襄汾县| 繁昌县| 龙南县| 安龙县| 花莲市| 临潭县| 昌平区| 凌源市| 土默特右旗| 任丘市| 灌南县| 前郭尔| 辰溪县|