PNG尺寸縮小實(shí)戰(zhàn)

為了節(jié)省資源,我們希望在不同分辨率的前端上可以獲取到不同尺寸的素材資源守屉。由于最近的業(yè)務(wù)中使用的所有素材都是PNG格式的圖片,并且對(duì)圖片效果要求比較嚴(yán)格,并沒(méi)有在市面上找到可以直接使用的服務(wù)入客,于是自行實(shí)現(xiàn)整個(gè)服務(wù)。

TL;DR

首先使用ImageMagick對(duì)圖片進(jìn)行縮放(假設(shè)輸出是64*64的圖片)和去模糊腿椎,再使用pngquant對(duì)縮放后的圖片進(jìn)行有損壓縮(假設(shè)原圖顏色數(shù)量為128)桌硫。

convert src.png -resize 64x64 resize.png
convert resize.png -unsharp 1.5x1+0.7+0.02 output.png
pngquant 128 -f --ext .png output.png

工具的選擇的心路歷程

圖片縮放

最早使用了號(hào)稱命令行上的Photoshop的ImageMagick來(lái)對(duì)圖片進(jìn)行縮放。當(dāng)然功能可以實(shí)現(xiàn)啃炸,只是發(fā)現(xiàn)圖片尺寸裁剪之后铆隘,文件本身的體積反而變大了。后來(lái)嘗試了各種不同的工具肮帐,包括Java的ImageIO咖驮,Python的PIL边器,以及知名圖片壓縮服務(wù)TinyPng的SDK。不同的工具不僅裁剪后文件大小不同托修,效果也有所差異忘巧。其中TinyPng表現(xiàn)最好,大部分時(shí)候圖片被縮小后文件尺寸也會(huì)隨之減小睦刃,但是也有個(gè)別圖片仍然存在同樣的問(wèn)題砚嘴。
在查閱到相關(guān)資料png 裁剪時(shí)遇到問(wèn)題,得到了較好的解釋:

原圖類型 Type: PaletteAlpha涩拙,Base type: TrueColorAlpha际长,本身就是經(jīng)過(guò)壓縮和優(yōu)化了的。
resize 時(shí)兴泥,會(huì)進(jìn)行各種差值工育,信息也會(huì)變多,類型也變成了 TrueColorAlpha搓彻。

這里涉及到了PNG文件具體格式相關(guān)資料如绸,可以參考PNG-8、24旭贬、32區(qū)別介紹PNG的故事怔接。

圖片顏色信息減少

在確認(rèn)造成文件變大的原因是顏色信息增多之后,自然是選擇將顏色信息適當(dāng)減少稀轨。由于我們要處理的圖片是縮小后的圖片扼脐,需要的顏色應(yīng)該不會(huì)比原圖要更多,所以我們目標(biāo)是將縮小后的圖片的顏色數(shù)較少到和原圖的顏色數(shù)相同奋刽。
這里我們使用一個(gè)有損壓縮工具pngquant來(lái)壓縮圖片和減少顏色數(shù)量瓦侮。選擇他是為數(shù)不多能直接改變顏色數(shù)的壓縮工具。
經(jīng)過(guò)縮小壓縮之后杨名,裁剪后的圖片文件已經(jīng)明顯小于原圖脏榆。相關(guān)文件的具體信息可以通過(guò)ImageMagick的identify命令來(lái)直接查看:

identify -verbose src.png

到這一步大部分需求已經(jīng)實(shí)現(xiàn),但是卻在個(gè)別邊緣分明的素材上發(fā)現(xiàn)了明顯的邊緣模糊台谍,導(dǎo)致視覺(jué)效果不佳须喂。

圖片去模糊

首先是排查原因。
起初我以為是我在壓縮的過(guò)程中趁蕊,過(guò)分減少了輸出圖片的顏色數(shù)量坞生,導(dǎo)致細(xì)節(jié)丟失。后來(lái)發(fā)現(xiàn)那些邊緣分明的圖片在resize時(shí)就已經(jīng)出現(xiàn)了模糊現(xiàn)象掷伙,那問(wèn)題自然是在ImageMagick的使用上是己。
之后在ImageMagick的官方文檔中找到了一片《Resampling Filter》,介紹了在圖片縮放時(shí)候的會(huì)遇到的各種問(wèn)題和各種參數(shù)的使用任柜。例如:


在模糊問(wèn)題上更是有另外一片文檔《Resize Unsharp》來(lái)說(shuō)明如何處理resize過(guò)程中的模糊問(wèn)題卒废。參照文檔使用下列命令可以很好地銳化圖片:

convert resize.png -unsharp 1.5x1+0.7+0.02 output.png

至此將三個(gè)步驟整合在一起沛厨,就可以達(dá)到令人滿意的png縮小效果。

相關(guān)原理

Resize

Resize的實(shí)際處理過(guò)程叫做Resampling摔认,即重采樣逆皮。簡(jiǎn)單來(lái)說(shuō),可以看作操作一個(gè)數(shù)組参袱,增加或者減少這個(gè)數(shù)組的元素电谣,并且讓處理的結(jié)果在人眼看起來(lái)不那么糟糕。其實(shí)這是一個(gè)非常復(fù)雜的問(wèn)題抹蚀,也有人專門從事這方面的研究剿牺,這里不展開(kāi)討論,還是要看《Resampling Filter》环壤,里面介紹了各種Resampling的策略晒来,也會(huì)說(shuō)明為什么圖片縮小后顏色數(shù)量會(huì)增多。
由于這個(gè)問(wèn)題的復(fù)雜性镐捧,所以沒(méi)有一套完美的方案可以解決所有場(chǎng)景下素材的resize潜索,畢竟有太多的策略和參數(shù)可以選擇,最終的方案是需要根據(jù)需求進(jìn)行取舍的。

有損壓縮

處理中關(guān)鍵的一部是使用pngquant進(jìn)行有損壓縮演痒。為什么顏色變少之后文件尺寸迅速下降橘洞?首先是因?yàn)轭伾珨?shù)量如果少于255,輸出的圖片將可以保存為PNG-8格式鄙漏,這樣就減少了像素深度。另外主要縮小圖片的原因還是PNG本身壓縮過(guò)程中的Filtering和DEFLATE算法起作用。簡(jiǎn)而言之瞎领,如果一個(gè)數(shù)組內(nèi)相似的元素越多,那么DEFLATE就可以將其壓縮得越小随夸。而Filtering步驟可以用差分編碼的編碼方式九默,即是記錄當(dāng)前數(shù)據(jù)和某個(gè)標(biāo)準(zhǔn)值的差距來(lái)存儲(chǔ)當(dāng)前數(shù)據(jù)。
比如說(shuō)有這么一個(gè)數(shù)組[99, 100, 100, 102, 103]宾毒,我們可以將其轉(zhuǎn)存為[99, 1, 0, 2, 1]驼修。轉(zhuǎn)存的規(guī)則就是以數(shù)組第1位為標(biāo)準(zhǔn)值,標(biāo)準(zhǔn)值存儲(chǔ)原始數(shù)據(jù)诈铛,后續(xù)均存儲(chǔ)以前1位數(shù)據(jù)的差值乙各。PNG一共支持5種Filtering,基本原理相似幢竹。通過(guò)類似這樣的轉(zhuǎn)換之后耳峦,DEFLATE就可以更好得壓縮數(shù)據(jù)。

END

特別鳴謝:V友icyalala
參考資料
PNG-8焕毫、24蹲坷、32區(qū)別介紹
Resampling Filter
減少PNG文件的大小
PNG的故事

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末驶乾,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子循签,更是在濱河造成了極大的恐慌轻掩,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,270評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件懦底,死亡現(xiàn)場(chǎng)離奇詭異唇牧,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)聚唐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門丐重,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人杆查,你說(shuō)我怎么就攤上這事扮惦。” “怎么了亲桦?”我有些...
    開(kāi)封第一講書人閱讀 165,630評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵崖蜜,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我客峭,道長(zhǎng)豫领,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 58,906評(píng)論 1 295
  • 正文 為了忘掉前任舔琅,我火速辦了婚禮等恐,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘备蚓。我一直安慰自己课蔬,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布郊尝。 她就那樣靜靜地躺著二跋,像睡著了一般。 火紅的嫁衣襯著肌膚如雪流昏。 梳的紋絲不亂的頭發(fā)上扎即,一...
    開(kāi)封第一講書人閱讀 51,718評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音横缔,去河邊找鬼铺遂。 笑死,一個(gè)胖子當(dāng)著我的面吹牛茎刚,可吹牛的內(nèi)容都是我干的襟锐。 我是一名探鬼主播,決...
    沈念sama閱讀 40,442評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼膛锭,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼粮坞!你這毒婦竟也來(lái)了蚊荣?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,345評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤莫杈,失蹤者是張志新(化名)和其女友劉穎互例,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體筝闹,經(jīng)...
    沈念sama閱讀 45,802評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡媳叨,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了关顷。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片糊秆。...
    茶點(diǎn)故事閱讀 40,117評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖议双,靈堂內(nèi)的尸體忽然破棺而出痘番,到底是詐尸還是另有隱情,我是刑警寧澤平痰,帶...
    沈念sama閱讀 35,810評(píng)論 5 346
  • 正文 年R本政府宣布汞舱,位于F島的核電站,受9級(jí)特大地震影響宗雇,放射性物質(zhì)發(fā)生泄漏昂芜。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評(píng)論 3 331
  • 文/蒙蒙 一逾礁、第九天 我趴在偏房一處隱蔽的房頂上張望说铃。 院中可真熱鬧,春花似錦嘹履、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,011評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至窒篱,卻和暖如春焕刮,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背墙杯。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,139評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工配并, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人高镐。 一個(gè)月前我還...
    沈念sama閱讀 48,377評(píng)論 3 373
  • 正文 我出身青樓溉旋,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親嫉髓。 傳聞我的和親對(duì)象是個(gè)殘疾皇子观腊,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,180評(píng)論 25 707
  • 王埃拉閱讀 105評(píng)論 0 3
  • 你到故鄉(xiāng)來(lái)邑闲, 路兩邊盛開(kāi)著無(wú)數(shù)的野薔薇。 紅的梧油、白的花朵兒 是尋覓許久不曾到來(lái)的驚喜苫耸。 多少年來(lái), 以為離鄉(xiāng)是一種...
    清若閱讀 564評(píng)論 7 8
  • 不久前和一個(gè)10年未見(jiàn)的發(fā)小肖君見(jiàn)面褐筛,酒足飯飽以后。肖君不停的向我傾述叙身, 原來(lái)肖君在考研渔扎,這已經(jīng)是第四次考研了,就...
    筆下春天閱讀 901評(píng)論 2 2