Skip to content

ESP32 传输大图片会乱码

复制本地路径 | 在线编辑

做一个项目的时候,之前一直用降采样的图片粗略查看情况。有一次为了演示换成了不降采样,结果发现图片传输经常会乱码。

直接说结论,原因是因为传输的数据量大了,所以串口传输可能会错乱掉... 所以解决方式就是分块发送,每个块之间延迟一些时间:

uint8_t *jpgbuf = NULL;
size_t jpglen = 0;
frame2jpg(fb, 80, &jpgbuf, &jpglen);

// DEBUG_PRINT("send jpg len: %d, img width: %d, height: %d\n", jpglen, fb->width, fb->height);

// 防止乱码,按照 1024 分组发送
int chunk_size = 1024;
for (int i = 0; i < jpglen; i += chunk_size) {
    if (i + chunk_size > jpglen) {
        SerialDebug.write(jpgbuf + i, jpglen - i);
    } else {
        SerialDebug.write(jpgbuf + i, chunk_size);
    }
    SerialDebug.flush();
    delay(100); // 需要自己尝试 delay 多久
}
free(jpgbuf);

当时排查了大概一天多,周五下午+周六上午,中午去资料馆看了电影,五点多回来突然想到了这一点,非常奇妙的经历...排查了半天,问了 AI 半天,一直在走偏路,如果不是突然想到这一点估计要猴年马月了。

当时的排查思路:
1. 刚开始只是带着排查的,当时是发现图片乱码了,怀疑是因为芯片的 setting 不对?改了一会发现还是有,后来专门检查才发现只有不降采样才会有,那肯定不是图像芯片的问题,因为降采样我是在 ESP32 主程序里面做的。
2. 既然不降采样会有,那大概率就是转 JPG 溢出了呗。所以增大缓冲区,发现不起作用。后来干脆增加的特别大,不行。
3. 看来要好好对待这个问题了,所以先看看原图会不会乱码?所以修改程序让他出原图。但没想到获取原图会如此麻烦,这个后记详细说明。原图不是乱码,那么还是转 JPG 的问题。
4. 在 AI 的帮助下,想到是不是因为没有申请内存到 PRAM 中?于是做了一下检查,改了好几条语句,发现还是不行。
5. 于是就怀疑是转 JPG 的那个工具有问题,直接下载源码 jpge.cpp 去修改,先打印了几条语句,感觉也没有溢出的风险。
6. 最后就突然想到,会不会和打印原图时候遇到的问题一样,因为传输量变大,所以乱码概率加大了!而且一旦乱码,后续我对收到的数据进行 JPG 解码,那肯定有问题。果然如此。

打印原图的记录:
1. 没想到打印原图这么麻烦,不过多亏有这个经历,才突然想到最终的原因。
2. 当时我是直接用 Serial.printf("%02X", img[i]) 来打印各个字节内容。但是收到发现总是会有乱掉的(伏笔了)。
3. 本来打算是用无损压缩,但既然我们是临时这样做,所以就反复多次输出原图,并且是一行一行打印内容,每行之前做个标记。
4. 这样如果某次有一行的数据量不对,那就直接丢弃,多次循环总有一次这一行的数据是正常的。最后是三次循环出图,大部分行的数据都有了。

Comments