3、JPG格式详解:有损压缩的取舍之道

JPG,或者说JPEG,应该是我们日常接触最多的图片格式了。手机拍的照片、网上下载的素材,十有八九都是JPG。但在嵌入式GUI里,JPG却是个让人又爱又恨的角色。爱的是它能把一张几兆的照片压到几百K,恨的是——它是有损的。

说白了,JPG用“丢掉一部分人眼不敏感的信息”来换取体积的缩小。这个思路很聪明,但代价就是画质不可逆地下降。我在项目里见过不少新手,上来就把所有图片都转成JPG,结果在屏幕上显示时,文字边缘全是鬼影,渐变背景也出现了明显的色块断层。嗯,今天我们就来把JPG的底裤扒干净。

3.1 JPG有损压缩的核心原理

JPG的压缩流程,我习惯把它拆成四步走:

  1. 颜色空间转换:把RGB转成YCbCr。Y是亮度,Cb和Cr是色度。人眼对亮度敏感,对色度不敏感,所以这一步是为后面的“偷懒”做准备。
  2. 下采样:对色度通道进行缩小。常见的是4:2:0,也就是每4个像素共享一组色度信息。你想想看,色度信息直接砍掉75%,体积能不降吗?
  3. DCT变换 + 量化:把图像块从空间域变换到频率域,然后用量化表去“舍掉”高频细节。这是JPG有损的核心——量化表里的数值越大,丢掉的信息越多,文件越小,画质越差。
  4. 熵编码:用哈夫曼编码对量化后的数据进行无损压缩,这一步不丢信息。

我在项目中调试过一块主频只有200MHz的MCU,解码一张800×480的JPG背景图,耗时接近300ms。后来发现是量化表太复杂,解码器需要做大量反量化运算。所以你看,JPG的压缩率不仅影响画质,还直接影响解码性能。

核心结论:JPG的有损压缩,本质上是“用高频细节换体积”。你丢掉的信息,永远回不来了。

JPG有损压缩流程 RGB → YCbCr 色度下采样 DCT + 量化 熵编码 关键说明: • 颜色空间转换:利用人眼对亮度敏感、对色度不敏感的特性 • 色度下采样:4:2:0 格式下,色度信息减少 75% • DCT + 量化:量化表数值越大,高频细节丢失越多,文件越小

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的显示效果,很折腾。