Files
obsidian-notes/3Resources/游戏开发/性能优化/压缩/ASTC图片压缩.md
2025-07-19 16:40:04 +08:00

55 lines
7.3 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
参考链接: "[ASTC图片压缩技术浅析 - 知乎](https://zhuanlan.zhihu.com/p/1898042738022285491)"
参考链接2: "[深入理解ASTC](https://zhuanlan.zhihu.com/p/707250800)"
---
# 浅析
### ASTC是什么
有了上面的简单说明铺垫接下来正式介绍一下ASTC是什么
ASTC[Adaptive Scalable Texture Compression](https://zhida.zhihu.com/search?content_id=256803808&content_type=Article&match_order=1&q=Adaptive+Scalable+Texture+Compression&zhida_source=entity))是一种高级纹理压缩技术,由 ARM 和 AMD共同开发。其设计目标是提供更高效的压缩率和更高的图像质量并且支持多种块尺寸和位深度。
ASTC的核心优势在于其可变块大小系统支持从4x4到12x12的任意大小块包括非正方形块以及3D纹理的压缩和广泛的硬件支持。这种技术能够适应不同的纹理特征和压缩率需求从而在保持图像质量的同时显著减少纹理数据的大小。
### 常规的压缩方法
- **减少颜色数量**图片是由许多像素组成的每个像素都有一个颜色值。常规压缩技术会减少颜色的数量比如把256种颜色减少到16种然后用这16种颜色来近似原来的颜色。这样存储颜色信息的数据量就减少了。根据权重算出Block里主要颜色相似的颜色用这个主要颜色来储存达到减少颜色的目的。
- **去除冗余信息**:图片中往往有很多重复的内容,比如一片蓝色的天空。压缩技术会识别这些重复的部分,只存储一次,然后在需要的地方引用它,这样也能减少数据量。
### ASTC核心思想
- **根据不同区域的特点,灵活地选择压缩方式**
- **分块处理**ASTC把图片分成很多小块每个小块独立处理。就像把大画分成很多小区域一样每个小块可以根据自己的内容选择合适的压缩方式。
- **自适应性**对于简单的内容比如一片纯色的天空ASTC可以用很少的颜色来表示对于复杂的内容比如人物的面部细节ASTC会用更多的颜色来保持细节。这种自适应性使得ASTC在保持较高图像质量的同时还能实现较高的压缩率。
### ASTC压缩算法工作原理
- 将这张大图切成很多小块。
- ASTC允许我们选择块的大小比如选择块的大小为4x4那么512x512的大图就会被切成512x5124x4=16384块。再比如选择块的大小为8x8512x512的大图就会被切成4096块。
- 这里要注意一个点,**ASTC中无论每个块覆盖的像素数量是多少大小都固定为128比特16字节**。
- 选择颜色
- 对于已经切割好的每个矩形块ASTC算法会智能地选择两个颜色端点来定义这个矩形块里的颜色范围比如一块天空的颜色主要是浅蓝到深蓝那么两个端点就是浅蓝色和深蓝色有时候矩形块里的颜色比较多样ASTC算法就会使用更多的颜色端点来代表整个方块的颜色范围。
- 颜色渐变
- 在选择了颜色端点后ASTC算法会通过插值计算每个像素的颜色。值插值方法通常是线性的即根据像素在块内的位置计算其颜色值在两个端点之间的比例。例如靠近浅蓝色端点的像素会更接近浅蓝色而靠近深蓝色端点的像素会更接近深蓝色。
- 对于包含许多颜色的块ASTC则会使用多维插值的方法。例如如果一个块中有红色、绿色和蓝色的渐变ASTC会分别在红、绿、蓝三个颜色通道上进行插值以生成更自然的颜色过渡。
- 存储信息
- 对于每一个矩形块,记录下它的颜色端点,插值权重以及其他的辅助信息。
- 在存储时,还会采用更高效的编码方式来存储这些信息。例如,颜色端点可以使用较少的位数来表示,而插值权重则根据块内颜色的复杂度动态分配位数。这种编码方式确保了数据量的最小化,同时尽可能保留图像的视觉质量。
- 除了颜色端点和插值权重ASTC还会存储一些索引信息用于快速定位每个像素的颜色值。这些索引信息通常以紧凑的格式存储进一步减少了数据量。
- BISEBounded Integer Sequence Encoding
- 这个是ASTC压缩算法里面一个很核心的算法它的基本原理就是用一串一定范围内数值大的数来表示一串固定数量的数值小的数Color Endpoint和weight的数据都是用这种方式编码的。
- 这里首先抛开ASTC先把BISE说清楚。举例来说会更清楚:
- 比如现在有三个数字需要编码{405070}一般情况下我们可能想到的使用二进制来编码这三个值这三个值在128以内所以可以每个数用7bit来编码那么也就是需要21bit位。那这里我们可以用BISE来减少编码的位数以此来压缩数据量。BISE会把数分为高位和地位高位使用Trits三进制或者Quints五进制来表示多少值范围内的数如何分割表示是有个最佳实践的这里可以查表来确定为了简单这里直接给出例子中的结论它们是在80查找表中的固定值以内的数字所以使用4bit的Bits表示低位高位用Quints来表示。那它们的低位就是{1010001100101000110},这个直接编码就可以了,高位的值为{234}然后把这三个值拼到一个大数值上因为高位用Quints表示的三位的Quints就能表示1255*5*5以内的数字我们可以用7bit128来表示这样原本要243\*8bit的三个数字就用了4\*3 + 7 = 19bit来表示了。
- 解压缩
- 当需要在屏幕上显示这张画布时,解压缩算法会读取每个块的压缩数据,恢复颜色端点和插值权重。然后,根据这些信息,通过插值计算每个像素的颜色值,从而重建出原始图像。
- 这里需要了解ASTC的一个重要特点**硬件加速**。现代GPU通常内置了对ASTC解压缩的支持能够快速高效地解压缩图像数据从而在不显著增加计算负担的情况下实现高质量的图像显示。
### ASTC压缩使用建议
目前使用人数比较多的工具是 Arm ASTC Encoderastcenc
可以从这里获取 [https://github.com/ARM-software/astc-encoder.git](https://link.zhihu.com/?target=https%3A//github.com/ARM-software/astc-encoder.git)
其主要的特点有支持BMP、JPEG、PNG、TGA等多种图像格式提供多种质量预设开源
在使用ASTC技术时需要合理选择块大小和平衡视觉质量以下是一些建议
- 一般情况的合适的块大小
- 4×4块适用于颜色变化复杂或细节丰富的区域如**法线贴图**或**高精度纹理**。这种块大小可以提供较高的图像质量,但压缩率较低。
- 5×5或6×6块**适合一般的纹理,很多手游都用这个**,能够在质量和压缩率之间取得较好的平衡。
- 8×8、10×10、12×12块适用于尺寸较大但细节要求不高的纹理如**背景图或大面积的填充纹理**。这些块大小可以显著提高压缩率,但可能会牺牲一些图像质量。
- 考虑纹理类型
- 法线贴图建议使用4×4或5×5的块大小以避免丢失过多细节。
- 带Alpha通道的贴图推荐使用5×5的块大小。
- 无Alpha通道的贴图可以选择8×8的块大小。