目录
一 通过BmpCvtST.exe软件将图片转换为C数组,然后通过GUI_DrawBitmapEx函数显示
二 STemWin中bmp,jpg,gif,png格式图片的相关接口函数
三 读取SD卡的BMP格式图片的数据,然后调用GUI_BMP_DrawEx函数BMP图片。
四 读取SD卡的JPG格式图片的数据,然后调用GUI_JPG_DrawEx函数JPG图片。
五 读取SD卡的GIF格式图片的数据,然后调用GUI_GIF_DrawSub函数GIF图片。
一 通过BmpCvtST.exe软件将图片转换为C数组,然后通过GUI_DrawBitmapEx函数显示
该方式比较简便且可以转换多种图片格式,但是比较耗内存,生成的图片数组会占用大量空间。
1. 通过BmpCvtST.exe软件打开一张图片,然后通过“Image->Convert to->Best palette转换图片”
2. 通过“File -> save as”菜单将图片保存为.c文件,然后选择“8 bit per pixel ”或者 “High color(565)”都行
3. 生成的.c文件格式如下所示,需要关注的是bmzhenji_bitmap 结构体:
extern GUI_CONST_STORAGE GUI_BITMAP bmzhenji_bitmap;
static GUI_CONST_STORAGE unsigned short _aczhenji_bitmap[] = {
...............................//此处省略
};
GUI_CONST_STORAGE GUI_BITMAP bmzhenji_bitmap = {
500, // xSize
346, // ySize
1000, // BytesPerLine
16, // BitsPerPixel
(unsigned char *)_aczhenji_bitmap, // Pointer to picture data
NULL, // Pointer to palette
GUI_DRAW_BMP565
};
4. 通过GUI_DrawBitmapEx函数显示图片,该函数使用方法如下
//位图中坐标为(0,0)的对应显示在LCD的(150,30)点,且缩放倍数为500/1000 = 0.5
GUI_DrawBitmapEx(&bmzhenji_bitmap, 150, 30, 0, 0, 500, 500);
二 STemWin中bmp,jpg,gif,png格式图片的相关接口函数
BMP格式 | BMP格式图片的所有数据都已加载入内存(数组)时,可调用的相关函数。(使用该方式需要分配一个与图片大小一样的内存空间,且需要GUI_ALLOC_AssignMemory函数分配的STemWin空间能够完全加载整个图片,比较耗内存。) | GUI_BMP_GetXSize() //获取图片X方向尺寸 GUI_BMP_GetYSize() //获取图片Y方向尺寸 GUI_BMP_Draw() //按原大小进行显示 GUI_BMP_DrawScaled() //进行倍数显示 |
BMP格式图片循环读入一块指定大小的内存中,进行显示时,可调用的相关函数。(该方式必须额外实现一个GUI_GET_DATA_FUNC类型的函数) | GUI_BMP_GetXSizeEx() //获取图片X方向尺寸 GUI_BMP_GetYSizeEx() //获取图片Y方向尺寸 GUI_BMP_DrawEx() //按原大小进行显示 GUI_BMP_DrawScaledEx()//进行倍数显示 | |
将LCD屏幕截图为BMP格式的图片,可调用的相关函数 | GUI_BMP_Serialize() GUI_BMP_SerializeEx() GUI_BMP_SerializeExBpp() | |
JPG格式 | JPG格式图片的所有数据都已加载入内存(数组)时,可调用的相关函数。 | GUI_JPEG_GetInfo() GUI_JPEG_Draw() GUI_JPEG_DrawScaled() |
JPGP格式图片循环读入一块指定大小的内存中,进行显示时,可调用的相关函数。 | GUI_JPEG_DrawEx() GUI_JPEG_DrawScaledEx() GUI_JPEG_GetInfoEx() | |
GIF格式 | GIF格式图片的所有数据都已加载入内存(数组)时,可调用的相关函数。(如果是动图,建议使用该种方式) | GUI_GIF_GetImageInfo()//获取图片信息 GUI_GIF_Draw()//显示gif中的第一张图片 GUI_GIF_DrawSub()//第一张图片按倍数关系显示 GUI_GIF_DrawSub()//显示gif中的子图片 GUI_GIF_DrawSubScaled()//子图片按倍数关系显示 |
GIF格式图片循环读入一块指定大小的内存中,进行显示时,可调用的相关函数。(如果是动图,在STemWin中使用该种方式显示会发现越来越慢,猜测越到后面通过GUI_GET_DATA_FUNC函数读取数据越慢,具体原因不详。) | GUI_GIF_GetImageInfoEx()//获取图片信息 GUI_GIF_DrawEx()//显示gif中的第一张图片 GUI_GIF_DrawSubEx()//第一张图片按倍数关系显示 GUI_GIF_DrawSubEx()//显示gif中的子图片 GUI_GIF_DrawSubScaledEx()//子图片按倍数关系显示 | |
PNG格式 | PNG格式图片的所有数据都已加载入内存(数组)时,可调用的相关函数。(默认STemWin不带PNG相关函数,需要管网下载添加额外的PNG库) | GUI_PNG_GetXSize() GUI_PNG_GetYSize() GUI_PNG_Draw() |
PNG格式图片循环读入一块指定大小的内存中,进行显示时,可调用的相关函数。 | GUI_PNG_GetXSizeEx() GUI_PNG_GetYSizeEx() GUI_PNG_DrawEx() |
三 读取SD卡的BMP格式图片的数据,然后调用GUI_BMP_DrawEx函数BMP图片。
通过查看GUI_BMP_DrawEx函数,发现期第一个参数为GUI_GET_DATA_FUNC 类型的指针,而该指针定义如下:
typedef int GUI_GET_DATA_FUNC(void * p, const U8 ** ppData, unsigned NumBytes, U32 Off);
在STemWin的官方手册会说明该函数该怎么设计,下面是通过Fat32文件系统读取文件数据的前提下设计的该函数,该函数也通用于jpg,png,gif图片格式的显示。
//绘制无需加载到RAM中的BMP图片时,图片每行的字节数
#define BMP_PERLINE_SIZE 2*1024
static char bmpBuffer[BMP_PERLINE_SIZE];
static int GetPicData(void * p, const U8 ** ppData, unsigned NumBytesReq, U32 Off)
{
static int readAddr = 0;
FIL * phFile;
UINT br;
phFile = (FIL *)p;
if (NumBytesReq > sizeof(bmpBuffer)) {
NumBytesReq = sizeof(bmpBuffer);
}
//移动指针到应该读取的位置
if(Off == 1)
readAddr = 0;
else
readAddr = Off;
f_lseek(phFile,readAddr);
f_read(phFile, bmpBuffer, NumBytesReq, &br);//读取数据到缓冲区中
*ppData = (U8 *)bmpBuffer;
return br;//返回读取到的字节数
}
实现了GetPicData函数后,接下来就可以调用GUI_BMP_DrawEx函数进行显示了
static FIL PicFile;
/***************************************************************************************
* @brief
* @input BMPFileName:图片在SD卡或者其他存储设备中的路径(需文件系统支持!)
* @return
***************************************************************************************/
uint8_t ReadDisp_bmp(char *fileName)
{
int XSize,YSize;
/*######1. 打开bmp文件,判断文件大小#######*/
retSD = f_open(&PicFile, (const TCHAR*)fileName, FA_READ);
if(retSD != FR_OK || PicFile.obj.objsize > BMP_MAX_SIZE){
return 1;
}
/*######2. 获取bmp图像尺寸#######*/
XSize = GUI_BMP_GetXSizeEx(GetPicData, &PicFile); //获取图片的X轴大小
YSize = GUI_BMP_GetYSizeEx(GetPicData, &PicFile); //获取图片的Y轴大小
/*######3. 通过GUI_BMP_GetXSizeEx函数在LCD中间显示bmp图像#######*/
GUI_BMP_DrawEx(GetPicData, &PicFile, (LCD_WIDTH-XSize)/2-1, (LCD_HEIGHT-YSize)/2-1);
/*######4. 通过GUI_BMP_GetXSizeEx函数在LCD中间显示0.5倍的bmp图像#######*/
GUI_BMP_DrawScaledEx(GetPicData, &PicFile, (LCD_WIDTH - XSize * 0.5)/2, (LCD_HEIGHT - YSize * 0.5)/2, 1, 2);
f_close(&PicFile);
return 0;
}
四 读取SD卡的JPG格式图片的数据,然后调用GUI_JPG_DrawEx函数JPG图片。
static FIL PicFile;
/***************************************************************************************
* @brief
* @input JPGFileName:图片在SD卡或者其他存储设备中的路径(需文件系统支持!)
* @return
***************************************************************************************/
uint8_t ReadDisp_jpg(char *FileName)
{
GUI_JPEG_INFO JpegInfo;
/*######1. 打开jpg文件,判断文件大小#######*/
retSD = f_open(&PicFile, (const TCHAR*)FileName, FA_READ);
if(retSD != FR_OK || PicFile.obj.objsize > BMP_MAX_SIZE){
return 1;
}
/*######3. 在LCD中间显示jpg图像#######*/
GUI_JPEG_DrawEx(GetPicData, &PicFile,(LCD_WIDTH-JpegInfo.XSize)/2, (LCD_HEIGHT-JpegInfo.YSize)/2);
GUI_Delay(500);
GUI_Clear();
/*######4. 按0.5倍在LCD中间显示jpg图像#######*/
GUI_JPEG_DrawScaledEx(GetPicData, &PicFile, (LCD_WIDTH - JpegInfo.XSize * 0.5)/2, (LCD_HEIGHT - JpegInfo.YSize * 0.5)/2, 1, 2);
f_close(&PicFile);
return 0;
}
五 读取SD卡的GIF格式图片的数据,然后调用GUI_GIF_DrawSub函数GIF图片。
ReadDisp_gif函数中的内存分配函数是自己实现的,分配的是SDRAM中的空间,具体实现方式可参考正点原子的例子。
代码中的mem_free与mem_malloc函数可参考博客https://blog.csdn.net/Ningjianwen/article/details/90940570中的第四小节
ReadDisp_gif函数如下所示:
static FIL PicFile;
/***************************************************************************************
* @brief
* @input FileName:图片在SD卡或者其他存储设备中的路径(需文件系统支持!)
* @return
***************************************************************************************/
uint8_t ReadDisp_gif(char *FileName)
{
UINT br;
char *bmpBuf;
GUI_GIF_INFO GifInfo;
GUI_GIF_IMAGE_INFO ImageInfo;
/*######1. 打开gif文件,判断文件大小#######*/
retSD = f_open(&PicFile, (const TCHAR*)FileName, FA_READ);
if(retSD != FR_OK || PicFile.obj.objsize > BMP_MAX_SIZE){
return 1;
}
/*######2. 分配内存用于保存bmp文件内容#######*/
bmpBuf = mem_malloc(PicFile.obj.objsize);
if(bmpBuf == NULL){
return 2;
}
/*######3. 将文件内容读入分配好的bmpBuf缓存#######*/
retSD = f_read(&PicFile, bmpBuf, PicFile.obj.objsize, &br);
if(retSD != FR_OK){
return 3;
}
/*######4. 获取gif文件信息#######*/
GUI_GIF_GetInfo(bmpBuf, PicFile.obj.objsize, &GifInfo);
/*######5. 在LCD中间显示gif图像#######*/
for(int i = 0; i < GifInfo.NumImages; i++)
{
GUI_GIF_DrawSub(bmpBuf, PicFile.obj.objsize, (LCD_WIDTH - GifInfo.xSize)/2, (LCD_HEIGHT - GifInfo.ySize)/2,i);
GUI_Delay(ImageInfo.Delay ? ImageInfo.Delay*10 : 100 );//延时
}
/*######6. 按0.5倍关系在LCD中间显示gif图像#######*/
for(int i=0; i < GifInfo.NumImages; i++)
{
GUI_GIF_DrawSubScaled(bmpBuf, PicFile.obj.objsize, (LCD_WIDTH - GifInfo.xSize * 0.5)/2, (LCD_HEIGHT - GifInfo.ySize * 0.5)/2, i, 1 ,2);
GUI_Delay(ImageInfo.Delay ? ImageInfo.Delay*10 : 100 );//延时
}
mem_free(bmpBuf);
f_close(&PicFile);
return 0;
}