天天看點

幾種主流貼圖壓縮算法的實作原理1. DXTC2. ETC3. PVRTC4. ASTC

前段時間一直在搞項目上線前的各種優化,關于貼圖壓縮這塊也是需要針對不同的平台做不同的設定,這裡備忘一下在各種平台中常使用的幾種貼圖壓縮格式及其細節,以便更加适宜地選擇在特定裝置下的壓縮格式以便節省資源。關于移動平台和硬體裝置與壓縮格式的對應關系可以參考下這裡,基本上比較清楚了。

1. DXTC

DXTC(或BC)為微軟為DX而推出的基于block的貼圖壓縮格式,其主要采用調色闆的原理來進行壓縮。

BC1:

基于4x4block來進行,不含有alpha通道,每個block内記錄兩個16bits的顔色做為基準顔色,然後解壓時再使用兩個基準色調制出另外兩個顔色做為塊内4個壓縮顔色。其計算方式為:

basecolor2 = 2/3 *basecolor0 + 1/3 * basecolor1

basecolro3 = 1/3 *basecolor0 + 2/3 * basecolor1

對于每個塊内的texel,存儲2bits的索引,用來指向到4個基準顔色中的一個。是以對于BC1的壓縮狀态為64bits:

  • 32bits:兩個RGB565格式的基準顔色;
  • 32bits:16個2bits的索引;

BC3:

在BC1的基礎上支援alpha通道。首先,顔色的存儲方式與BC1相同,需要64bits;對于alpha部分,使用與顔色部分相同的政策來處理。在block存儲兩個基準的alpha值,然後在其基礎上插值得到其它6個共計8個alpha值,來做為alpha的調色闆;然後對于每個texel存儲一個3bits的索引,用來指向到這8個alpha中的一個。是以其對應的存儲狀态為:

  • 32bits:兩個RGB565格式的基準顔色;
  • 32bits:16個2bits的顔色索引;
  • 48bits:16個3bits的alpha索引;
  • 16bits:2個8bits的基準alpha;

同時,兩個alpha值中的不同的标記情況也對應着不同的插值操作:

若alpha0 > alpha1

alphai = (7 - i) / 7 *alpha0 + i/7 * alpha1;(2<=i<=7);

若alpha0 < alpha1

alphai = (5 - i) / 5 *alpha0 + i/5 * alpha1;(2<=i<=5);

alpha6 = 0;

alpha7=255;

2. ETC

ETC壓縮算法采用将圖像中的chromatic和luminance分開存儲的方式,而在解碼時使用luminance對chromatic進行調制進而重制原始圖像資訊。

幾種主流貼圖壓縮算法的實作原理1. DXTC2. ETC3. PVRTC4. ASTC

ETC也主要有兩種方法:ETC1和改進後的ETC2。

ETC1:

采用4x2的block進行分割(原始為4*2*24=192,壓縮後為32,壓縮率為6):

對于所有圖檔都使用一個全局的16個組table codeword,每組中有四個數值,且其中是有規律可循的,如下所示:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
-8 -12 -31 -34 -50 -47 -80 -127 -16 -24 -62 -68 -100 -94 -160 -254
-2 -4 -6 -12 -8 -19 -28 -42 -4 -8 -12 -24 -16 -38 -56 -84
2 4 6 12 8 19 28 42 4 8 12 24 16 38 56 84
8 12 31 34 50 47 80 127 16 24 62 68 100 94 160 254
  • 12bits:RBG444的一個basecolor,其在使用是需要被擴充到8bits;每個block使用32bits進行編輯存儲;比如對于RGB=(0,2,15) -> (0000 ,0010 , 1111),擴充後為(000000,00100010 , 11111111)->(0 , 34 , 255),擴充方法為直接将原始4位複制後拼接為8位即可;
  • 4bits:用來索引16個table codeword中的一組,比如{-10 , -1 , 4 , 7};
  • 16bits:對于block中的每個pixel配置設定2bits,就有4個值,用來索引目前像素對應于table codeword中的每個modifier,該modifier需要組成三個通道的調整值,比如,對于某個pixel其對應的modifier索引值為2,也即對應上述table codeword中的4,如此一來該pixel的RGB = (0,34,255) + (4,4,4)=(4,38,259),最後需要将其clamp至0,255,因而即為(4,38,255)。

改進後采用4x4的block進行分割(原始為4*4*24= 384, 壓縮後為64, 壓縮率為6):

主要針對某兩個4x2的block間的顔色差異相對較小,因而可以使用一個更多的bit來表示一個更高精度的basecolor,而另外一個basecolor則在其基礎上通過一個bit較小的diff來進行動态計算得來。

對于所有圖檔都使用一個全局的8個組table codeword,每組中有四個數值:

1 2 3 4 5 6 7
-8 -17 -29 -42 -60 -80 -106 -183
-2 -5 -9 -13 -18 -24 -33 -47
2 5 9 13 18 24 33 47
8 17 29 42 60 80 106 183
  • 1bit:用來記錄兩個字block是采用正常的4*2編碼還是基于內插補點的編碼; 
  • 1bit:用來記錄4x4的block内兩個子block的朝向(可以兩個4*2,也可以兩個2*4)
  • 32bits:對于16個pixel,每個配置設定2bits的索引,指向到對應的modifier;
  • 6bits:對于每個子block,有一個3bits的索引,指向8個table codeword中的某一個(由原始的16組codeword縮減為8個);
  • 24bits: 分别對應兩個basecolor。對于正常編碼時,則是兩個RGB444,然後對每個擴充到RGB888;對于內插補點編碼時,則是一個RGB555(精度較高)的basecolor和一個內插補點RGB333(較低精度),先計算出先求值,然後再擴充。

ETC2:

根據ETC1的實作方式,如果其塊内的顔色分布不均勻的話,則其存儲的兩個basecolor會較遠的分布于插值趨線的較遠的兩側,進行解壓後會得到較低的壓縮品質,

幾種主流貼圖壓縮算法的實作原理1. DXTC2. ETC3. PVRTC4. ASTC

因而ETC2就是解決如何針對這些較為特殊的顔色分布來選擇更加優化的壓縮政策。

改進主要針對ETC1中的diff為1的情況下展開,即basecolor為RGB555和內插補點RGB333,此時另外一個顔色值= RGB555 + dRGB333,而其中的三個通道也是可以獨立開來計算的,比如對于紅色通道即為R = R5 + dR3,此時,若其中的R5為0且dR3為負值時得到的紅色通道值就沒有意義,此種情況下就可以對該block重新定義編碼方式。

1. 對于紅色通道的溢出情況:

  • 1bit: diff mode
  • 8bits: R5,dR3,

剩餘64-1-8 =55bits可用來存儲其它的資訊,但是注意這些其中的R5與dR3之間的溢出方式有不同的16種,而也可以将其轉換為對應的資料存儲(可以存儲4bits的資訊),因而整個資訊存儲位數為59bits.

2. 對于綠色通道的溢出情況:

  • 1bit: diff mode
  • 8bits: R5,dR3
  • 8bits: G5, dG3

剩餘64-1-8-8 =47bits可用來存儲其它的資訊,但是注意此時R通道是沒有溢出的,共有256-16種狀态,因而其可以存儲7bits的資訊,G通道是有溢出的,其與R通道的溢出相同,也有16種不同的狀态,而也可以将其轉換為對應的資料存儲(可以存儲4bits的資訊),是以通過RG兩通道的狀态可以額外存儲的資訊bits數為7+4=11bits。所有在這種情況下的資訊存儲總數量為47+11=58bits。

3. 對于藍色通道的溢出情況:

  • 1bit: diff mode
  • 8bits: R5,dR3
  • 8bits: G5, dG3
  • 8bits:B5, dB3

剩餘64-1-8-8-8=39bits可用來存儲其它的資訊。同樣對于RGB三個通道進行額外的資訊存儲之後的存儲空間為7+7+4=18bits。是以此種情況下的資訊存儲空間即為:39+18=57bits。

上述操作就巧妙地利用了三個通道中的資訊,來得到擴充的存儲空間,然後使用這些存儲空間來對圖像資訊進行編碼與壓縮即可。但注意:這些通過三個通道的溢出情況來确定對應模式,并将其中的溢出狀态也利用為對應的存儲空間,看起來比較繞,為什麼不直接使用1位之外的其它63bits進行資料存儲呢?這裡主要是因為原始的ETC1采用了三個通道這樣的存儲方式,而ETC2又必須要相容ETC1,是以隻能使用如此的方法。

接下來即需要合理利用57,58,59這三種情況下的bits存儲空間來進行原始資料的壓縮。針對顔色分布不均勻的狀态,将其細分為了三種不同的分布情況:

T字型分布,一部分顔色沿插值趨線分布,另外的顔色分布于距離較遠的位置上,這裡将顔色分為不同的兩組,每組顔色統計出其對應的basecolor0,basecolor1(對應圖中的藍色點),每個basecolor為RGB444,而對于位于右下方的basecolor0存儲一個3bits的索引值,用來索引到一個operator(共有8個),然後得到其周圍的兩上basecolor3, basecolor4,如此一來就有4個basecolor,而block中的每個pixel均索引到4個basecolor中的一個。因而共需要存儲位數為:

  • 12bits: RGB444 basecolor0
  • 12bits: RGB444 basecolor1
  • 3bits: operator
  • 32bits: 對于16個pixel,每個2bits的索引值

共計為:59bits

幾種主流貼圖壓縮算法的實作原理1. DXTC2. ETC3. PVRTC4. ASTC

H字型分布,兩部分的顔色均有不同的分布趨向,同樣的原理,統計出兩組的basecolor,然後使用operator分别對兩個basecolor擴充為兩個basecolor(注意:對T字型隻需要擴充一個),然後用4個新的basecolor來重建block中每個像素的顔色資訊。

  • 24bits: RGB444,RGB444兩個basecolor
  • 3bits: operator
  • 32bits:對于16個pixel,每個2bits的索引值
幾種主流貼圖壓縮算法的實作原理1. DXTC2. ETC3. PVRTC4. ASTC

平面分布型,其主要針對block塊内的顔色分布于4個角落上的情形,如下所示:

幾種主流貼圖壓縮算法的實作原理1. DXTC2. ETC3. PVRTC4. ASTC

這裡對應的計算模型也就比較簡單直覺,可以直接存儲C0,CH與CV三個顔色值,可将其處理為三角形(或四邊形)上的三個頂點(對應的頂點坐标為00,30,03,33),然後對block内每個pixel點上的顔色通過插值的方法得到即可,這裡每個pixel點的坐标可以使用其在block塊内的位置即可(如00,01,02,03,10,11,12,13...)。此種情況下不需要其它的資訊,所有我們可以直接把bits資訊全部用來存儲c0,ch,cv三個basecolor即可,在57bits的情況下可得到三個顔色的存儲為19,因而每個basecolorr的存儲格式為RGB676。

通過上述可以看出,ETC2對于原始圖像的分析比ETC1要更為多樣,且要相容ETC1的格式,因而對應的壓縮算法會更加複雜。ETC存儲格式是沒有處理alpha資訊,因而其不能直接應用于半透明圖像的壓縮,但是這裡也有可先的方案來在ETC的基礎上使用alpha通道:ETC Texture compression and alphachannel handling

3. PVRTC

幾種主流貼圖壓縮算法的實作原理1. DXTC2. ETC3. PVRTC4. ASTC

PVRTC的不是基于block的方式生成的,但是卻也可以了解為以block方式組織的。其生成壓縮後包含兩張(w/4,h/4)大小的縮略圖(w,h為原始圖檔的寬和高,可以了解為第4級的mipmap,但生成過程會比較mipmap的複雜),其中的每個pixel映射并對應到原始圖像中的一個64x64的block上;然後使用1張與原始圖像大小相同的modulate圖,對應的每個pixel占2個bits,也即可對應四種調制方式,通過幾種不同的調制方式還原出近似的原始像素值。

壓縮後的一個4x4的block中的bits的組成内容為:

  • 1bit:對應的融合方式,透明或不透明;
  • 32bits:對應于16個pixel,每個pixel有2bits的調制因子;
  • 31bits:對應兩個縮略圖中的該塊映射到的兩個像素上的顔色,若是透明模式,則兩個顔色為RGBA44431,RGBA34431;若是不透明模式,則兩個顔色為RGBA5551,RGBA4551;

兩種模式下的調制因子分别為:

不透明 透明
00 0/8 0/8
01 3/8 4/8
10 5/8 --
11 8/8 8/8

透明情況下的10調制因子會強制設定目前pixel的alpha為0;

通過調節上述兩張縮略圖的大小,可以相應的改變對應的壓縮比,比如由(w/4,h/4)修改為(w/8,h/4),而其它的映射方式不變,即可将壓縮比增大一倍。

4. ASTC

ASTC中ARM研發的一種較新的貼圖壓縮格式,相對于上述幾種方法具有較多的優勢,其應該會慢慢成為之後移動裝置上貼圖壓縮的主要标準和主流。其主要具有如下的特性:

  1. 較高的靈活性;
  2. 可變的壓縮率;
  3. 支援2d/3d貼圖;
  4. 适用于移動平台;
  5. 支援LDR/HDR貼圖内容;

ASTC同樣是基于block的壓縮方式,但塊的大小卻較支援多種尺寸,比如從基本的4x4到12x12,而且塊的寬高也不限于pot,比如6x5;每個塊内的内容用128bits來進行存儲,因而不同的塊就對應着不同的壓縮率。

對于每個塊,同樣存儲兩個插值端點,稱為endpoints,但是這裡的endpoints不一定是基于顔色的(RGBA),也可以基于layer,比如對于R,G,B,A甚或其中的組合如RG等,這樣的話就可以用來對normal map或alpha map進行更好的壓縮;

對于塊中的每個texel,存儲其對應于endpoints的插件weight,但是存儲的weight數量可以比texel少,特别是對于規格較大的塊(比如12x12),這種情況下會首先對于每個texel通過線性插值得到其對就應的weight,然後再進行顔色的計算;

對于塊内顔色分布較為複雜的情況,分析塊内顔色的分布,然後做partition,對于每個partition進行分别的處理(與ETC2中将顔色分布對應到具體的預知分布模式中的處理方法不同),分别存儲其對應的endpoints;這樣一來對于塊内的某個texel進行取值時就先定位其對應的partition,然後再計算在其在對應的小子塊内的顔色。

塊内資訊的存儲采用了BISE的方式來進行壓縮,盡可能的節省對應的存儲空間。比如對于一組5個表示範圍已知的整型數值,采用BISE存儲後可節省兩個bits,這樣就使用每個塊内較大量的資料存儲于128bits内成為可能;

對于單layer的一個block内的bits組織大概如下所示:

  • 11bits: 存儲weight, height, 以及特殊塊的辨別,比如void-extent等;
  • 2bits: part數量;
  • 4bits: 存儲16種不同的endpoints的模式,比如是LDR或HDR,RGB或是RGBA;
  • 111bit:其中存儲endpoints,texel weight以及其它的配置資訊,(注意,每種具體的存儲大小是可變的,因其采用BISE進行壓縮放置);

更多的細節可以看這裡

4.1 Bounded Integer sequence encoding

主要是針對範圍限定的整數序列進行壓縮存儲進而節省空間。比如對于三個數4,78,55,其直接用binary的表示為0000100,1001110,0110111,直接存儲二進制序列的話需要7bits * 3 = 21bits(在已知最大範圍為78的情況下,不需要存儲滿8bits)。但是能不能在21bits的基礎上再減少呢?BISE就是實作這樣的目的的。

假設序列的範圍為N,對應的bit位數為n:

  • 若N<= 3*2^n-2,則其可用基于5的BISE壓縮;
  • 若N<=5*2^n-3,則其可用基于3的BISE壓縮。

這裡的背後其實是基于這樣的一個事實,比如在基于3的壓縮中,如果N<=3*2^n-2,那麼在N的最高兩位bit上,其并不會出現2^2種情況的所有組合(因其大小是受限的),到少11這樣的組合就是沒有的,否則其對應的值必定大于N。是以BISE壓縮就是将受限的整數序列中的前兩位資料中的無效bits進行合理使用。比如,在上述4,78,55的序列中,78 <= 5 * 2^4 = 80,是以可以使用基于5的BISE,将三個數的二進制序列構造為{000 0100, 100 1100, 011 0111},高三位的組合為{000,100,011},因這三個3位bits序列中的最大值是5,是以每三個bits最多有5種情況,那麼這個高三位組合的序列共可能有5^3=125種組合情況,這樣的話就可以使用7bits的空間來存儲所有的這些組合,如此一來就可以将原來3*3=9bits的存儲空間存儲在7bits中,進而達到壓縮的目的。

繼續閱讀