3、图像资源压缩:L8、A4、RLE格式选择与PNG/JPEG预处理
图像资源,往往是TouchGFX项目里内存占用的头号大户。我见过不少项目,UI逻辑写得挺漂亮,结果一编译,Flash超了,RAM也爆了。查来查去,罪魁祸首就是几张没处理过的PNG。
这一章,咱们就专门聊聊怎么给图像资源“瘦身”。说白了,就是选对格式、做对预处理。你想想看,一张图如果能从RGBA8888压缩到L8,内存直接省掉75%。这买卖,划算。
3.1 理解TouchGFX的像素格式家族
TouchGFX支持好几种像素格式。但真正能帮你省内存的,其实就那几种。我习惯把它们分成两类:“真彩色系”和“索引/压缩系”。
| 格式 | 位深 | 适用场景 | 内存占用(相对RGBA8888) |
|---|---|---|---|
| RGBA8888 | 32位 | 照片、高精度渐变、半透明特效 | 100% |
| RGB565 | 16位 | 无透明通道的普通界面元素 | 50% |
| L8 | 8位 | 图标、单色背景、颜色数≤256的图像 | 25% |
| A4 | 4位 | 仅需透明通道的遮罩、阴影 | 12.5% |
| RLE | 可变 | 大面积纯色块、简单几何图形 | 取决于内容,通常极低 |
核心原则:能用L8,就别用RGB565。能用A4,就别用L8。能用RLE,就别用原始格式。每降低一位,省的可都是真金白银的Flash和RAM。
3.2 L8格式:索引色的威力
L8,全称是8位索引色。它不直接存每个像素的颜色值,而是存一个“调色板索引”。图像里最多256种颜色,每种颜色在调色板里占4字节(RGBA8888)。
举个例子。一张32x32的图标,如果用RGBA8888,大小是32x32x4=4096字节。转成L8后,图像数据只有32x32x1=1024字节,再加上调色板256x4=1024字节。总共2048字节。省了一半。
什么时候用L8?
- 图标、按钮、小控件
- 颜色数少于256的插图
- 不需要平滑渐变的背景
我的经验:在项目中,我习惯把所有图标都先转成L8试试。如果视觉上没明显差异,就直接用。有一次,一个包含200多个图标的项目,光这一步就省了将近300KB的Flash。嗯,这300KB后来全用来放中文字库了。
3.3 A4格式:透明通道的极致压缩
A4格式很有意思。它只存透明通道,不存颜色信息。每个像素用4位表示透明度,也就是16级透明度。
你可能会问:“只有透明,没有颜色,那显示出来是什么?”答案是:它通常作为遮罩或阴影使用。比如一个按钮的阴影,只需要知道哪里透明、哪里半透明、哪里不透明。颜色?让上层图层的颜色透过来就行。
什么时候用A4?
- 投影、发光、模糊边缘
- 不规则形状的遮罩
- 任何只需要透明信息的图像
避坑指南:我曾经在一个项目里,把一张带渐变色的背景图强行转成了A4。结果显示出来一片灰蒙蒙,因为A4不存颜色信息。记住,A4只存透明,不存颜色。颜色信息得靠其他图层提供。
3.4 RLE格式:游程编码的妙用
RLE,Run-Length Encoding,游程编码。它的原理很简单:把连续的相同颜色像素压缩成一个“长度+颜色值”对。
比如一行像素:红红红红红蓝蓝蓝绿绿。RLE编码后变成:5红 3蓝 2绿。如果图像里大块大块都是纯色,压缩率会非常惊人。
什么时候用RLE?
- 大面积纯色背景
- 简单的几何图形(矩形、圆角矩形)
- 文字轮廓(如果文字颜色单一)
注意:RLE的解码需要额外CPU开销。如果图像内容很“碎”(比如照片),RLE反而可能比原始格式还大。所以,RLE只适合内容简单的图像。
3.5 PNG/JPEG预处理:从源头控制
很多人直接把设计师给的PNG扔进TouchGFX Designer。这是个大坑。设计师给的PNG,往往是32位带Alpha通道的,尺寸也可能是2倍甚至3倍的分辨率。
预处理步骤:
- 降位深:如果不需要透明,果断转成RGB565或L8。如果需要透明,评估能否用A4。
- 缩分辨率:确认UI设计的分辨率。如果屏幕是480x272,设计师给了960x544的图,直接缩到一半。别犹豫。
- 去冗余Alpha:很多PNG的Alpha通道是全白的(完全不透明)。这种情况下,可以去掉Alpha通道,转成RGB565。
- 量化颜色:对于L8格式,用工具(如pngquant)把颜色数降到256色以内。调色板优化得好,视觉损失几乎看不出来。
我的习惯:我会在项目里建一个“预处理脚本”。每次设计师更新资源,我跑一遍脚本,自动完成降位深、缩分辨率、量化颜色。省时省力,还不会漏掉哪张图。
3.6 格式选择决策流程
说了这么多,到底怎么选?我画了一张流程图,帮你快速决策。
3.7 实战:用ImageMagick做批量预处理
说了这么多理论,来点实际的。我常用ImageMagick做批量预处理。下面这个脚本,能一键把目录下所有PNG转成最适合的格式。
#!/bin/bash
# 批量图像预处理脚本
# 用法:./preprocess_images.sh input_dir output_dir
INPUT_DIR=$1
OUTPUT_DIR=$2
mkdir -p $OUTPUT_DIR
for file in $INPUT_DIR/*.png; do
filename=$(basename "$file")
name="${filename%.*}"
# 1. 缩放到目标分辨率(假设屏幕是480x272)
convert "$file" -resize 480x272\> "$OUTPUT_DIR/${name}_resized.png"
# 2. 检查颜色数,决定是否转L8
colors=$(identify -format "%k" "$OUTPUT_DIR/${name}_resized.png")
if [ $colors -le 256 ]; then
# 转L8
convert "$OUTPUT_DIR/${name}_resized.png" -colors 256 "$OUTPUT_DIR/${name}_L8.png"
echo "$filename: 转L8成功"
else
# 转RGB565
convert "$OUTPUT_DIR/${name}_resized.png" -depth 16 "$OUTPUT_DIR/${name}_RGB565.png"
echo "$filename: 颜色数过多,转RGB565"
fi
done
小技巧:你可以把这个脚本集成到CI/CD流程里。每次设计师提交新资源,自动触发预处理。这样,开发人员永远拿到的是“瘦身版”资源,不会有人手滑把大图塞进去。
3.8 总结:省内存,从选对格式开始
图像资源压缩,说白了就是“用最少的位数,表达最多的信息”。L8、A4、RLE,各有各的适用场景。选对了,内存占用直接砍半甚至更多。选错了,不仅没省,还可能影响显示效果。
我个人习惯,在项目初期就定好图像资源规范。哪些用L8,哪些用A4,哪些用RLE,写清楚。然后配合预处理脚本,自动化执行。这样,整个团队都能受益。
嗯,这一章就到这里。记住,下一张图放进去之前,先问问自己:“它真的需要32位吗?”