Jack Jiang

          我的最新工程MobileIMSDK:http://git.oschina.net/jackjiang/MobileIMSDK
          posts - 497, comments - 13, trackbacks - 0, articles - 1

          本文來自騰訊前端開發(fā)工程師“ wendygogogo”的技術(shù)分享,作者自評(píng):“在Web前端摸爬滾打的碼農(nóng)一枚,對(duì)技術(shù)充滿熱情的菜鳥,致力為手Q的建設(shè)添磚加瓦。”

          1、GIF格式的歷史

          GIF ( Graphics Interchange Format )原義是“圖像互換格式”,是 CompuServe 公司在1987年開發(fā)出的圖像文件格式,可以說是互聯(lián)網(wǎng)界的老古董了。

          GIF 格式可以存儲(chǔ)多幅彩色圖像,如果將這些圖像((https://www.qcloud.com/document/ ... w.59167.59167.59167)連續(xù)播放出來,就能夠組成最簡(jiǎn)單的動(dòng)畫。所以常被用來存儲(chǔ)“動(dòng)態(tài)圖片”,通常時(shí)間短,體積小,內(nèi)容簡(jiǎn)單,成像相對(duì)清晰,適于在早起的慢速互聯(lián)網(wǎng)上傳播。

          本來,隨著網(wǎng)絡(luò)帶寬的拓展和視頻技術(shù)的進(jìn)步,這種圖像已經(jīng)漸漸失去了市場(chǎng)。可是,近年來流行的表情包文化,讓老古董 GIF 圖有了新的用武之地。

          表情包通常來源于手繪圖像,或是視頻截取,目前有很多方便制作表情包的小工具。

          這類圖片通常具有文件體積小,內(nèi)容簡(jiǎn)單,兼容性好(無需解碼工具即可在各類平臺(tái)上查看),對(duì)畫質(zhì)要求不高的特點(diǎn),剛好符合 GIF 圖的特性。

          所以,老古董 GIF 圖有了新的應(yīng)用場(chǎng)景。

          學(xué)習(xí)交流:

          - 即時(shí)通訊開發(fā)交流3群:185926912[推薦]

          - 移動(dòng)端IM開發(fā)入門文章:《新手入門一篇就夠:從零開發(fā)移動(dòng)端IM

          (本文同步發(fā)布于:http://www.52im.net/thread-2032-1-1.html

          2、相關(guān)文章

          騰訊技術(shù)分享:社交網(wǎng)絡(luò)圖片的帶寬壓縮技術(shù)演進(jìn)之路

          QQ音樂團(tuán)隊(duì)分享:Android中的圖片壓縮技術(shù)詳解(上篇)

          QQ音樂團(tuán)隊(duì)分享:Android中的圖片壓縮技術(shù)詳解(下篇)

          騰訊原創(chuàng)分享(一):如何大幅提升移動(dòng)網(wǎng)絡(luò)下手機(jī)QQ的圖片傳輸速度和成功率

          騰訊技術(shù)分享:騰訊是如何大幅降低帶寬和網(wǎng)絡(luò)流量的(圖片壓縮篇)

          全面掌握移動(dòng)端主流圖片格式的特點(diǎn)、性能、調(diào)優(yōu)等

          基于社交網(wǎng)絡(luò)的Yelp是如何實(shí)現(xiàn)海量用戶圖片的無損壓縮的?

          3、技術(shù)需求場(chǎng)景

          新的應(yīng)用場(chǎng)景帶來新的需求,本文所要探究的技術(shù)和要解決的問題來源于某個(gè)真實(shí)的業(yè)務(wù)場(chǎng)景下——即為用戶批量推送GIF表情包的功能需求。

          一批圖像大約有200-500張,以縮略圖列表的形式展示在客戶端。

          根據(jù)我們使用測(cè)試數(shù)據(jù)進(jìn)行的統(tǒng)計(jì) GIF 圖表情包的尺寸大部分在200k-500k之間,批量推送的一個(gè)重要問題就是數(shù)據(jù)量太大,因此,我們希望能夠在列表里展示體積較小的縮略圖,用戶點(diǎn)擊后,再單獨(dú)拉取原圖。

          傳統(tǒng)的 GIF 縮略圖是靜態(tài)的,通常是提取第一幀,但在表情包的情形下,這種方式不足以表達(dá)出圖片中信息。

          比如下面的例子:

          (左為原始GIF動(dòng)態(tài)圖,右為GIF的第一幀)

          第一幀完全看不出重點(diǎn)啊!

          所以,我們希望縮略圖也是動(dòng)態(tài)的,并盡可能和原圖相似。

          對(duì)于傳統(tǒng)圖片來說,文件大小一般和圖片分辨率(尺寸)正相關(guān),所以,生成縮略圖最直觀的思路就是縮小尺寸,resize大法。

          但是在 GIF 圖的場(chǎng)合,這個(gè)方式不再高效,因?yàn)?GIF 圖的文件大小還受到一個(gè)重要的因素制約——幀數(shù)

          以這張柴犬表情為例,原圖寬度200,尺寸1.44M,等比縮放到150之后,尺寸還是1.37M,等比縮放到100,相當(dāng)于尺寸變?yōu)樵瓉淼乃姆种唬w積還是749K。

          可見,resize大法的壓縮率并不理想,收效甚微。

          而且,我們所得到的大部分表情圖素材,分辨率已經(jīng)很小了,為了保證客戶端展示效果,不能夠過度減少尺寸,不然圖片會(huì)變得模糊。

          所以,想要對(duì)GIF圖進(jìn)行壓縮,只能從別的方向入手。

          4、GIF技術(shù)詳解:拆解GIF格式

          4.1 基本

          想要壓縮一個(gè)文件,首先要了解它是如何存儲(chǔ)的。畢竟,編程的事,萬變不離其宗嘛。

          作為一種古老的格式,GIF的存儲(chǔ)規(guī)則也相對(duì)簡(jiǎn)單,容易理解。

          一個(gè)GIF文件主要由以下幾部分組成:

          1)文件頭;

          2)圖像幀信息;

          3)注釋。

          下面我們來分別探究每個(gè)部分。

          4.2 文件頭

          GIF格式文件頭和一般文件頭差別不大,也包含有:

          1)格式聲明;

          2)邏輯屏幕描述塊;

          3)全局調(diào)色盤;

          格式聲明:

          Signature 為“GIF”3 個(gè)字符;Version 為“87a”或“89a”3 個(gè)字符。

          邏輯屏幕描述塊:

          前兩字節(jié)為像素單位的寬、高,用以標(biāo)識(shí)圖片的視覺尺寸。

          Packet里是調(diào)色盤信息,分別來看:

          1)Global Color Table Flag為全局顏色表標(biāo)志,即為1時(shí)表明全局顏色表有定義;

          2)Color Resolution 代表顏色表中每種基色位長(zhǎng)(需要+1),為111時(shí),每個(gè)顏色用8bit表示,即我們熟悉的RGB表示法,一個(gè)顏色三字節(jié);

          3)Sort Flag 表示是否對(duì)顏色表里的顏色進(jìn)行優(yōu)先度排序,把常用的排在前面,這個(gè)主要是為了適應(yīng)一些顏色解析度低的早期渲染器,現(xiàn)在已經(jīng)很少使用了;

          4)Global Color Table 表示顏色表的長(zhǎng)度,計(jì)算規(guī)則是值+1作為2的冪,得到的數(shù)字就是顏色表的項(xiàng)數(shù),取最大值111時(shí),項(xiàng)數(shù)=256,也就是說GIF格式最多支持256色的位圖,再乘以Color Resolution算出的字節(jié)數(shù),就是調(diào)色盤的總長(zhǎng)度。

          這四個(gè)字段一起定義了調(diào)色盤的信息。

          Background color Index 定義了圖像透明區(qū)域的背景色在調(diào)色盤里的索引。

          Pixel Aspect Ratio 定義了像素寬高比,一般為0。

          什么是調(diào)色盤?我們先考慮最直觀的圖像存儲(chǔ)方式,一張分辨率M×N的圖像,本質(zhì)是一張點(diǎn)陣,如果采用Web最常見的RGB三色方式存儲(chǔ),每個(gè)顏色用8bit表示,那么一個(gè)點(diǎn)就可以由三個(gè)字節(jié)(3BYTE = 24bit)表達(dá),比如0xFFFFFF可以表示一個(gè)白色像素點(diǎn),0x000000表示一個(gè)黑色像素點(diǎn)。

          如果我們采用最原始的存儲(chǔ)方式,把每個(gè)點(diǎn)的顏色值寫進(jìn)文件,那么我們的圖像信息就要占據(jù)就是3×M×N字節(jié),這是靜態(tài)圖的情況,如果一張GIF圖里有K幀,點(diǎn)陣信息就是3×M×N×K。

          下面這張兔子snowball的表情有18幀,分辨率是200×196,如果用上述方式計(jì)算,文件尺寸至少要689K。

          但實(shí)際文件尺寸只有192K,它一定經(jīng)歷過什么……

          我們可以使用命令行圖片處理工具gifsicle來看看它的信息:

          gifsicle -I snowball.gif > snowball.txt

          我們得到下面的文本:

          5.gif 19 images

          logical screen 200x196

          global color table (128)

          background 93

          loop forever

          extensions 1

          + image #0 200x196 transparent 93

          disposal asis delay 0.04s

          + image #1 200x188 transparent 93

          disposal asis delay 0.04s

          ........

          可以看到,global color table 128就是它的調(diào)色盤,長(zhǎng)度128。

          為了確認(rèn),我們?cè)儆枚M(jìn)制查看器查看一下它的文件頭:

          可以看到Packet里的字段的確符合我們的描述。

          在實(shí)際情況中,GIF圖具有下面的特征:

          1)一張圖像最多只會(huì)包含256個(gè)RGB值;

          2)在一張連續(xù)動(dòng)態(tài)GIF里,每一幀之間信息差異不大,顏色是被大量重復(fù)使用的。

          在存儲(chǔ)時(shí),我們用一個(gè)公共的索引表,把圖片中用到的顏色提取出來,組成一個(gè)調(diào)色盤,這樣,在存儲(chǔ)真正的圖片點(diǎn)陣時(shí),只需要存儲(chǔ)每個(gè)點(diǎn)在調(diào)色盤里的索引值。

          如果調(diào)色盤放在文件頭,作為所有幀公用的信息,就是公共(全局)調(diào)色盤,如果放在每一幀的幀信息中,就是局部調(diào)色盤。GIF格式允許兩種調(diào)色盤同時(shí)存在,在沒有局部調(diào)色盤的情況下,使用公共調(diào)色盤來渲染。

          這樣,我們可以用調(diào)色盤里的索引來代表實(shí)際的顏色值。

          一個(gè)256色的調(diào)色盤,24bit的顏色只需要用9bit就可以表達(dá)了。

          調(diào)色盤還可以進(jìn)一步減少,128色,64色,etc,相應(yīng)的壓縮率就會(huì)越來越大……

          還是以兔子為例,我們還可以嘗試指定它的調(diào)色盤大小,對(duì)它進(jìn)行重壓縮:

          gifsicle --colors=64 5.gif > 5-64.gif

          gifsicle --colors=32 5.gif > 5-32.gif

          gifsicle --colors=16 5.gif > 5-16.gif

          gifsicle --colors=2 5.gif > 5-2.gif

          ......

          依然使用gifsicle工具,colors參數(shù)就是調(diào)色盤的長(zhǎng)度,得到的結(jié)果:

          注意到了2的時(shí)候,圖像已經(jīng)變成了黑白二值圖。

          居然還能看出是個(gè)兔子……

          所以我們得出結(jié)論——如果可以接受犧牲圖像的部分視覺效果,就可以通過減色來對(duì)圖像做進(jìn)一步壓縮。

          文件頭所包含的對(duì)我們有用的信息就是這些了,我們繼續(xù)往后看。

          4.3 幀信息描述

          幀信息描述就是每一幀的圖像信息和相關(guān)標(biāo)志位,在逐項(xiàng)了解它之前,我們首先探究一下幀的存儲(chǔ)方式。

          我們已經(jīng)知道調(diào)色盤相關(guān)的定義,除了全局調(diào)色盤,每一幀可以擁有自己的局部調(diào)色盤,渲染順序更優(yōu)先,它的定義方式和全局調(diào)色盤一致,只是作用范圍不同。

          直觀地說,幀信息應(yīng)該由一系列的點(diǎn)陣數(shù)據(jù)組成,點(diǎn)陣中存儲(chǔ)著一系列的顏色值。點(diǎn)陣數(shù)據(jù)本身的存儲(chǔ)也是可以進(jìn)行壓縮的,GIF圖所采用的是LZW壓縮算法。

          這樣的壓縮和圖像本身性質(zhì)無關(guān),是字節(jié)層面的,文本信息也可以采用(比如常見的gzip,就是LZW和哈夫曼樹的一個(gè)實(shí)現(xiàn))。

          基于表查詢的無損壓縮是如何進(jìn)行的?基本思路是,對(duì)于原始數(shù)據(jù),將每個(gè)第一次出現(xiàn)的串放在一個(gè)串表中,用索引來表示串,后續(xù)遇到同樣的串,簡(jiǎn)化為索引來存儲(chǔ)(串表壓縮法)。

          舉一個(gè)簡(jiǎn)單的例子來說明LZW算法的核心思路。

          有原始數(shù)據(jù):ABCCAABCDDAACCDB

          可以看出,原始數(shù)據(jù)里只包括4個(gè)字符A,B,C,D,四個(gè)字符可以用2bit的索引來表示,0-A,1-B,2-C,3-D。

          原始字符串存在重復(fù)字符,比如AB,CC,都重復(fù)出現(xiàn)過。用4代表AB,5代表CC,上面的字符串可以替代表示為45A4CDDAA5DB

          這樣就完成了壓縮,串長(zhǎng)度從16縮減到12。對(duì)原始信息來說,LZW壓縮是無損的。

          除了采用LZW之外,幀信息存儲(chǔ)過程中還采取了一些和圖像相關(guān)的優(yōu)化手段,以減小文件的體積,直觀表述就是——公共區(qū)域排除、透明區(qū)域疊加

          這是ImageMagick官方范例里的一張GIF圖:

          根據(jù)直觀感受,這張圖片的每一幀應(yīng)該是這樣的:

          但實(shí)際上,進(jìn)行過壓縮優(yōu)化的圖片,每一幀是這樣的:

          首先,對(duì)于各幀之間沒有變化的區(qū)域進(jìn)行了排除,避免存儲(chǔ)重復(fù)的信息。

          其次,對(duì)于需要存儲(chǔ)的區(qū)域做了透明化處理,只存儲(chǔ)有變化的像素,沒變化的像素只存儲(chǔ)一個(gè)透明值。

          這樣的優(yōu)化在表情包中也是很常見的,舉個(gè)栗子:

          上面這個(gè)表情的文件大小是278KB,幀數(shù)是14

          我們?cè)囍霉ぞ邔⑺饚痖_,這里使用另一個(gè)命令行圖像處理工具ImageMagick:

          gm convert source.gif target_%d.gif

          可以看出,除了第一幀之外,后面的幀都做了不同程度的處理,文件體積也比第一幀小。

          這樣的壓縮處理也是無損的,帶來的壓縮比和原始圖像的具體情況有關(guān),重復(fù)區(qū)域越多,壓縮效果越好,但相應(yīng)地,也需要存儲(chǔ)一些額外的信息,來告訴引擎如何渲染。

          具體包括:

          幀數(shù)據(jù)長(zhǎng)寬分辨率,相對(duì)整圖的偏移位置;

          透明彩色索引——填充透明點(diǎn)所用的顏色;

          Disposal Method——定義該幀對(duì)于上一幀的疊加方式;

          Delay Time——定義該幀播放時(shí)的停留時(shí)間。

          其中值得額外說明的是Disposal Method,它定義的是幀之間的疊加關(guān)系,給定一個(gè)幀序列,我們用怎樣的方式把它們渲染成起來。

          詳細(xì)參數(shù)定義,可以參考該網(wǎng)站的范例:http://www.theimage.com/animation/pages/disposal.html

          Disposal Method和透明顏色一起,定義了幀之間的疊加關(guān)系。在實(shí)際使用中,我們通常把第一幀當(dāng)做基幀(background),其余幀向前一幀對(duì)齊的方式來渲染,這里不再贅述。

          理解了上面的內(nèi)容,我們?cè)賮砜磶畔⒌木唧w定義,主要包括:

          1)幀分隔符;

          2)幀數(shù)據(jù)說明;

          3)點(diǎn)陣數(shù)據(jù)(它存儲(chǔ)的不是顏色值,而是顏色索引);

          4)幀數(shù)據(jù)擴(kuò)展(只有89a標(biāo)準(zhǔn)支持)。

          1和3比較直觀,第二部分和第四部分則是一系列的標(biāo)志位,定義了對(duì)于“幀”需要說明的內(nèi)容。

          幀數(shù)據(jù)說明:

          除了上面說過的字段之外,還多了一個(gè)Interlace Flag,表示幀點(diǎn)陣的存儲(chǔ)方式,有兩種,順序和隔行交錯(cuò),為 1 時(shí)表示圖像數(shù)據(jù)是以隔行方式存放的。最初 GIF 標(biāo)準(zhǔn)設(shè)置此標(biāo)志的目的是考慮到通信設(shè)備間傳輸速度不理想情況下,用這種方式存放和顯示圖像,就可以在圖像顯示完成之前看到這幅圖像的概貌,慢慢的變清晰,而不覺得顯示時(shí)間過長(zhǎng)。

          幀數(shù)據(jù)擴(kuò)展是89a標(biāo)準(zhǔn)增加的,主要包括四個(gè)部分。

          1)程序擴(kuò)展結(jié)構(gòu)(Application Extension):主要定義了生成該gif的程序相關(guān)信息

          2)注釋擴(kuò)展結(jié)構(gòu)(Comment Extension):一般用來儲(chǔ)存圖片作者的簽名信息

          3)圖形控制擴(kuò)展結(jié)構(gòu)(Graphic Control Extension):這部分對(duì)圖片的渲染比較重要

          除了前面說過的Dispose Method、Delay、Background Color之外,User Input用來定義是否接受用戶輸入后再播放下一幀,需要圖像解碼器對(duì)應(yīng)api的配合,可以用來實(shí)現(xiàn)一些特殊的交互效果。

          4)平滑文本擴(kuò)展結(jié)構(gòu)(Plain Text Control Extension):

          89a標(biāo)準(zhǔn)允許我們將圖片上的文字信息額外儲(chǔ)存在擴(kuò)展區(qū)域里,但實(shí)際渲染時(shí)依賴解碼器的字體環(huán)境,所以實(shí)際情況中很少使用。

          以上擴(kuò)展塊都是可選的,只有Label置位的情況下,解碼器才會(huì)去渲染。

          5、將技術(shù)理論付諸應(yīng)用——給表情包減負(fù)

          說完了基本原理,用剛才了解到的技術(shù)細(xì)節(jié)來分析一下我們的實(shí)際問題。

          給大量表情包生成縮略圖,在不損耗原畫質(zhì)的前提下,盡可能減少圖片體積,節(jié)省用戶流量。

          之前說過,單純依靠resize大法不能滿足我們的要求,沒辦法,只能損耗畫質(zhì)了。

          主要有兩個(gè)思路:減少顏色和減少幀數(shù):

          1)減少顏色——圖片情況各異,標(biāo)準(zhǔn)難以控制,而且會(huì)造成縮略圖和原圖視覺差異比較明顯。

          2)減少幀數(shù)——通過提取一些間隔幀,比如對(duì)于一張10幀的動(dòng)畫,提取其中的提取1,3,5,7,9幀。來減少圖片的整體體積,似乎更可行。

          先看一個(gè)成果,就拿文章開頭的圖做栗子吧:

          看上去連貫性不如以前,但是差別不大,作為縮略圖的視覺效果可以接受,由于幀數(shù)減小,體積也可以得到明顯的優(yōu)化。體積從428K縮到了140K。

          但是,在開發(fā)初期,我們嘗試暴力間隔提取幀,把幀重新連接壓成新的GIF圖,這時(shí),會(huì)得到這樣的圖片:

          主要有兩個(gè)問題:

          1)幀數(shù)過快;

          2)能看到明顯的殘留噪點(diǎn)。

          分析我們上面的原理,不難找到原因,正是因?yàn)榇蟛糠諫IF存儲(chǔ)時(shí)采用了公共區(qū)域排除和透明區(qū)域疊加的優(yōu)化,如果我們直接間隔抽幀,再拼起來,就破壞了原來的疊加規(guī)則,不該露出來的幀露出來了,所以才會(huì)產(chǎn)生噪點(diǎn)。

          所以,我們首先要把原始信息恢復(fù)出來。

          兩個(gè)命令行工具,gifsicle和ImageMagick都提供這樣的命令:

          gm convert -coalesce source.gif target_%d.gif

          gifsicle --unoptimize source.gif > target.gif

          還原之后抽幀,重建新的GIF,就可以解決問題2了。

          注意重建的時(shí)候,可以應(yīng)用工具再進(jìn)行對(duì)透明度和公共區(qū)域的優(yōu)化壓縮。

          至于問題1,也是因?yàn)槲覀儧]有對(duì)幀延遲參數(shù)Delay Time做處理,直接取原幀的參數(shù),幀數(shù)減少了,速度一定會(huì)加快。

          所以,我們需要把抽去的連續(xù)幀的總延時(shí)加起來,作為新的延遲數(shù)據(jù),這樣可以保持縮略圖和原圖頻率一致,看起來不會(huì)太過鬼畜,也不會(huì)太過遲緩。

          提取出每一幀的delay信息,也可以通過工具提供的命令來提取:

          gm identify -verbose source.gif

          gifsicle -I source.gif

          在實(shí)際應(yīng)用中,抽幀的間隔gap是根據(jù)總幀數(shù)frame求出的:

          frame<8 gap=1

          frame>40 gap=5

          delay值的計(jì)算還做了歸一化處理,如果新生成縮略圖的幀間隔平均值大于200ms,則統(tǒng)一加速到均值200ms,同時(shí)保持原有節(jié)奏,這樣可以避免極端情況下,縮略圖過于遲緩。

          6、具體的代碼實(shí)踐

          本文介紹的算法已經(jīng)應(yīng)用于手Q熱圖功能的后臺(tái)管理系統(tǒng)等,使用Nodejs編寫。ImageMagick是一個(gè)較為常用的圖像處理工具,除了gif還可以處理各類圖像文件,有node封裝的版本可以使用。gifsicle只有可執(zhí)行版本,在服務(wù)器上重新編譯源碼后,采用spawn調(diào)起子進(jìn)程的方式實(shí)現(xiàn)。

          ImageMagick對(duì)于圖片信息的解析較為方便,可以直接得到結(jié)構(gòu)化信息。gifsicle支持命令管道級(jí)聯(lián),處理圖片速度較快。實(shí)際生產(chǎn)過程中,同時(shí)采用了兩個(gè)工具。

          const {spawn} = require('child_process');

          const image = gm("src2/"+file)

            image.identify((err, val) => {

              if(!val.Scene){

                    console.log(file+" has err:"+err)

                    return

              }

              let frames_count = val.Scene[0].replace(/\d* of /, '') * 1

              let gap = countGap(frames_count)


              let delayList = [];

              let totaldelay = 0

              if(val.Delay!=undefined){

                    let iii

                    for(iii = 0; iii < val.Delay.length; iii ++) {

                      delayList[iii] = val.Delay[iii].replace(/x\d*/, '') * 1

                      totaldelay+=delayList[iii]

                    }

                    for(; iii < val.Scene.length; iii ++) {

                      delayList[iii] = 8

                      totaldelay+=delayList[iii]

                    }

              }else{

                    for(let iii = 0; iii < val.Scene.length; iii ++) {

                      delayList[iii] = 8

                      totaldelay+=delayList[iii]

                    }

              }

              let totalFrame = parseInt(frames_count/gap)

              //判斷是否速度過慢,需要進(jìn)行歸一加速處理

              if(totaldelay/totalFrame>20){

                    let scale =(totalFrame*1.0*20)/totaldelay

                    for(let iii = 0; iii < delayList.length; iii ++) {

                      delayList[iii] = parseInt(delayList[iii] * scale)

                    }

              }


              let params=[]

              params.push("--colors=255")

              params.push("--unoptimize")

              params.push("src2/"+file)


              let tempdelay = delayList[0]

              for(let iii = 1; iii < frames_count; iii ++) {

                    if(i%gap==0){

                      params.push("-d"+tempdelay)

                      params.push("#"+(iii-gap))

                      tempdelay=0

                    }

                tempdelay += delayList[iii]

              }

              params.push("--optimize=3")

              params.push("-o")

              params.push("src2/"+file+"gap-keepdelay.gif")

              spawn("gifsicle", params, { stdio: 'inherit'})

          })

          測(cè)試時(shí),采用該算法隨機(jī)選擇50張gif圖進(jìn)行壓縮,原尺寸15.5M被壓縮到6.0M,壓縮比38%,不過由于該算法的壓縮比率和具體圖片質(zhì)量、幀數(shù)、圖像特征有關(guān),測(cè)試數(shù)據(jù)僅供參考。

          本文到這里就結(jié)束了,原來看似簡(jiǎn)單的表情包,也有不少文章可做。

          謝謝觀看,希望文中介紹的知識(shí)和研究方法對(duì)你有所啟發(fā)。

          附錄:來自即時(shí)通訊大廠的分享

          [1] QQ、微信團(tuán)隊(duì)原創(chuàng)技術(shù)文章:

          微信朋友圈千億訪問量背后的技術(shù)挑戰(zhàn)和實(shí)踐總結(jié)

          騰訊技術(shù)分享:騰訊是如何大幅降低帶寬和網(wǎng)絡(luò)流量的(圖片壓縮篇)

          騰訊技術(shù)分享:騰訊是如何大幅降低帶寬和網(wǎng)絡(luò)流量的(音視頻技術(shù)篇)

          微信團(tuán)隊(duì)分享:微信移動(dòng)端的全文檢索多音字問題解決方案

          騰訊技術(shù)分享:Android版手機(jī)QQ的緩存監(jiān)控與優(yōu)化實(shí)踐

          微信團(tuán)隊(duì)分享:iOS版微信的高性能通用key-value組件技術(shù)實(shí)踐

          微信團(tuán)隊(duì)分享:iOS版微信是如何防止特殊字符導(dǎo)致的炸群、APP崩潰的?

          騰訊技術(shù)分享:Android手Q的線程死鎖監(jiān)控系統(tǒng)技術(shù)實(shí)踐

          微信團(tuán)隊(duì)原創(chuàng)分享:iOS版微信的內(nèi)存監(jiān)控系統(tǒng)技術(shù)實(shí)踐

          讓互聯(lián)網(wǎng)更快:新一代QUIC協(xié)議在騰訊的技術(shù)實(shí)踐分享

          iOS后臺(tái)喚醒實(shí)戰(zhàn):微信收款到賬語音提醒技術(shù)總結(jié)

          騰訊技術(shù)分享:社交網(wǎng)絡(luò)圖片的帶寬壓縮技術(shù)演進(jìn)之路

          微信團(tuán)隊(duì)分享:視頻圖像的超分辨率技術(shù)原理和應(yīng)用場(chǎng)景

          微信團(tuán)隊(duì)分享:微信每日億次實(shí)時(shí)音視頻聊天背后的技術(shù)解密

          QQ音樂團(tuán)隊(duì)分享:Android中的圖片壓縮技術(shù)詳解(上篇)

          QQ音樂團(tuán)隊(duì)分享:Android中的圖片壓縮技術(shù)詳解(下篇)

          騰訊團(tuán)隊(duì)分享:手機(jī)QQ中的人臉識(shí)別酷炫動(dòng)畫效果實(shí)現(xiàn)詳解

          騰訊團(tuán)隊(duì)分享 :一次手Q聊天界面中圖片顯示bug的追蹤過程分享

          微信團(tuán)隊(duì)分享:微信Android版小視頻編碼填過的那些坑》 

          微信手機(jī)端的本地?cái)?shù)據(jù)全文檢索優(yōu)化之路》 

          企業(yè)微信客戶端中組織架構(gòu)數(shù)據(jù)的同步更新方案優(yōu)化實(shí)戰(zhàn)

          微信團(tuán)隊(duì)披露:微信界面卡死超級(jí)bug“15。。。。”的來龍去脈

          QQ 18年:解密8億月活的QQ后臺(tái)服務(wù)接口隔離技術(shù)

          月活8.89億的超級(jí)IM微信是如何進(jìn)行Android端兼容測(cè)試的

          以手機(jī)QQ為例探討移動(dòng)端IM中的“輕應(yīng)用”

          一篇文章get微信開源移動(dòng)端數(shù)據(jù)庫組件WCDB的一切!

          微信客戶端團(tuán)隊(duì)負(fù)責(zé)人技術(shù)訪談:如何著手客戶端性能監(jiān)控和優(yōu)化

          微信后臺(tái)基于時(shí)間序的海量數(shù)據(jù)冷熱分級(jí)架構(gòu)設(shè)計(jì)實(shí)踐

          微信團(tuán)隊(duì)原創(chuàng)分享:Android版微信的臃腫之困與模塊化實(shí)踐之路

          微信后臺(tái)團(tuán)隊(duì):微信后臺(tái)異步消息隊(duì)列的優(yōu)化升級(jí)實(shí)踐分享

          微信團(tuán)隊(duì)原創(chuàng)分享:微信客戶端SQLite數(shù)據(jù)庫損壞修復(fù)實(shí)踐》 

          騰訊原創(chuàng)分享(一):如何大幅提升移動(dòng)網(wǎng)絡(luò)下手機(jī)QQ的圖片傳輸速度和成功率》 

          騰訊原創(chuàng)分享(二):如何大幅壓縮移動(dòng)網(wǎng)絡(luò)下APP的流量消耗(下篇)》 

          騰訊原創(chuàng)分享(三):如何大幅壓縮移動(dòng)網(wǎng)絡(luò)下APP的流量消耗(上篇)》 

          微信Mars:微信內(nèi)部正在使用的網(wǎng)絡(luò)層封裝庫,即將開源》 

          如約而至:微信自用的移動(dòng)端IM網(wǎng)絡(luò)層跨平臺(tái)組件庫Mars已正式開源》 

          開源libco庫:?jiǎn)螜C(jī)千萬連接、支撐微信8億用戶的后臺(tái)框架基石 [源碼下載]》 

          微信新一代通信安全解決方案:基于TLS1.3的MMTLS詳解》 

          微信團(tuán)隊(duì)原創(chuàng)分享:Android版微信后臺(tái)保活實(shí)戰(zhàn)分享(進(jìn)程保活篇)》 

          微信團(tuán)隊(duì)原創(chuàng)分享:Android版微信后臺(tái)保活實(shí)戰(zhàn)分享(網(wǎng)絡(luò)保活篇)》 

          Android版微信從300KB到30MB的技術(shù)演進(jìn)(PPT講稿) [附件下載]》 

          微信團(tuán)隊(duì)原創(chuàng)分享:Android版微信從300KB到30MB的技術(shù)演進(jìn)》 

          微信技術(shù)總監(jiān)談架構(gòu):微信之道——大道至簡(jiǎn)(演講全文)

          微信技術(shù)總監(jiān)談架構(gòu):微信之道——大道至簡(jiǎn)(PPT講稿) [附件下載]》 

          如何解讀《微信技術(shù)總監(jiān)談架構(gòu):微信之道——大道至簡(jiǎn)》

          微信海量用戶背后的后臺(tái)系統(tǒng)存儲(chǔ)架構(gòu)(視頻+PPT) [附件下載]

          微信異步化改造實(shí)踐:8億月活、單機(jī)千萬連接背后的后臺(tái)解決方案》 

          微信朋友圈海量技術(shù)之道PPT [附件下載]》 

          微信對(duì)網(wǎng)絡(luò)影響的技術(shù)試驗(yàn)及分析(論文全文)》 

          一份微信后臺(tái)技術(shù)架構(gòu)的總結(jié)性筆記》 

          架構(gòu)之道:3個(gè)程序員成就微信朋友圈日均10億發(fā)布量[有視頻]》 

          快速裂變:見證微信強(qiáng)大后臺(tái)架構(gòu)從0到1的演進(jìn)歷程(一)

          快速裂變:見證微信強(qiáng)大后臺(tái)架構(gòu)從0到1的演進(jìn)歷程(二)》 

          微信團(tuán)隊(duì)原創(chuàng)分享:Android內(nèi)存泄漏監(jiān)控和優(yōu)化技巧總結(jié)》 

          全面總結(jié)iOS版微信升級(jí)iOS9遇到的各種“坑”》 

          微信團(tuán)隊(duì)原創(chuàng)資源混淆工具:讓你的APK立減1M》 

          微信團(tuán)隊(duì)原創(chuàng)Android資源混淆工具:AndResGuard [有源碼]》 

          Android版微信安裝包“減肥”實(shí)戰(zhàn)記錄》 

          iOS版微信安裝包“減肥”實(shí)戰(zhàn)記錄》 

          移動(dòng)端IM實(shí)踐:iOS版微信界面卡頓監(jiān)測(cè)方案》 

          微信“紅包照片”背后的技術(shù)難題》 

          移動(dòng)端IM實(shí)踐:iOS版微信小視頻功能技術(shù)方案實(shí)錄》 

          移動(dòng)端IM實(shí)踐:Android版微信如何大幅提升交互性能(一)

          移動(dòng)端IM實(shí)踐:Android版微信如何大幅提升交互性能(二)

          移動(dòng)端IM實(shí)踐:實(shí)現(xiàn)Android版微信的智能心跳機(jī)制》 

          移動(dòng)端IM實(shí)踐:WhatsApp、Line、微信的心跳策略分析》 

          移動(dòng)端IM實(shí)踐:谷歌消息推送服務(wù)(GCM)研究(來自微信)

          移動(dòng)端IM實(shí)踐:iOS版微信的多設(shè)備字體適配方案探討》 

          信鴿團(tuán)隊(duì)原創(chuàng):一起走過 iOS10 上消息推送(APNS)的坑

          騰訊信鴿技術(shù)分享:百億級(jí)實(shí)時(shí)消息推送的實(shí)戰(zhàn)經(jīng)驗(yàn)

          IPv6技術(shù)詳解:基本概念、應(yīng)用現(xiàn)狀、技術(shù)實(shí)踐(上篇)

          IPv6技術(shù)詳解:基本概念、應(yīng)用現(xiàn)狀、技術(shù)實(shí)踐(下篇)

          騰訊TEG團(tuán)隊(duì)原創(chuàng):基于MySQL的分布式數(shù)據(jù)庫TDSQL十年鍛造經(jīng)驗(yàn)分享

          微信多媒體團(tuán)隊(duì)訪談:音視頻開發(fā)的學(xué)習(xí)、微信的音視頻技術(shù)和挑戰(zhàn)等

          了解iOS消息推送一文就夠:史上最全iOS Push技術(shù)詳解

          騰訊技術(shù)分享:微信小程序音視頻技術(shù)背后的故事

          騰訊資深架構(gòu)師干貨總結(jié):一文讀懂大型分布式系統(tǒng)設(shè)計(jì)的方方面面

          微信多媒體團(tuán)隊(duì)梁俊斌訪談:聊一聊我所了解的音視頻技術(shù)

          騰訊音視頻實(shí)驗(yàn)室:使用AI黑科技實(shí)現(xiàn)超低碼率的高清實(shí)時(shí)視頻聊天

          騰訊技術(shù)分享:微信小程序音視頻與WebRTC互通的技術(shù)思路和實(shí)踐

          手把手教你讀取Android版微信和手Q的聊天記錄(僅作技術(shù)研究學(xué)習(xí))

          微信技術(shù)分享:微信的海量IM聊天消息序列號(hào)生成實(shí)踐(算法原理篇)

          微信技術(shù)分享:微信的海量IM聊天消息序列號(hào)生成實(shí)踐(容災(zāi)方案篇)

          騰訊技術(shù)分享:GIF動(dòng)圖技術(shù)詳解及手機(jī)QQ動(dòng)態(tài)表情壓縮技術(shù)實(shí)踐

          >> 更多同類文章 ……

          [2] 有關(guān)QQ、微信的技術(shù)故事:

          技術(shù)往事:微信估值已超5千億,雷軍曾有機(jī)會(huì)收編張小龍及其Foxmail

          QQ和微信兇猛成長(zhǎng)的背后:騰訊網(wǎng)絡(luò)基礎(chǔ)架構(gòu)的這些年

          閑話即時(shí)通訊:騰訊的成長(zhǎng)史本質(zhì)就是一部QQ成長(zhǎng)史

          2017微信數(shù)據(jù)報(bào)告:日活躍用戶達(dá)9億、日發(fā)消息380億條

          騰訊開發(fā)微信花了多少錢?技術(shù)難度真這么大?難在哪?

          技術(shù)往事:創(chuàng)業(yè)初期的騰訊——16年前的冬天,誰動(dòng)了馬化騰的代碼》 

          技術(shù)往事:史上最全QQ圖標(biāo)變遷過程,追尋IM巨人的演進(jìn)歷史》 

          技術(shù)往事:“QQ群”和“微信紅包”是怎么來的?》 

          開發(fā)往事:深度講述2010到2015,微信一路風(fēng)雨的背后》 

          開發(fā)往事:微信千年不變的那張閃屏圖片的由來》 

          開發(fā)往事:記錄微信3.0版背后的故事(距微信1.0發(fā)布9個(gè)月時(shí))》 

          一個(gè)微信實(shí)習(xí)生自述:我眼中的微信開發(fā)團(tuán)隊(duì)

          首次揭秘:QQ實(shí)時(shí)視頻聊天背后的神秘組織

          為什么說即時(shí)通訊社交APP創(chuàng)業(yè)就是一個(gè)坑?

          微信七年回顧:歷經(jīng)多少質(zhì)疑和差評(píng),才配擁有今天的強(qiáng)大

          前創(chuàng)始團(tuán)隊(duì)成員分享:盤點(diǎn)微信的前世今生——微信成功的必然和偶然

          即時(shí)通訊創(chuàng)業(yè)必讀:解密微信的產(chǎn)品定位、創(chuàng)新思維、設(shè)計(jì)法則等

          QQ的成功,遠(yuǎn)沒有你想象的那么順利和輕松

          QQ現(xiàn)狀深度剖析:你還認(rèn)為QQ已經(jīng)被微信打敗了嗎?

          [技術(shù)腦洞] 如果把14億中國(guó)人拉到一個(gè)微信群里技術(shù)上能實(shí)現(xiàn)嗎?》 

          >> 更多同類文章 ……

          (本文同步發(fā)布于:http://www.52im.net/thread-2032-1-1.html



          作者:Jack Jiang (點(diǎn)擊作者姓名進(jìn)入Github)
          出處:http://www.52im.net/space-uid-1.html
          交流:歡迎加入即時(shí)通訊開發(fā)交流群 215891622
          討論:http://www.52im.net/
          Jack Jiang同時(shí)是【原創(chuàng)Java Swing外觀工程BeautyEye】【輕量級(jí)移動(dòng)端即時(shí)通訊框架MobileIMSDK】的作者,可前往下載交流。
          本博文 歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)注明出處(也可前往 我的52im.net 找到我)。


          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          Jack Jiang的 Mail: jb2011@163.com, 聯(lián)系QQ: 413980957, 微信: hellojackjiang
          主站蜘蛛池模板: 陆丰市| 玛曲县| 琼中| 兴安县| 胶州市| 沂南县| 清苑县| 夹江县| 称多县| 玉龙| 遂昌县| 沐川县| 杭锦旗| 廉江市| 山阴县| 阿拉善盟| 宁阳县| 玉溪市| 禄丰县| 海原县| 蒲城县| 韩城市| 邻水| 沅江市| 土默特左旗| 招远市| 宾阳县| 张家港市| 鄂伦春自治旗| 南岸区| 沈丘县| 三河市| 皮山县| 会理县| 霍林郭勒市| 景洪市| 长治市| 新建县| 衡南县| 彭阳县| 隆化县|