你好,我是吴老师。这份是给你自己读的——不用等我讲,看不懂就整段复制给 AI,加一句"请一次只解释一个概念,讲完问我一个小问题"。
读完之后,你应该能:
- 说出"JPG 为什么小、显示前为什么要解码";
- 说清"一张 JPG 从 TF 卡到屏幕"经过哪几步;
- 记住两个代码名:
getFsJpgSize量宽高、drawFsJpg解码画图。用时:约 60 分钟。 准备:烧录
demo01_sd_picture的板子 + 一根 USB 线 + 一张装了图片的 TF 卡。
一、让板子当一本绘本
第 38 课板子会放歌,这一课换种玩法——让板子当一本电子绘本。音乐是一段时间轴上的声音,绘本是一页页静止的画面。
可板子没有"纸",它怎么把一张张图片"摆"到屏幕上、一页页翻?答案:存进 TF 卡,读出来、解码、画到屏幕。
先看现象:烧录后,TF 卡里的 4 张 JPG 在屏幕上一张接一张出现,每张停约 1.5 秒,放完又从头来。
二、我观察到的现象
| 现象 | 勾选 |
|---|---|
| 上电后屏幕先出现一张彩色图片 | |
| 过一会儿自动换成下一张(约 1.5 秒) | |
| 一共 4 张,放完又从第一张开始 | |
| 板子没联网也能显示 | |
| 图片是缩放到屏幕大小,不是被裁掉一半 |
三、一张图怎么从 TF 卡到屏幕?
它不是"现画"在内存里的,是从 TF 卡这个"书柜"里读出来、再"还原"到屏幕的:
| 环节 | 谁在干 |
|---|---|
| 存图片 | TF 卡(把 JPG 文件存起来) |
| 读文件 | TF 卡控制器(SD_MMC,6 线引脚) |
| 解 码 | TJpgDec 解码库(把压缩 JPG 还原成像素) |
| 画 屏 | TFT 屏幕(把一块块像素推上去) |
四、JPG 为什么要"解码"?
一张大图要寄出去,直接寄又大又容易折;聪明的做法是压缩成小文件寄过去,到了再还原成能看的图。
- 存进 TF 卡的是"小文件"——JPG(小);
- 显示前的解码,就是"还原"——把压缩的图还原成一格格像素;
- 还原的像素再送到屏幕显示。
⚠️ 比喻要有边界:压缩/还原是说 JPG 用小体积存图片、显示前要解码,不是说图片能 100% 还原。JPG 丢的是人眼不敏感的细节,所以叫"有损压缩"。
一句话:JPG 小,是因为先被压缩过;能显示,是因为板子会解码还原。
五、两个代码名,够了
TJpgDec 是"解码师傅",你把 TF 卡里一张 JPG 交给它,它边解码边把像素送到屏幕。你只要认识它两个动作:
1. TJpgDec.getFsJpgSize(&w, &h, "/tulip.jpg", SD_MMC)——量宽高
get Fs Jpg Size:拿 TF 卡里某路径的 JPG,量出宽(w)和高(h),填进 w、h。
为什么先量尺寸?因为图可能比屏幕大,量出宽高才知道要不要缩放,让整张图放得进屏幕。
2. TJpgDec.drawFsJpg(0, 0, "/tulip.jpg", SD_MMC)——解码画图
draw Fs Jpg:从 TF 卡读这张 JPG,解码,从角(0,0)开始一格格画到屏幕。
画图前还得做两件事:setCallback(tft_output)(告诉解码库"解出的每一小块像素请送到屏幕"),和 setJpgScale(1)(缩放倍数,只能取 1/2/4/8)。解码库每解出一块,就调一次回调 tft_output,用 tft.pushImage(...) 把这一块推到屏幕——像拼图一样拼出整张图。
最该记住的:先 getFsJpgSize 量宽高,再 drawFsJpg 画整张图。 口诀:量一量,画一画,JPG 从 TF 卡变屏幕。
六、想翻页?加上触摸就行
demo01 是自动轮播(1.5 秒一换),已经是一本"自动放映"的绘本。真正的绘本是你想翻哪页就翻哪页——把第 8 课学会的触摸加进来:
手指往左滑 → 下一页;往右滑 → 上一页;
翻到最后一页再滑 → 回到第一页(或显示 THE END)。
追问:为什么断网还能看图? 因为图片不是从网上"下载"的,是从 TF 卡这个本地书柜里读出来的。只要图在 TF 卡里,板子随时能读、随时能翻,跟 WiFi 无关——内容本地化,离线也能看。
七、改一个条件:把图放大或缩小
思想实验:如果这张图比屏幕还大,不改文件名,只改一个数字,怎么让整张图"缩"进屏幕?
| 我改了什么 | 我预测 | 实际 |
|---|---|---|
setJpgScale(1) 改 setJpgScale(2) | 图变小一半,正好放得进屏幕;倍数只能 1/2/4/8 | |
| 图太大,只显示一半 | 用 getFsJpgSize 量宽高,再按宽高选 setJpgScale |
图片缩放不是改文件名,而是改 setJpgScale 一个数字——缩放后图变小、解码像素更少、画得更快。
八、一条完整的"显示一张 JPG"链路
TF 卡里的 JPG → SD_MMC.setPins + begin 拉起 TF 卡
→ getFsJpgSize 量宽高 w, h
→ setJpgScale 决定缩放 1/2/4/8
→ drawFsJpg 读文件、开始解码
→ 解码库每解出一块,调 tft_output 回调
→ tft.pushImage 把这一块推到屏幕
→ 一块块拼出整张图
→ 停 1.5 秒 / 等你手指滑一下,换下一张
真正要记住的只有一句:一张 JPG 到屏幕 = 拉起 TF 卡 → 量宽高 → 定缩放 → 解码 → 一块块推到屏幕;JPG 是压缩图,画出来靠 TJpgDec 解码。
九、过关检查
- JPG 为什么比原图小?"解码"在干什么?
- 一张 JPG 从 TF 卡到屏幕,经过哪几步?
SD_MMC.setPins那 6 个数字是干嘛的?begin()呢?- 为什么要先
getFsJpgSize量宽高,再drawFsJpg? - 图太大画不下,改哪个代码名?取哪几个值?
- 为什么电子绘本断网也能翻页?
留下三样东西:TF 卡里那 4 张图的名字、串口打印的第一张图 Width/Height、以及"一张 JPG 怎么显示到屏幕上"的一句话。
十、还能做成什么
| 作品方向 | 描述给 AI 的效果 | 再想想 |
|---|---|---|
| 一图一行字 | 每页图下面加一行中文说明 | 用哪套中文字库?字放屏幕底部怎么定位? |
| 目录页 | 打开先显示 4 张缩略图,点哪张看哪页 | 缩略图用 setJpgScale(8)?点击怎么对应原图? |
| 下一页/上一页 | 左滑下一页、右滑上一页 | 方向判断用触摸坐标差怎么算? |
| 自动配乐绘本 | 每翻一页配一段第 38 课音效 | 翻页和放歌怎么"抢" CPU? |
| 我的相册 | 自动扫出 TF 卡所有 .jpg | 怎么扫描而不是写死 4 个文件名? |
下节课预告:学会"从 TF 卡读一张图、解码、显示到屏幕"后,第 40 课让板子"出门"——通过蓝牙把图和字送到另一块板子的屏幕上。