3、JPG格式详解:有损压缩的取舍之道
JPG,或者说JPEG,应该是我们日常接触最多的图片格式了。手机拍的照片、网上下载的素材,十有八九都是JPG。但在嵌入式GUI里,JPG却是个让人又爱又恨的角色。爱的是它能把一张几兆的照片压到几百K,恨的是——它是有损的。
说白了,JPG用“丢掉一部分人眼不敏感的信息”来换取体积的缩小。这个思路很聪明,但代价就是画质不可逆地下降。我在项目里见过不少新手,上来就把所有图片都转成JPG,结果在屏幕上显示时,文字边缘全是鬼影,渐变背景也出现了明显的色块断层。嗯,今天我们就来把JPG的底裤扒干净。
3.1 JPG有损压缩的核心原理
JPG的压缩流程,我习惯把它拆成四步走:
- 颜色空间转换:把RGB转成YCbCr。Y是亮度,Cb和Cr是色度。人眼对亮度敏感,对色度不敏感,所以这一步是为后面的“偷懒”做准备。
- 下采样:对色度通道进行缩小。常见的是4:2:0,也就是每4个像素共享一组色度信息。你想想看,色度信息直接砍掉75%,体积能不降吗?
- DCT变换 + 量化:把图像块从空间域变换到频率域,然后用量化表去“舍掉”高频细节。这是JPG有损的核心——量化表里的数值越大,丢掉的信息越多,文件越小,画质越差。
- 熵编码:用哈夫曼编码对量化后的数据进行无损压缩,这一步不丢信息。
我在项目中调试过一块主频只有200MHz的MCU,解码一张800×480的JPG背景图,耗时接近300ms。后来发现是量化表太复杂,解码器需要做大量反量化运算。所以你看,JPG的压缩率不仅影响画质,还直接影响解码性能。
核心结论:JPG的有损压缩,本质上是“用高频细节换体积”。你丢掉的信息,永远回不来了。
3.2 质量因子:一个数字,两种命运
质量因子(Quality Factor,QF)是JPG压缩时最直接的参数。范围通常是1到100,数值越大,画质越好,文件也越大。但这里有个坑——不是线性关系。
我做过一组测试,用同一张照片在不同QF下导出,结果如下:
| 质量因子 | 文件大小(KB) | 主观画质 | 适用场景 |
|---|---|---|---|
| 95-100 | 原始大小的60-80% | 几乎无损 | 照片存档、印刷级素材 |
| 80-90 | 原始大小的20-40% | 肉眼难以察觉差异 | TouchGFX中的照片背景 |
| 60-75 | 原始大小的10-20% | 轻微可见压缩痕迹 | 渐变背景、非关键区域 |
| 30-50 | 原始大小的5-10% | 明显块效应和伪影 | 不推荐在GUI中使用 |
我的个人习惯:在TouchGFX项目中,照片类素材用QF=85,渐变背景用QF=70。既能控制体积,又不会在屏幕上露馅。你可以先导出一张QF=85的图,如果文件还是太大,再降到80试试。每次降5,别贪心。
3.3 JPG在TouchGFX中的适用场景
TouchGFX支持JPG解码,但并不是所有场景都适合用JPG。我根据项目经验,把常见场景分成了三类:
3.3.1 照片类素材:JPG的主场
照片的特点是色彩丰富、细节多、没有硬边缘。JPG的有损压缩对这类图像影响最小。我在一个智能家居项目中,用JPG存储了十几张室内场景照片作为背景切换,每张图从原来的2MB压到300KB左右,解码时间控制在100ms以内,效果很理想。
- 推荐质量因子:80-90
- 注意事项:避免在照片上叠加高精度文字,否则文字边缘会出现JPG伪影
- 解码性能:取决于MCU算力,建议在目标硬件上实测
3.3.2 渐变背景:小心色块断层
渐变背景是JPG的软肋。因为JPG的量化过程会把平滑过渡的区域“切”成一块一块的,导致肉眼可见的色块断层。我曾经在一个车载项目中,用QF=60的JPG做仪表盘背景渐变,结果客户一眼就看出了条纹,最后不得不换成PNG。
避坑指南:如果你非要用JPG做渐变背景,请记住三点:
- 质量因子不要低于70
- 渐变范围尽量宽,避免窄带渐变
- 在屏幕上实际预览,不要在电脑上看——电脑屏幕和嵌入式屏幕的显示效果差异很大
3.3.3 文字和图标:绝对不要用JPG
这个我强调过很多次了。JPG的有损压缩对文字和图标是灾难性的。文字边缘会出现振铃效应,图标里的纯色区域会变成一团模糊。我在项目中见过有人把按钮图标存成JPG,结果按钮上的字完全看不清。嗯,这种问题排查起来特别浪费时间。
- 文字:必须用PNG或直接使用字体渲染
- 图标:推荐SVG或PNG,JPG绝对不行
- 线框图:同样不适合JPG,边缘会模糊
3.4 实战建议:什么时候选JPG?
我总结了一个简单的判断逻辑,你在选格式时可以对照一下:
| 条件 | 推荐格式 | 理由 |
|---|---|---|
| 全屏照片背景 | JPG (QF=85) | 体积小,画质可接受 |
| 渐变背景(宽渐变) | JPG (QF=75) 或 PNG | JPG体积小,但需测试色块 |
| 渐变背景(窄渐变) | PNG | JPG必出断层 |
| 产品展示图 | JPG (QF=90) | 保留细节,体积可控 |
| 按钮/图标/文字 | PNG 或 SVG | JPG有损不可接受 |
最后说一句,JPG不是万能的,但用对了地方,它能让你的固件体积大幅下降。我个人建议,在项目初期就把所有图片的格式和质量因子定好,不要等到集成阶段再改——那时候改一张图,可能意味着要重新测试整个UI的显示效果,很折腾。