文章目录
前段时间做了个 ESP32-S3 串流小电视(见 桌面小电视新思路,ESP32-S3 + 12864 OLED 串流视频)的项目,最近准备试试显示彩色图片,这就需要持续显示 JPEG 图片来模拟视频播放。
在 Arduino 生态中找到了好几个解码库,虽然也有一些对比测试,还是想自己实测一下,看看具体的效果怎么样 😃。
起因
在串流进行视频播放时,需要视频的每一帧解码、上屏,如果需要达到 30 FPS 的刷新率,那么解码 + 上屏的时间要在 1000 / 30 = 33.333 ms 以内。在这种情况下,图片解码性能直接影响用户体验。
另外,ESP32-S3 有双核 + 更高主频 + PSRAM + SIMD 指令支持,理论上应该可以跑得更快,但是具体能快多少,不同库之间差距多大,都需要实测数据。
测试环境
硬件平台
- 开发板: ESP32-S3-Zero 开发板
- PSRAM: 2MB PSRAM
- CPU 频率: 240MHz (双核)
- Flash: 4MB
- Arduino 版本: PlatformIO Espressif 32 (55.3.34)
测试样本
测试图片使用了经典的计算机图像处理测试图片 Lenna(见 https://en.wikipedia.org/wiki/Lenna)。
不同尺寸使用 ImageMagick 缩放、裁切,并使用 80% 质量导出为 JPEG 图片。

JPEG 图片测试样本:
- 160x80 像素,质量 80,文件大小约 4KB
- 240x240 像素,质量 80,文件大小约 12KB
- 320x240 像素,质量 80,文件大小约 49KB
测试视频
解码库介绍
JPEGDEC
项目地址: https://github.com/bitbank2/JPEGDEC
bitbank2 大佬的作品,支持 JPEG、Progressive JPEG,代码精简,专门为嵌入式优化。Arduino Library Manager 可以直接安装,并且新版本也支持了 SIMD 指令。
特点:
- 代码体积小
- 支持部分解码
- 可以直接输出到 LCD
TJpg_Decoder
项目地址: https://github.com/Bodmer/TJpg_Decoder
基于 TinyJPEG 的 Arduino 封装库,Bodmer 大佬维护,和 TFT_eSPI 配合使用非常方便。
特点:
- 集成度高
- 和 TFT_eSPI 无缝配合
- 支持缩放输出
- 纯软件解码
ESP32_NEW_JPEG
项目地址: https://github.com/espressif/esp-adf-libs/tree/master/esp_new_jpeg
乐鑫官方提供的 JPEG 硬件加速库,理论上也是使用 SIMD 指令加速,仅提供 lib 库使用,不开放源代码。
特点:
- 硬件加速
- 理论性能最强
- 功耗更低
乐鑫官方在 2025 年 9 月才宣布这个库,也是相当新了,文章见 https://developer.espressif.com/blog/2025/09/esp-new-jpeg-introduction/ 。
另外有个问题,ESP32_NEW_JPEG 只支持 Baseline JPEG,不支持 Progressive JPEG,如果遇到 Progressive JPEG 会解码失败。
JPEG 解码性能测试
测试代码
测试方法很简单,测试图片直接生成 C 头文件,编译到固件中,然后在固件中每个尺寸的每个图片,均解码 10 次并上屏,记录平均耗时。
static bool DecodeWithJpegdec(const uint8_t *data, size_t len) {
BeginRunMetrics();
// Image arrays are stored in flash (.rodata) on ESP32, so use openFLASH().
int rc = gJpegDec.openFLASH(data, static_cast<int>(len), JpegdecOutput);
if (rc == 0) {
EndRunMetrics();
return false;
}
gJpegDec.setPixelType(RGB565_LITTLE_ENDIAN);
rc = gJpegDec.decode(0, 0, 0);
gJpegDec.close();
EndRunMetrics();
return rc != 0;
}
static bool DecodeWithTjpg(const uint8_t *data, size_t len) {
BeginRunMetrics();
TJpgDec.setSwapBytes(false);
TJpgDec.setCallback(TjpgOutput);
const bool ok = TJpgDec.drawJpg(0, 0, data, static_cast<uint32_t>(len)) == JDR_OK;
EndRunMetrics();
return ok;
}
其他库的测试代码类似,主要是调整 API 调用方式。
测试结果
160x80 JPEG 解码速度
| Library | Decode(ms) | Draw(ms) | Total(ms) | FPS |
|---|---|---|---|---|
| JPEGDEC | 6.79 | 7.67 | 14.46 | 69.2 |
| Tjpg_Decoder | 10.54 | 8.63 | 19.16 | 52.2 |
| ESP32_NEW_JPEG | 3.89 | 7.51 | 11.40 | 87.7 |
240x240 JPEG 解码速度
| Library | Decode(ms) | Draw(ms) | Total(ms) | FPS |
|---|---|---|---|---|
| JPEGDEC | 26.64 | 33.98 | 60.62 | 16.5 |
| Tjpg_Decoder | 43.05 | 38.67 | 81.72 | 12.2 |
| ESP32_NEW_JPEG | 26.08 | 34.87 | 60.95 | 16.4 |
320x240 JPEG 解码速度
| Library | Decode(ms) | Draw(ms) | Total(ms) | FPS |
|---|---|---|---|---|
| JPEGDEC | 34.89 | 45.37 | 80.26 | 12.5 |
| Tjpg_Decoder | 56.53 | 51.54 | 108.07 | 9.3 |
| ESP32_NEW_JPEG | 34.48 | 46.46 | 80.95 | 12.4 |
可以看到,ESP32_NEW_JPEG 硬件加速真的强,在低分辨率下比软件解码快了 2 倍多。
但是 JPEGDEC 新版本在使用了 SIMD 之后,性能也很强劲,甚至在 320x240 分辨率下领先 ESP32_NEW_JPEG 一点点,当然这也有可能是测试误差 😃。
内存占用对比
除了速度,内存占用也很重要,特别是对于复杂项目。
注意:这里只是简单的统计了堆内存和栈大小的变化,并不是很严谨,仅供参考。
| Size | Library | HeapDelta(B) | StackDelta(B) |
|---|---|---|---|
| 160x80 | JPEGDEC | 0 | 1271 |
| 160x80 | Tjpg_Decoder | 0 | 1189 |
| 160x80 | ESP32_NEW_JPEG | 38024 | 1006 |
| 240x240 | JPEGDEC | 0 | 1272 |
| 240x240 | Tjpg_Decoder | 0 | 1241 |
| 240x240 | ESP32_NEW_JPEG | 128648 | 989 |
| 320x240_B | JPEGDEC | 0 | 1265 |
| 320x240_B | Tjpg_Decoder | 0 | 1252 |
| 320x240_B | ESP32_NEW_JPEG | 167560 | 987 |
可以看到只有 ESP32_NEW_JPEG 使用到了堆内存,而另外两个库直接通过栈内存解码。
另外不管图片大小,几个库在栈内存使用上都差不多。
注:ESP32_NEW_JPEG 还有 block 方式解码,这里没有使用,内存使用情况可以会有所不同。
小结
经过一番测试,得出以下结论:
JPEG 解码选择指南:
| 场景 | 推荐库 | 理由 |
|---|---|---|
| 追求性能 | JPEGDEC 或 ESP32_NEW_JPEG | 硬件加速,速度快 |
| 节省内存 | JPEGDEC | 内存占用小,速度也不错 |
| 需要 Progressive JPEG | JPEGDEC | ESP32-JPEG 不支持 |
| 配合 TFT_eSPI | TJpg_Decoder | 集成度高,使用方便 |
在完成测试之前,以为 ESP32_NEW_JPEG 会有绝对优势领先,毕竟官方理论上可以发挥 ESP32-S3 的全部性能。
但是在测试完成后发现 JPEGDEC 在有 SIMD 指令加持下之后,性能也相当不错。
核心建议:
- 优先使用 ESP32-JPEG - 如果内存上不太紧张,并且图片都是 Baseline JPEG,可以优先选择 ESP32-JPEG,毕竟官方库。
- JPEGDEC 作为备选 - 内存比较紧张,或者需要兼容 Progressive JPEG 时使用。
顺便再提一句,ESP32 系列中,只有 ESP32-S3 以及 ESP32-P4 才支持 SIMD 指令,因此如果是使用 ESP32-S3 以外的芯片,可能测试结果会有所不同。
再再提一下,这些数据都是我自己测的,在不同的图片质量、编码方式、测试代码上性能可能会有差异,仅供参考 😃。

0 条评论。