有關(guān)圖片壓縮整理

紋理壓縮

有損壓縮:是指對圖像的壓縮過程中,算法丟失一部分圖像信息,降低了圖像的質(zhì)量,并且這種損失是不可逆的。有損壓縮可以減少圖像在內(nèi)存和磁盤中占用的空間。使用有損壓縮的圖片如果在屏幕上顯示,可能肉眼看起來影響不大,但如果用高分辨率打印機(jī)打印出來,那么圖像質(zhì)量就會有明顯的受損痕跡

無損壓縮:是指對圖像的壓縮過程中,不丟失圖片原本的信息,任何時(shí)候都可以從無損壓縮過的圖片中恢復(fù)出原本的信息;無損壓縮雖然能減小圖像占用磁盤的大小,但不能減少圖像占用的內(nèi)存空間,因?yàn)閷?shí)際的顯示過程中,看圖軟件會先把圖片還原成原本的信息。無損壓縮能較好的保存圖片質(zhì)量,但壓縮率較低

索引色和直接色

索引色:用一個(gè)數(shù)組來代表一種顏色,在存儲圖像的時(shí)候,存儲一個(gè)數(shù)字的組合,同時(shí)存儲數(shù)字到圖像顏色的映射。這種方式只能存儲有限種顏色,通常的用法是256種顏色

直接色:使用四個(gè)數(shù)字來代表一種顏色,這四個(gè)數(shù)字分別代表顏色中的紅色R、綠色G、藍(lán)色B以及透明度A。所以直接色可以表示2^32種顏色。當(dāng)然,并非所有的直接色都直接這么多種變化,為壓縮空間,可能有多種設(shè)定

點(diǎn)陣圖和矢量圖

點(diǎn)陣圖:也叫位圖,象素圖。構(gòu)成點(diǎn)陣圖的最小單位是像素,位圖就是由像素點(diǎn)陣列的排列來實(shí)現(xiàn)其顯示效果。點(diǎn)陣圖縮放會失真

矢量圖:也叫做向量圖。矢量圖并不記錄畫面上每一點(diǎn)的信息,而是記錄元素的形狀以及顏色的算法,當(dāng)你打開一副矢量圖的時(shí)候,軟件對圖像對應(yīng)的函數(shù)進(jìn)行運(yùn)算,將運(yùn)算結(jié)果顯示給你看,無論顯示畫面是大還是小,畫面對應(yīng)的算法是不變的,所以對畫面進(jìn)行倍數(shù)相當(dāng)大的縮放,其顯示效果仍然相同(不失真)

不同圖片格式的特性

介紹了這些,那么我們來看看我們經(jīng)常見到的圖片的一些特性

JPEG 有損,直接色,點(diǎn)陣圖 ;BMP 無損,直接色,點(diǎn)陣圖;PNG-8 無損,索引色,點(diǎn)陣圖;PNG-24 無損,直接色,點(diǎn)陣圖

為什么png還有多種樣式?那是因?yàn)镻NG算法在把圖像轉(zhuǎn)化成圖片的時(shí)候有很多參數(shù)和方式可以選擇,這些參數(shù)和方式就決定了圖像的壓縮和成像品質(zhì)

為什么需要紋理壓縮?

Android平臺默認(rèn)支持格式:JPEG、PNG、GIF、BMP 和 WebP

iOS平臺默認(rèn)支持格式:JPEG、JPEG2000、PNG、GIF、BMP、ICO、TIFF、PICT、APNG、SVG、RAW

既然Android和iOS支持這么多圖片格式,那么游戲中為什么沒有”直接”使用JPEG或者PNG這兩種都支持格式呢?下面進(jìn)行下原因的分析

常見的圖片文件格式,比如PNG,JPG,BMP等,是圖像為了存儲信息而使用的對信息的特殊編碼方式。它存儲在磁盤中,或者內(nèi)存中,但是并不能被GPU所識別。這些文件格式當(dāng)被讀入后,還是需要經(jīng)過CPU解壓成bitmap,再傳送到GPU端進(jìn)行使用。

1 JPEG不支持透明度

一般在游戲中,有很多透明物件,而JPEG不支持透明度,所以沒法使用

2 PNG不支持隨機(jī)讀取像素

PNG格式支持透明度,但是因?yàn)镻NG的壓縮算法是根據(jù)圖片整體進(jìn)行壓縮(比如采用霍夫曼編碼),像素和像素之間存在依賴關(guān)系,無法直接實(shí)現(xiàn)單個(gè)像素級別的解析,這就沒辦法發(fā)揮顯卡的優(yōu)勢

間接尋址


上圖為間接尋址模式中獲取顏色數(shù)據(jù)的過程:GPU首先請求加載索引數(shù)據(jù)14;一旦有了索引數(shù)據(jù)就可以立即加載實(shí)際顏色值,來回四次最終得到顏色值。索引數(shù)據(jù)可能為FIFO緩沖區(qū)引入了性能隱患,芯片端保存顏色表的代價(jià)也十分大,顏色表可能和紋理緩存占的空間接近;所以最好避免使用顏色表這些全局?jǐn)?shù)據(jù)。

3 無法減小顯存占用

無論是JPEG或者PNG 的圖片最終在顯卡解碼之后,都是RGBA紋理,(寬*高*4)無法減小顯存的占用(256×256像素的圖片,雖然文件格式、磁盤占用、內(nèi)存占用大小不一樣,但都是占用256Kb的顯存空間,性能消耗大)

jpeg和png圖片,從文件加載的時(shí)候都必須先在cpu先解碼成原始的RGB(A)格式的數(shù)據(jù)

紋理壓縮之后占用顯存減少,一種比較簡單的統(tǒng)計(jì)方案。你直接查看紋理壓縮文件的大小就好了,比如紋理壓縮文件是170k,那顯存占用也是170k

紋理格式需求

正是因?yàn)閭鹘y(tǒng)的圖片并沒有考慮顯卡的這種特性,所以很難滿足三維應(yīng)用中的要求,要滿足顯卡能使用的紋理格式,應(yīng)該具有以下特點(diǎn):

1 解析速度

在紋理操作中,讀取紋理數(shù)據(jù)是關(guān)鍵步驟,所以解碼速度至關(guān)重要,這一點(diǎn)是最應(yīng)該考慮的

2 隨機(jī)讀取數(shù)據(jù)

能快速的隨機(jī)讀取任意像素,因?yàn)轱@卡中很多操作都是針對單個(gè)像素執(zhí)行的,所以這一點(diǎn)也很重要

3 壓縮率和紋理質(zhì)量

既要保證一個(gè)不錯(cuò)的壓縮效果,也要把紋理損失控制在一定范圍內(nèi)

4 壓縮速度

通常紋理壓縮在渲染前已經(jīng)提前準(zhǔn)備好,所以如果壓縮的速度比解析速度慢,也是可以接受的。

說明:Unity在導(dǎo)入圖片后,編輯器會卡住彈出一個(gè)進(jìn)度條窗口,就是使用原圖進(jìn)行紋理壓縮然后生成新的圖片文件的過程。生成的文件的位置,你可以根據(jù)導(dǎo)入圖片對應(yīng)的.meta文件內(nèi)的guid,去項(xiàng)目中的Library文件夾中查找,Unity打包圖片的Assetbundle其實(shí)是根據(jù)這個(gè)文件來打包的,這已經(jīng)不是你導(dǎo)入的那張?jiān)瓐D

紋理壓縮技術(shù)

紋理壓縮不同于其他圖片壓縮方式(jpg,png),在使用中,不會在CPU中進(jìn)行解壓縮,而是直接把壓縮內(nèi)容傳給GPU,而且在GPU中也不會一次把整張圖片進(jìn)行解壓縮,只會在需要采樣特定區(qū)域的紋理時(shí)對這一區(qū)域的紋理進(jìn)行解壓縮。

紋理壓縮格式

為了滿足以上4點(diǎn),圖形工程師開發(fā)了很多種紋理壓縮格式,目前移動(dòng)設(shè)備主流的紋理壓縮格式有PVRTC、ETC/ETC2、ASTC,當(dāng)然,還有其他的類型(比如:RGBA32、RGBA16、Alpha8等有興趣的可以去了解下)

紋理壓縮格式不需要CPU解碼

ETC/ETC2紋理壓縮格式

說到ETC ,就要說到OpenGL ES,OpenGL ES 是 OpenGL 三維圖形 API 的子集,針對手機(jī)、平板和游戲主機(jī)等嵌入式設(shè)備而設(shè)計(jì). OpenGL ES2 支持ETC 格式,所以我們可以在支持OpenGL ES2的顯卡的設(shè)備上使用ETC這種紋理壓縮格式;而ETC2 則需要OpenGL ES3才能支持,而OpenGL ES3已經(jīng)發(fā)布了三四年,所以現(xiàn)在市面上的顯卡都支持,也就是說,現(xiàn)在市面上的移動(dòng)設(shè)備都支持ETC2這種紋理壓縮格式了,可以放心使用了;

ETC不支持透明通道,所以以前很多項(xiàng)目的做法是用2張紋理來保存一張圖片。ETC+Alpha8的組合形式,然后用自定義Shader合并。不過現(xiàn)在基本淘汰,可以直接使用ETC2代替。

Alpha壓縮率適用機(jī)型

ETC1N6:1OpenGLES 2.0支持幾乎所有市面上的Android機(jī),所有iPhone

ETC2Y6:1OpenGLES3.0支持大部分高端Android機(jī),iPhone 5S及以上

PVRTC紋理壓縮格式

iPhone的圖形芯片(PowerVR MBX)對 PVRTC 的壓縮提供硬件支持,Apple推薦在開發(fā)iPhone應(yīng)用程序時(shí)使用 PVRTC 壓縮紋理格式。而且,根據(jù)圖像成圖質(zhì)量以及占用內(nèi)存等,有多種格式可選擇(pvtrc_rgba2,pvrtc_rbga4等);缺點(diǎn)是需要圖片的長寬相等而且為2的冪次方(針對這種情況,可以考慮把圖片打包在一張2的冪次方圖集內(nèi))

支持的Android機(jī)型需要GPU為 PowerVR系列

總結(jié)

在實(shí)際游戲引擎內(nèi)(以Unity為例),圖片顯示流程大概是:原圖 —> 紋理壓縮(ETC/ETC2等)—>OpenGL ES3—>顯卡—>游戲內(nèi)顯示;

而一張圖片在游戲引擎中運(yùn)行時(shí)占用的顯存大小,與這種圖片本身占用磁盤大小無關(guān),只和圖片的寬和高相關(guān);

圖片導(dǎo)入到Unity引擎中,之所以很慢,是因?yàn)樵谶M(jìn)行紋理壓縮編碼生成新的文件,這一步很耗時(shí)間;

AssetBundle打包圖片,不是打包原圖,而是針對你對圖片設(shè)置的紋理壓縮格式而生成的新的文件打包,所以ab文件的大小也和原圖本身占用磁盤大小無關(guān);

AssetBundle文件的大小與加載成正比關(guān)系,同時(shí),紋理壓縮格式的解碼時(shí)間也有差異(差異不是很大)

平臺的最佳紋理壓縮格式是:astc_rgba_4x4 它兼顧了成像質(zhì)量,內(nèi)存占用,ab大小,解碼時(shí)間,跨平臺等因素

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容