找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4178|回复: 33
收起左侧

esp32利用Arduino_GFX_Library库显示图片问题

[复制链接]
ID:891089 发表于 2023-2-21 13:29 | 显示全部楼层 |阅读模式
好兄弟们,我在用esp32c3读取SD卡中图片并显示到tft1.8屏幕上,单独一张图片显示正常显示,但是循环一组图片时,就一直显示第一张图片。代码贴到下面
///////////////////////////////////////代码开始///////////////////////////////////////////////
  1. #include <SPI.h>
  2. #include <mySD.h>
  3. #include <Arduino_GFX_Library.h>
  4. #include<String.h>
  5. ext::File bmpFile;
  6. unsigned short pic[0x5000]; // 128*160图像0x5000像素
  7. byte aByte;                 // 1字节数据
  8. /*******重复播放图片所需变量*******************************/
  9. char* aa[]={"1.bmp","2.bmp","3.bmp","4.bmp","5.bmp"};
  10. unsigned int bmp;
  11. /******************************************************/
  12. Arduino_DataBus *bus = new Arduino_ESP32SPI(5 /* DC */, 7 /* CS */, 2 /* SCK */, 3 /* MOSI */);
  13. Arduino_GFX *gfx = new Arduino_ST7735(bus, 4 /* RST */, 2 /* 旋转屏幕180度 */, false);

  14. void setup()
  15. {
  16.     Serial.begin(115200);
  17.     //从SD卡读取图片
  18.     SD.begin(6, 3, 10, 2);
  19. }
  20. void loop()
  21. {
  22.    for(bmp=0;bmp<5;bmp++){
  23.    bmpFile = SD.open(aa[bmp], FILE_READ);
  24.    if (bmpFile){
  25.         //显示图片
  26.         while (bmpFile.available())
  27.         {
  28.             //跳过前0x36个字节的头
  29.             for (int i = 0; i < 0x36; i++)
  30.             {
  31.                 Serial.print(bmpFile.read(), HEX);
  32.             }
  33.             //把rgb24转换成rgb16
  34.             for (int i = 0; i < 0x5000; i++)
  35.             {
  36.                 aByte = bmpFile.read();
  37.                 pic[i] = (aByte * 32 / 256) << 11;
  38.                 aByte = bmpFile.read();
  39.                 pic[i] |= (aByte * 64 / 256) << 5;
  40.                 aByte = bmpFile.read();
  41.                 pic[i] |= (aByte * 32 / 256);
  42.             }
  43.         }
  44.        bmpFile.close();
  45.     }
  46.     //显示图片
  47.     gfx->begin();
  48.     gfx->fillScreen(WHITE);
  49.     gfx->draw16bitRGBBitmap(0, 0, pic, 128, 160);
  50.     delay(100);
  51.   }
  52. }
复制代码
///////////////////////////////////////代码结束///////////////////////////////////////////////
就是这句bmpFile = SD.open(aa[bmp], FILE_READ);,我aa[]数组放的是图片的名称:{"1.bmp","2.bmp","3.bmp","4.bmp","5.bmp"},当写为aa[0]时,显示的是"1.bmp"这张图片,是正确的。但是用循环 for(bmp=0;bmp<5;bmp++),然后aa[bmp]时,只会显示第一张图片5次,而不会显示"2.bmp","3.bmp","4.bmp","5.bmp",各位好兄弟有什么想法吗?
回复

使用道具 举报

ID:1063483 发表于 2023-2-21 14:48 | 显示全部楼层
<SPI.h>
<mySD.h>
<Arduino_GFX_Library.h>
<String.h>
如果可以把这几个头文件提供一下,愿意帮你调试一下
回复

使用道具 举报

ID:891089 发表于 2023-2-21 15:30 来自触屏版 | 显示全部楼层
watsonbu 发表于 2023-2-21 14:48
如果可以把这几个头文件提供一下,愿意帮你调试一下

谢谢好兄弟,spi.h和string.h是自带库,其他两个我怎么发给你?
回复

使用道具 举报

ID:384109 发表于 2023-2-21 16:26 | 显示全部楼层
可以先不用数组,直接把显示图片部分重复五次,每次开不同的图片,就可以确定问题点了
回复

使用道具 举报

ID:891089 发表于 2023-2-21 16:33 来自触屏版 | 显示全部楼层
人中狼 发表于 2023-2-21 16:26
可以先不用数组,直接把显示图片部分重复五次,每次开不同的图片,就可以确定问题点了

这个方法也试过,我是把显示部分复制了两次,结果是第一张图片显示了两次。刷新函数也有,我就想不通是哪里出现了问题,你可以看下我的程序,我是把显示部分除了gfx变量的所有变量都新定义了新变量,gfx是屏幕引脚定义变量,我觉得应该不是这个方法问题。
回复

使用道具 举报

ID:1063483 发表于 2023-2-21 17:18 | 显示全部楼层
就在黑51发消息给我就可以了
回复

使用道具 举报

ID:891089 发表于 2023-2-21 17:45 来自触屏版 | 显示全部楼层
watsonbu 发表于 2023-2-21 17:18
就在黑51发消息给我就可以了

我手机没看到怎么发文件给你,是要用电脑发给你吗?
回复

使用道具 举报

ID:384109 发表于 2023-2-21 17:49 | 显示全部楼层
美琴的备胎 发表于 2023-2-21 16:33
这个方法也试过,我是把显示部分复制了两次,结果是第一张图片显示了两次。刷新函数也有,我就想不通是哪 ...

我的意思是这里bmpFile = SD.open(aa[bmp], FILE_READ);不用数组,看代码应该是这个函数调用的问题,只打开了一个文件,可以查查这个函数的具体用法和参数要求。
回复

使用道具 举报

ID:384109 发表于 2023-2-21 17:51 | 显示全部楼层
美琴的备胎 发表于 2023-2-21 16:33
这个方法也试过,我是把显示部分复制了两次,结果是第一张图片显示了两次。刷新函数也有,我就想不通是哪 ...

还有一个已经打开的文件,在开第二个文件时是否需要关闭的问题
回复

使用道具 举报

ID:891089 发表于 2023-2-21 18:55 | 显示全部楼层
人中狼 发表于 2023-2-21 17:49
我的意思是这里bmpFile = SD.open(aa, FILE_READ);不用数组,看代码应该是这个函数调用的问题,只打开了 ...

这个原始程序就是bmpFile = SD.open(“1.bmp”, FILE_READ);,我改成数组调用了,aa[0]的话也是可以正常显示的,我试过了
回复

使用道具 举报

11#
无效楼层,该帖已经被删除
ID:891089 发表于 2023-2-21 18:58 | 显示全部楼层
人中狼 发表于 2023-2-21 17:51
还有一个已经打开的文件,在开第二个文件时是否需要关闭的问题

bmpFile.close();  有的,要关的
回复

使用道具 举报

ID:891089 发表于 2023-2-21 19:24 | 显示全部楼层
#include <SPI.h>
#include <mySD.h>
#include <Arduino_GFX_Library.h>
#include<String.h>
ext::File bmpFile,bmpFile1;
unsigned short pic[0x5000],pic1[0x5000]; // 128*160图像0x5000像素
byte aByte,aByte1;                 // 1字节数据
/*******重复播放图片所需变量*******************************/
char* aa[]={"1.bmp","2.bmp","3.bmp","4.bmp","5.bmp"};
unsigned int bmp;
/******************************************************/
Arduino_DataBus *bus = new Arduino_ESP32SPI(5 /* DC */, 7 /* CS */, 2 /* SCK */, 3 /* MOSI */);
Arduino_GFX *gfx = new Arduino_ST7735(bus, 4 /* RST */, 2 /* 旋转屏幕180度 */, false);

void setup()
{
    Serial.begin(115200);
    //从SD卡读取图片
    SD.begin(6, 3, 10, 2);
}
void loop()
{
   //for(bmp=0;bmp<5;bmp++){
   bmpFile = SD.open(/*aa[bmp]*/"1.bmp", FILE_READ);
   if (bmpFile){
        //显示图片
        while (bmpFile.available())
        {
            //跳过前0x36个字节的头
            for (int i = 0; i < 0x36; i++)
            {
                Serial.print(bmpFile.read(), HEX);
            }
            //把rgb24转换成rgb16
            for (int i = 0; i < 0x5000; i++)
            {
                aByte = bmpFile.read();
                pic[i] = (aByte * 32 / 256) << 11;
                aByte = bmpFile.read();
                pic[i] |= (aByte * 64 / 256) << 5;
                aByte = bmpFile.read();
                pic[i] |= (aByte * 32 / 256);
            }
        }  
       bmpFile.close();
   }


    bmpFile1 = SD.open(/*aa[bmp]*/"2.bmp", FILE_READ);
   if (bmpFile1){
        //显示图片
        while (bmpFile1.available())
        {
            //跳过前0x36个字节的头
            for (int i = 0; i < 0x36; i++)
            {
                Serial.print(bmpFile1.read(), HEX);
            }
            //把rgb24转换成rgb16
            for (int i = 0; i < 0x5000; i++)
            {
                aByte1 = bmpFile1.read();
                pic1[i] = (aByte1 * 32 / 256) << 11;
                aByte1 = bmpFile1.read();
                pic1[i] |= (aByte1 * 64 / 256) << 5;
                aByte1 = bmpFile1.read();
                pic1[i] |= (aByte1 * 32 / 256);
            }
        }  
       bmpFile1.close();
   }

   
    //显示图片
    gfx->begin();
    gfx->fillScreen(WHITE);
    gfx->draw16bitRGBBitmap(0, 0, pic, 128, 160);
    delay(100);
    gfx->draw16bitRGBBitmap(0, 0, pic1, 128, 160);
    delay(100);
   //}
}
这样写代码,可以两个图片循环显示了
回复

使用道具 举报

ID:384109 发表于 2023-2-21 20:12 | 显示全部楼层
返回一下文件打开状态吧,如果if (bmpFile)这个不成立的话,显示数据pic[ i] 不会改变,应该就还是之前打开文件的数据,问题应该还是在文件的打开上,后面的文件都没有成功打开,只打开了第一个
回复

使用道具 举报

ID:1063483 发表于 2023-2-21 21:27 | 显示全部楼层
你的程序有个小问题,从头到尾再找吧。

可能程序有点小问题

可能程序有点小问题
回复

使用道具 举报

ID:384109 发表于 2023-2-21 22:28 | 显示全部楼层
美琴的备胎 发表于 2023-2-21 19:24
#include
#include
#include

aa[]定义错误,https://blog.csdn.net/qiaoermeng/article/details/88366250,可以看看这里的解释
回复

使用道具 举报

ID:1063483 发表于 2023-2-21 22:31 | 显示全部楼层
修改了如下,不知道能不能成功

#include <SPI.h>
#include <mySD.h>
#include <Arduino_GFX_Library.h>
#include<String.h>
ext::File bmpFile;
unsigned short pic[0x5000]; // 128*160图像0x5000像素
byte aByte;                 // 1字节数据
/*******重复播放图片所需变量*******************************/
char* aa[5]={"1.bmp","2.bmp","3.bmp","4.bmp","5.bmp"};
unsigned int bmp;
/******************************************************/
Arduino_DataBus *bus = new Arduino_ESP32SPI(5 /* DC */, 7 /* CS */, 2 /* SCK */, 3 /* MOSI */);
Arduino_GFX *gfx = new Arduino_ST7735(bus, 4 /* RST */, 2 /* 旋转屏幕180度 */, false);

void setup()
{
    Serial.begin(115200);
    //从SD卡读取图片
    SD.begin(6, 3, 10, 2);
}
void loop()
{
   for(bmp=0;bmp<5;bmp++){
   bmpFile = SD.open(aa[bmp], FILE_READ);
   if (bmpFile){
        //显示图片
        while (bmpFile.available())
        {
            //跳过前0x36个字节的头
            for (int i = 0; i < 0x36; i++)
            {
                Serial.print(bmpFile.read(), HEX);
            }
            //把rgb24转换成rgb16
            for (int i = 0; i < 0x5000; i++)
            {
                aByte = bmpFile.read();
                pic[i] = (aByte * 32 / 256) << 11;
                aByte = bmpFile.read();
                pic[i] |= (aByte * 64 / 256) << 5;
                aByte = bmpFile.read();
                pic[i] |= (aByte * 32 / 256);
            }
        }
        /***********************************/
       if (++bmp == 5)
       bmp = 0;          //计数复位
       /***********************************/
       bmpFile.close();
      
      // bmpFile.delete();//试试不行再加这句再试试***********
    }
    //显示图片
    gfx->begin();
    gfx->fillScreen(WHITE);
    gfx->draw16bitRGBBitmap(0, 0, pic, 128, 160);
   
    delay(100);//前面修改完还不行 ,改为delay(1000)试试************
  }
}
回复

使用道具 举报

ID:891089 发表于 2023-2-21 22:40 | 显示全部楼层
watsonbu 发表于 2023-2-21 21:27
你的程序有个小问题,从头到尾再找吧。

好兄弟,你这是缺了sd卡的库,这是地址github.com/nhatuan84/esp32-micro-sdcard/blob/master/mySD.h
回复

使用道具 举报

ID:891089 发表于 2023-2-21 23:00 | 显示全部楼层
人中狼 发表于 2023-2-21 22:28
aa[]定义错误,https://blog.csdn.net/qiaoermeng/article/details/88366250,可以看看这里的解释

我程序改成这样了

String aa[]={"1.bmp","2.bmp","3.bmp","4.bmp","5.bmp"};
*****
   for(bmp=0;bmp<5;bmp++){
   bmpFile = SD.open(aa[bmp].c_str(), FILE_READ);
******
最后输出了下 :
Serial.println(aa[bmp].c_str());

这是输出内容:
22:57:37.539 -> 5.bmp
22:57:38.886 -> 1.bmp
22:57:40.249 -> 2.bmp
22:57:41.615 -> 3.bmp
22:57:42.996 -> 4.bmp
22:57:44.372 -> 5.bmp
22:57:45.722 -> 1.bmp
22:57:47.085 -> 2.bmp
22:57:48.454 -> 3.bmp
22:57:49.842 -> 4.bmp
22:57:51.227 -> 5.bmp
22:57:52.575 -> 1.bmp
22:57:53.966 -> 2.bmp
22:57:55.316 -> 3.bmp
22:57:56.697 -> 4.bmp
22:57:58.031 -> 5.bmp
22:57:59.404 -> 1.bmp
22:58:00.797 -> 2.bmp
22:58:02.164 -> 3.bmp
确实已经写入文件名了,但是显示屏还是只显示第一张图片
回复

使用道具 举报

ID:384109 发表于 2023-2-21 23:12 | 显示全部楼层
这个不熟,不过看代码SD.open(/*aa[bmp]*/"2.bmp", FILE_READ);,串口的输出似乎少了双引号,看现象就是pic[]的数据没更新,也就是if (bmpFile)不成立
回复

使用道具 举报

ID:1063483 发表于 2023-2-21 23:20 | 显示全部楼层
#include <SPI.h>
#include <mySD.h>
#include <Arduino_GFX_Library.h>
#include<String.h>
ext::File bmpFile;
unsigned short pic[0x5000]; // 128*160图像0x5000像素
byte aByte;                 // 1字节数据
/*******重复播放图片所需变量*******************************/
char* aa[5]={"1.bmp","2.bmp","3.bmp","4.bmp","5.bmp"};
unsigned int bmp;
/******************************************************/
Arduino_DataBus *bus = new Arduino_ESP32SPI(5 /* DC */, 7 /* CS */, 2 /* SCK */, 3 /* MOSI */);
Arduino_GFX *gfx = new Arduino_ST7735(bus, 4 /* RST */, 2 /* 旋转屏幕180度 */, false);

void setup()
{
    Serial.begin(115200);
    //从SD卡读取图片
    SD.begin(6, 3, 10, 2);
}
void loop()
{
   for(bmp=0;bmp<5;bmp++){
   bmpFile = SD.open(aa[bmp], FILE_READ);
   if (bmpFile){
        //显示图片
        while (bmpFile.available())
        {
            //跳过前0x36个字节的头
            for (int i = 0; i < 0x36; i++)
            {
                Serial.print(bmpFile.read(), HEX);
            }
            //把rgb24转换成rgb16
            for (int i = 0; i < 0x5000; i++)
            {
                aByte = bmpFile.read();
                pic[i] = (aByte * 32 / 256) << 11;
                aByte = bmpFile.read();
                pic[i] |= (aByte * 64 / 256) << 5;
                aByte = bmpFile.read();
                pic[i] |= (aByte * 32 / 256);
            }
        }
        /***********************************/
       if (++bmp == 5)
       bmp = 0;          //计数复位
       /***********************************/
       bmpFile.close();
      
      // bmpFile.delete();//试试不行再加这句***********
    }
    //显示图片
    gfx->begin();
    gfx->fillScreen(WHITE);
    gfx->draw16bitRGBBitmap(0, 0, pic, 128, 160);
   
    delay(100);//前面修改完还不行 ,改为delay(1000)试试************
  }
}
回复

使用道具 举报

ID:891089 发表于 2023-2-22 12:26 | 显示全部楼层
watsonbu 发表于 2023-2-21 23:20
#include
#include
#include

只加
/***********************************/
       if (++bmp == 5)
       bmp = 0;          //计数复位
/***********************************/
也不行
  bmpFile.delete(); 也不行,会报错expected unqualified-id before 'delete'
回复

使用道具 举报

ID:1063483 发表于 2023-2-22 12:41 | 显示全部楼层
“ext::File bmpFile;”
这里能改成指针?类似    ext::File  * bmpFile;
之后只加和不加两种:
/***********************************/
       if (++bmp == 5)
       bmp = 0;          //计数复位
/***********************************/
试试?有Bug,就是如此令人不愉快
回复

使用道具 举报

ID:891089 发表于 2023-2-22 12:56 | 显示全部楼层
watsonbu 发表于 2023-2-22 12:41
“ext::File bmpFile;”
这里能改成指针?类似    ext::File  * bmpFile;
之后只加和不加两种:

试过了,会报错,我都在考虑换个显示库了,有推荐吗?
回复

使用道具 举报

ID:1063483 发表于 2023-2-22 13:04 | 显示全部楼层
“unsigned short pic[0x5000]; // 128*160图像0x5000像素”
这边有这样的问题,调试出错说, pic[0x5000]的0x5000太大。

如果考虑这些之后不行,是不是要考虑 LINUX 调试ESP32了?但是配置完 LINUX 之后,真的不推荐。
看你的程序很清晰的,似乎还是没有循环读进来。很久以前也感同身受,慢慢折腾,也许得来全不费工夫。

还有一个可能解决问题的办法,找一找 ESP32的供应商,他们有专门的售后软件工程师,当时好像跟他们一起,才把问题解决掉。但是他们就是用的 LINUX 调试和烧录的,搞好之后,不要用LINUX 烧录,太慢了!直接用他们的串口软件烧录挺快的。
回复

使用道具 举报

ID:978267 发表于 2023-2-22 14:22 | 显示全部楼层
安信可软件怎么编译三元组
回复

使用道具 举报

ID:384109 发表于 2023-2-22 16:30 | 显示全部楼层
美琴的备胎 发表于 2023-2-21 23:00
我程序改成这样了

String aa[]={"1.bmp","2.bmp","3.bmp","4.bmp","5.bmp"};

你这里应该是在bmpFile = SD.open(aa[bmp].c_str(), FILE_READ);后看bmpFile的值,现在串口输出的只是数组aa[]的内容而已,并不是打开文件是否成功的结果
回复

使用道具 举报

ID:1063483 发表于 2023-2-22 17:53 | 显示全部楼层
。。。。
SD.begin(6, 3, 10, 2);
}

void clear_buffer(){                         //缓存清除,返回-1,缓存清除。
while(Serial.read()>=0);
}
。。。。。
  gfx->draw16bitRGBBitmap(0, 0, pic, 128, 160);
    delay(1000);
    clear_buffeer();//调用清掉前一缓存
  }
}
回复

使用道具 举报

ID:419909 发表于 2023-2-23 06:50 | 显示全部楼层
路过。顺便问一下。Arduino_GFX_Library用这个库后,编译速度是不是 很慢。大概多长时间?
回复

使用道具 举报

ID:891089 发表于 2023-2-23 14:32 来自触屏版 | 显示全部楼层
watsonbu 发表于 2023-2-22 17:53
。。。。
SD.begin(6, 3, 10, 2);
}

    gfx->fillScreen(WHITE);
这一句就是刷新
回复

使用道具 举报

ID:891089 发表于 2023-2-23 14:33 来自触屏版 | 显示全部楼层
wfqxgw 发表于 2023-2-23 06:50
路过。顺便问一下。Arduino_GFX_Library用这个库后,编译速度是不是 很慢。大概多长时间?

嗯…我不知道是不是因为这个库的原因,我感觉esp32编译都很慢
回复

使用道具 举报

ID:1063483 发表于 2023-2-24 13:18 | 显示全部楼层
“esp32编译都很慢”
是arduino慢,特别是大一点的程序,里面啰啰嗦嗦一堆
回复

使用道具 举报

ID:891089 发表于 2023-2-24 19:34 | 显示全部楼层
问题解决了,用TFT_espi库,源程序放下面:
//程序开始
/*
*@功能:ESP32读取SD卡图片显示在1.14IPS屏幕上
*@作者:刘泽文
*@时间:2020/3/27
*/

//引用相关库
#include <SD.h>
#include <FS.h>
#include <SPI.h>
#include <TFT_eSPI.h>
#include <JPEGDecoder.h>


#define DEBUG

#ifdef DEBUG
#define DebugPrintln(message) Serial.println(message)
#else
#define DebugPrintln(message)
#endif

#ifdef DEBUG
#define DebugPrint(message) Serial.print(message)
#else
#define DebugPrint(message)
#endif

TFT_eSPI tft = TFT_eSPI(128, 160); // Invoke custom library
SPIClass sdSPI(VSPI);
#define SD_MISO     10
#define SD_MOSI     3
#define SD_SCLK     2
#define SD_CS       9

void drawSdJpeg(const char *filename, int xpos, int ypos);
void jpegRender(int xpos, int ypos);
void jpegInfo();
void showTime(uint32_t msTime);
void SD_read_Time(uint32_t msTime);

void setup()
{
  Serial.begin(9600);
  DebugPrintln();

  tft.init();
  tft.setRotation(1);
  tft.fillScreen(TFT_WHITE);
  tft.setTextSize(1);
  tft.setTextColor(TFT_MAGENTA);
  tft.setCursor(0, 0);
  tft.setTextDatum(MC_DATUM);
  tft.setTextSize(1);
  tft.setSwapBytes(true);
  delay(500);

  if (TFT_BL > 0) { // TFT_BL has been set in the TFT_eSPI library in the User Setup file TTGO_T_Display.h
     pinMode(TFT_BL, OUTPUT); // Set backlight pin to output mode
     digitalWrite(TFT_BL, 1); // TFT_BACKLIGHT_ONTurn backlight on. TFT_BACKLIGHT_ON has been set in the TFT_eSPI library in the User Setup file TTGO_T_Display.h
   }
  
  //挂载文件系统
  sdSPI.begin(SD_SCLK, SD_MISO, SD_MOSI, SD_CS);
  if (!SD.begin(SD_CS, sdSPI))
  {
    DebugPrintln("存储卡挂载失败");
    return;
  }
  uint8_t cardType = SD.cardType();

  if (cardType == CARD_NONE)
  {
    DebugPrintln("未连接存储卡");
    return;
  }
  else if (cardType == CARD_MMC)
  {
    DebugPrintln("挂载了MMC卡");
  }
  else if (cardType == CARD_SD)
  {
    DebugPrintln("挂载了SDSC卡");
  }
  else if (cardType == CARD_SDHC)
  {
    DebugPrintln("挂载了SDHC卡");
  }
  else
  {
    DebugPrintln("挂载了未知存储卡");
  }

  //打印存储卡信息
  Serial.printf("存储卡总大小是: %lluMB \n", SD.cardSize() / (1024 * 1024)); // "/ (1024 * 1024)"可以换成">> 20"
  Serial.printf("文件系统总大小是: %lluB \n", SD.totalBytes());
  Serial.printf("文件系统已用大小是: %lluB \n", SD.usedBytes());
}

void loop() {
/*
  //测试壁纸
  for(int image_num = 1;image_num<=6;image_num++){
    char FileName[10];
    sprintf(FileName,"%d.jpg",image_num);
    drawSdJpeg(FileName, 0, 0);     // This draws a jpeg pulled off the SD Card
    delay(500);
  }
*/
  //播放badapple,共6540帧,每秒30帧
  for(int image_num = 1;image_num<=2;image_num+=1){
    char FileName[10];
    sprintf(FileName,"/%d.jpg",image_num);
    //drawSdJpeg(FileName, 0, 0);     // This draws a jpeg pulled off the SD Card
    drawSdJpeg(FileName, 0, 0);
    delay(100);
  }

}

void drawSdJpeg(const char *filename, int xpos, int ypos) {
  uint32_t readTime = millis();
  // Open the named file (the Jpeg decoder library will close it)
  File jpegFile = SD.open( filename, FILE_READ);  // or, file handle reference for SD library

  if ( !jpegFile ) {
    DebugPrint("ERROR: File \"");
    DebugPrint(jpegFile);
    DebugPrintln ("\" not found!");
    return;
  }

  DebugPrintln("===========================");
  DebugPrint("Drawing file: "); DebugPrintln(filename);
  DebugPrintln("===========================");

  // Use one of the following methods to initialise the decoder:
  boolean decoded = JpegDec.decodeSdFile(jpegFile);  // Pass the SD file handle to the decoder,
  //boolean decoded = JpegDec.decodeSdFile(filename);  // or pass the filename (String or character array)
  SD_read_Time(millis() - readTime);

  if (decoded) {
    // print information about the image to the serial port
    jpegInfo();
    // render the image onto the screen at given coordinates
    jpegRender(xpos, ypos);
  }
  else {
    DebugPrintln("Jpeg file format not supported!");
  }
}

//####################################################################################################
// Draw a JPEG on the TFT, images will be cropped on the right/bottom sides if they do not fit
//####################################################################################################
// This function assumes xpos,ypos is a valid screen coordinate. For convenience images that do not
// fit totally on the screen are cropped to the nearest MCU size and may leave right/bottom borders.
void jpegRender(int xpos, int ypos) {
  // record the current time so we can measure how long it takes to draw an image
  uint32_t drawTime = millis();

  //jpegInfo(); // Print information from the JPEG file (could comment this line out)

  uint16_t *pImg;
  uint16_t mcu_w = JpegDec.MCUWidth;
  uint16_t mcu_h = JpegDec.MCUHeight;
  uint32_t max_x = JpegDec.width;
  uint32_t max_y = JpegDec.height;

  bool swapBytes = tft.getSwapBytes();
  tft.setSwapBytes(true);
  
  // Jpeg images are draw as a set of image block (tiles) called Minimum Coding Units (MCUs)
  // Typically these MCUs are 16x16 pixel blocks
  // Determine the width and height of the right and bottom edge image blocks
  uint32_t min_w = (mcu_w<(max_x % mcu_w)?mcu_w:(max_x % mcu_w));
  uint32_t min_h = (mcu_h<(max_y % mcu_h)?mcu_h:(max_y % mcu_h));

  // save the current image block size
  uint32_t win_w = mcu_w;
  uint32_t win_h = mcu_h;

  // save the coordinate of the right and bottom edges to assist image cropping
  // to the screen size
  max_x += xpos;
  max_y += ypos;

  // Fetch data from the file, decode and display
  while (JpegDec.read()) {    // While there is more data in the file
    pImg = JpegDec.pImage ;   // Decode a MCU (Minimum Coding Unit, typically a 8x8 or 16x16 pixel block)

    // Calculate coordinates of top left corner of current MCU
    int mcu_x = JpegDec.MCUx * mcu_w + xpos;
    int mcu_y = JpegDec.MCUy * mcu_h + ypos;

    // check if the image block size needs to be changed for the right edge
    if (mcu_x + mcu_w <= max_x) win_w = mcu_w;
    else win_w = min_w;

    // check if the image block size needs to be changed for the bottom edge
    if (mcu_y + mcu_h <= max_y) win_h = mcu_h;
    else win_h = min_h;

    // copy pixels into a contiguous block
    if (win_w != mcu_w)
    {
      uint16_t *cImg;
      int p = 0;
      cImg = pImg + win_w;
      for (int h = 1; h < win_h; h++)
      {
        p += mcu_w;
        for (int w = 0; w < win_w; w++)
        {
          *cImg = *(pImg + w + p);
          cImg++;
        }
      }
    }

    // calculate how many pixels must be drawn
    uint32_t mcu_pixels = win_w * win_h;

    // draw image MCU block only if it will fit on the screen
    if (( mcu_x + win_w ) <= tft.width() && ( mcu_y + win_h ) <= tft.height())
      tft.pushImage(mcu_x, mcu_y, win_w, win_h, pImg);
    else if ( (mcu_y + win_h) >= tft.height())
      JpegDec.abort(); // Image has run off bottom of screen so abort decoding
  }

  tft.setSwapBytes(swapBytes);

  showTime(millis() - drawTime); //将图片显示到屏幕所用的时间(ms)
}

void jpegInfo() {
  DebugPrintln("JPEG image info");
  DebugPrintln("===============");
  DebugPrint("Width      :");
  DebugPrintln(JpegDec.width);
  DebugPrint("Height     :");
  DebugPrintln(JpegDec.height);
  DebugPrint("Components :");
  DebugPrintln(JpegDec.comps);
  DebugPrint("MCU / row  :");
  DebugPrintln(JpegDec.MCUSPerRow);
  DebugPrint("MCU / col  :");
  DebugPrintln(JpegDec.MCUSPerCol);
  DebugPrint("Scan type  :");
  DebugPrintln(JpegDec.scanType);
  DebugPrint("MCU width  :");
  DebugPrintln(JpegDec.MCUWidth);
  DebugPrint("MCU height :");
  DebugPrintln(JpegDec.MCUHeight);
  DebugPrintln("===============");
  DebugPrintln("");
}

void showTime(uint32_t msTime) {
  DebugPrint(F(" JPEG drawn in "));
  DebugPrint(msTime);
  DebugPrintln(F(" ms "));
}

void SD_read_Time(uint32_t msTime) {
  Serial.print(F(" SD JPEG read in "));
  Serial.print(msTime);
  Serial.println(F(" ms "));
}
//程序结束,可以看这篇博客,我借鉴这位大佬的https://blog.csdn.net/weixin_42880082/article/details/125939534
回复

使用道具 举报

ID:891089 发表于 2023-2-24 22:37 来自触屏版 | 显示全部楼层
美琴的备胎 发表于 2023-2-24 19:34
问题解决了,用TFT_espi库,源程序放下面:
//程序开始
/*

此贴完结,谢谢大家
回复

使用道具 举报

ID:88256 发表于 2023-2-25 00:09 | 显示全部楼层
有始有终,值得一赞,不过用Arduino_GFX_Library库不能用的问题还是没有解决,希望到时候有更完美的结果。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表