ETC1纹理压缩原理

前言

最近看了下这方面的资料,顺便也做个整理记录,就先以用得较广泛的ETC1纹理压缩开个头,着重讲下是如何把ETC数据还原成RGB图像数据。
主要是基于这篇资料的翻译和理解,如有错漏之处,还望斧正。

介绍

Ericsson Texture Compression (ETC)是由 Khronos 支持的开放标准,在移动平台中广泛采用。它是一种为感知质量设计的有损算法,其依据是人眼对亮度改变的反应要高于色度改变。对于24位的RGB数据,提供6倍的压缩率。最大的弊端是不支持Alpha通道的存储,不过在后续的ETC2中也得到了支持。 维基百科

原理

ETC的压缩纹理以4x4的像素块为单位的方式描述出来。如果纹理在任意方向小于4个像素,那么只有位于左上角的像素块才是可用的。

    单个像素块
 ---- ---- ---- ---- 
|a   |e   |i   |m   |
|    |    |    |    |
 ---- ---- ---- ---- 
|b   |f   |j   |n   |
|    |    |    |    |
 ---- ---- ---- ---- 
|c   |g   |k   |o   |
|    |    |    |    |
 ---- ---- ---- ---- 
|d   |h   |l   |p   |
|    |    |    |    |
 ---- ---- ---- ---- 

一个4x4的像素块的数据用64bit的数据来表示。4x4的块被分成两个子块,垂直分(2x4)或者水平分(4x2),每一个子块有一组基础颜色(分别是RGB444/RGB444或RGB555/RGB333格式)、亮度索引、像素索引。
每个像素的颜色等于所属子块基础颜色加上索引指向的亮度修正。

        垂直分块

 子块 1     子块 2
 ---- ---- ---- ----
|a    e   |i    m   |
|         |         |
|         |         |
|b    f   |j    n   |
|         |         |
|         |         |
|c    g   |k    o   |
|         |         |
|         |         |
|d    h   |l    p   |
|         |         |
 ---- ---- ---- ----

        水平分块

 ---- ---- ---- ----
|a    e    i    m   |
|                   |
|                   | 子块 1
|b    f    j    n   |
|                   |
 -------------------
|c    g    k    o   |
|                   |
|                   | 子块 2
|d    h    l    p   |
|                   |
 ---- ---- ---- ----

下面讲下这64bit的数据是存放和使用的

子块基础颜色计算

2个子块的基础颜色根据32-63bit的数据而决定。ETC1里有两种模式:individual模式differential模式
这两种模式决定了子块存储的颜色是以RGB444/RGB444(individual模式)还是RGB555/RGB333(differential模式)格式存储颜色的数据,由bit 33(称为 diffbit)的值来决定,值为0时是individual模式,为1时是differential模式。

 32bit到63bit,当 diffbit = 0时的布局

 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48
 -----------------------------------------------
| base col1 | base col2 | base col1 | base col2 |
| R1 (4bits)| R2 (4bits)| G1 (4bits)| G2 (4bits)|
 -----------------------------------------------
 47 46 45 44 43 42 41 40 39 38 37 36 35 34  33  32
 ---------------------------------------------------
| base col1 | base col2 | table  | table  |diff|flip|
| B1 (4bits)| B2 (4bits)| cw 1   | cw 2   |bit |bit |
 ---------------------------------------------------

 32bit到63bit,当 diffbit = 1时的布局

 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 
 -----------------------------------------------
| base col1    | dcol 2 | base col1    | dcol 2 |
| R1' (5 bits) | dR2    | G1' (5 bits) | dG2    |
 -----------------------------------------------

 47 46 45 44 43 42 41 40 39 38 37 36 35 34  33  32 
 ---------------------------------------------------
| base col 1   | dcol 2 | table  | table  |diff|flip|
| B1' (5 bits) | dB2    | cw 1   | cw 2   |bit |bit |
 ---------------------------------------------------
  • Individual模式
    每个子块以RGB444/RGB444方式存储,将4bit颜色扩充为8bit,高4位和低4位相同
    举例:子块1存储的RGB数据是R1=14=1110b,G1=3=0011b,B1=8=1000b
    那么还原后的子块1基础RGB为R1=11101110b=238,G1=00110011b=51,B1=10001000b=136
    子块2同理

    base col subblock1 = extend_4to8bits(R1, G1, B1)
    base col subblock2 = extend_4to8bits(R2, G2, B2)

  • Differential模式
    子块1以RGB555,子块2以RGB333方式存储,子块1的颜色是以5bit的高3位作为扩充为8位之后的低3位
    举例:子块1存储的RGB数据是R1=28=11100b,G1=4=00100b,B1=3=00011b
    那么还原后的子块1基础RGB为R1=11100111b=231,G1=00100001b=33,B1=00011000b=24
    子块2计算时,先要通过和子块1存储的RGB叠加。把RGB333转为RGB555,然后再扩充为RGB888
    原有RGB333可看作是带符号位的,所以取值范围是[-4, 3]
    举例:和上面一样有R1’=28,的dR2=100b=-4,R1’+dR2=24=11000b,转成8bit则为,R2=11000110=198,G2B2同理

    base col subblock1 = extend_5to8bits(R1’, G1’, B1’)
    base col subblock2 = extend_5to8bits(R1’+dR2, G1’+dG2, B1’+dG2)

分块方式

分块方式根据bit 32来决定(称为flipbit),flipbit=0为垂直分(2x4),flipbit=1为水平分(4x2)。

像素RGB的最终确定

通过上面的步骤可以得出两个分块的基础颜色,然后需要确定每个像素的修正值,和基础颜色进行叠加,最后限定在[0, 255]内。

  • 亮度修正表
    亮度修正表定义了8组修正的值(固定不变的),每组包含4个值,具体的像素采用哪个修正值还需要通过修正结果映射表(下面会说到)来决定。
    继续引用上面表格,37bit到39bit这3bit存储的是子块1的亮度修正表索引,34bit到36bit是存了子块2的亮度修正表索引。
    举例:37bit到39bit的值为010b=2,则得到修正值为{-17,-5,5,17}
codewordsmodifier value1modifier value2modifier value3modifier value4
0-8-228
1-17-5517
2-29-9929
3-42-131342
4-60-181860
5-80-242480
6-106-3333106
7-183-4747183
  • 修正结果映射表
    0bit到31bit之间是记录4x4个像素采用的索引值,每个像素由2bit(msb和lsb)决定。
    0-15bit之间的值为lsb(least significant bit),16-31bit之间的值为msb(most significant bit),第一个像素对应0bit和16bit,第二个像素对应1bit和17bit…如此类推。
    msb和lsb可以称为像素下标位。
    上面已经根据亮度索引从亮度修正表里面得出了四个值,现在可以通过得到的msb和lsb,在修正结果映射表里面得到一个最终的修正值。
msblsb最后的修正值
11modifier value1
10modifier value2
00modifier value3
01modifier value4
  • 最终结果计算举例
    算出像素所在子块的基础色为(231, 8, 16),亮度修正索引为010b=2,对应值为{-29, -9, 9, 29},像素下标位为01b=1,所以取得修正值为29,叠加后得到(260, 37, 45),修正在[0, 255],所以最终结果是(255, 37, 45)

小计:

任何图片的压缩都会造成像素和原始像素的差异,只是人眼对色差分辨不出来。

参考链接:

https://www.jianshu.com/p/f3491b81f707

http://kc123kc.github.io/2016/03/20/ETC1-Introduce/

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值