STM32——EMWIN PNG 图片显示(二十五)

EMWIN

前言

PNG 格式是一种图像格式,其目的是试图替代 GIF 和 TIFF 文件格式,同时增加一些 GIF文件格式所不具备的特性。PNG 用来存储灰度图像时,灰度图像的深度可多到 16 位,存储彩色图像时,彩色图像的深度可多到 48 位,并且还可存储多到 16 位的α通道数据。emWin 是支持 PNG 解码的

一、RAM 使用

PNG 解压缩大约需要 21 Kb RAM 用于与图像大小无关的解压缩和依赖大小的字节量。
RAM 要求可按以下方式计算:
大约 RAM 要求 = (X-Size + 1)* Y 大小 * 4 + 21Kbytes。
这里我们给 emWin 分配 500k 的外部 SRAM 内存,打开 GUIConf.c,图中红框就是为emWin 分配的内存大小。
在这里插入图片描述

二、PNG 文件 API 函数

GUI_PNG_Draw() 绘制已加载到存储器的 PNG 文件。
GUI_PNG_DrawEx() 绘制无需加载到存储器的 PNG 文件。
GUI_PNG_GetXSize() 返回加载到存储器的位图的 X 大小
GUI_PNG_GetXSizeEx() 返回无需加载到存储器的位图的 X 大小。
GUI_PNG_GetYSize() 返回加载到存储器的位图的 Y 大小。
GUI_PNG_GetYSizeEx() 返回无需加载到存储器的位图的 Y 大小。

三、实验演示

#include "pngdisplay.h"
#include "EmWinHZFont.h"
#include "GUI.h"
#include "malloc.h"
#include "ff.h"
#include "ili93xx.h"
#if SYSTEM_SUPPORT_UCOS
#include "includes.h" //ucos 使用 
#endif
static FIL PNGFile;
static int PngGetData(void * p, const U8 ** ppData, unsigned NumBytesReq, U32 Off) 
{
    
    
static int readaddress=0;
FIL * phFile;
U8 *pData;
UINT NumBytesRead;
#if SYSTEM_SUPPORT_UCOS
OS_CPU_SR cpu_sr;
#endif
pData = (U8*)*ppData;
phFile = (FIL *)p;
//移动指针到应该读取的位置
if(Off == 1) readaddress = 0;
else readaddress=Off;
#if SYSTEM_SUPPORT_UCOS
OS_ENTER_CRITICAL(); //临界区
#endif
f_lseek(phFile,readaddress); 
//读取数据到缓冲区中
f_read(phFile,pData,NumBytesReq,&NumBytesRead);
#if SYSTEM_SUPPORT_UCOS
OS_EXIT_CRITICAL(); //退出临界区
#endif
return NumBytesRead;//返回读取到的字节数
}
//在指定位置显示加载到 RAM 中的 PNG 图片(PNG 图片不能缩放!)
//PNGFileName:图片在 SD 卡或者其他存储设备中的路径(需文件系统支持!)
//mode:显示模式
// 0 在指定位置显示,有参数 x,y 确定显示位置
// 1 在 LCD 中间显示图片,当选择此模式的时候参数 x,y 无效。
//x:图片左上角在 LCD 中的 x 轴位置(当参数 mode 为 1 时,此参数无效)
//y:图片左上角在 LCD 中的 y 轴位置(当参数 mode 为 1 时,此参数无效)
//返回值:0 显示正常,其他 失败
int displaypng(char *PNGFileName,u8 mode,u32 x,u32 y)
{
    
    
GUI_HMEM PNGMem;
u16 bread;
char *pngbuffer;
char result;
int XSize,YSize;
#if SYSTEM_SUPPORT_UCOS
OS_CPU_SR cpu_sr;
#endif
result = f_open(&PNGFile,(const TCHAR*)PNGFileName,FA_READ); //打开文件
//文件打开错误或者文件大于 JPEGMEMORYSIZE
if((result != FR_OK) || (PNGFile.fsize>PNGMEMORYSIZE)) return 1;
pngbuffer=mymalloc(SRAMEX,PNGFile.fsize);
if(pngbuffer == NULL) return 2;
#if SYSTEM_SUPPORT_UCOS
OS_ENTER_CRITICAL(); //临界区
#endif
result = f_read(&PNGFile,pngbuffer,PNGFile.fsize,(UINT *)&bread); //读取数据
if(result != FR_OK) return 3;
#if SYSTEM_SUPPORT_UCOS
OS_EXIT_CRITICAL(); //退出临界区
#endif
XSize = GUI_PNG_GetXSize(pngbuffer,PNGFile.fsize); //获取 PNG 图片的 X 轴大小
YSize = GUI_PNG_GetYSize(pngbuffer,PNGFile.fsize); //获取 PNG 图片的 Y 轴大小
switch(mode)
{
    
    
case 0: //在指定位置显示图片
GUI_PNG_Draw(pngbuffer,PNGFile.fsize,x,y);//显示 PNG 图片
break;
case 1: //在 LCD 中间显示图片
GUI_PNG_Draw(pngbuffer,PNGFile.fsize,(lcddev.width-XSize)/2-1,\
(lcddev.height-YSize)/2-1);
break;
}
f_close(&PNGFile); //关闭 PNGFile 文件
myfree(SRAMEX,pngbuffer);
return 0;
}
//在指定位置显示无需加载到 RAM 中的 PNG 图片(需文件系统支持!对于小 RAM,推荐使用
此方法!PNG 图片不能缩放!)
//PNGFileName:图片在 SD 卡或者其他存储设备中的路径
//mode:显示模式
// 0 在指定位置显示,有参数 x,y 确定显示位置
// 1 在 LCD 中间显示图片,当选择此模式的时候参数 x,y 无效。
//x:图片左上角在 LCD 中的 x 轴位置(当参数 mode 为 1 时,此参数无效)
//y:图片左上角在 LCD 中的 y 轴位置(当参数 mode 为 1 时,此参数无效)
//返回值:0 显示正常,其他 失败
int displaypngex(char *PNGFileName,u8 mode,u32 x,u32 y)
{
    
    
char result;
int XSize,YSize;
result = f_open(&PNGFile,(const TCHAR*)PNGFileName,FA_READ); //打开文件
//文件打开错误
if(result != FR_OK) return 1;
XSize = GUI_PNG_GetXSizeEx(PngGetData,&PNGFile);//PNG 图片 X 大小
YSize = GUI_PNG_GetYSizeEx(PngGetData,&PNGFile);//PNG 图片 Y 大小
switch(mode)
{
    
    
case 0: //在指定位置显示图片
GUI_PNG_DrawEx(PngGetData,&PNGFile,x,y);
break;
case 1: //在 LCD 中间显示图片
GUI_PNG_DrawEx(PngGetData,&PNGFile,(lcddev.width-XSize)/2-1,\
(lcddev.height-YSize)/2-1);
break;
}f_close(&PNGFile); //关闭 PNGFile 文件
return 0;
}
//PNG 图片显示例程
void pngdisplay_demo(void)
{
    
    
GUI_SetBkColor(GUI_BLUE);
GUI_SetFont(&GUI_FontHZ16);
GUI_SetColor(GUI_RED);
GUI_Clear();
while(1)
{
    
    
GUI_DispStringHCenterAt("在指定位置显示一张加载到 RAM 中的 PNG 图片",400,0);
displaypng("0:/PICTURE/PNG/皇冠.png",0,200,100);
GUI_Delay(1000);
GUI_Clear();
displaypng("0:/PICTURE/PNG/CS.png",1,0,0);
GUI_Delay(1000);
GUI_Clear();
displaypng("0:/PICTURE/PNG/香蕉.png",1,0,0);
GUI_Delay(1000);
GUI_Clear();
GUI_DispStringHCenterAt("在指定位置显示一张无需加载的 PNG 图片",400,0);
displaypngex("0:/PICTURE/PNG/驴.png",0,200,100);
GUI_Delay(1000);
GUI_Clear();
displaypngex("0:/PICTURE/PNG/文件夹.png",1,0,0);
GUI_Delay(1000);
GUI_Clear();
displaypngex("0:/PICTURE/PNG/风扇.png",1,0,0);
GUI_Delay(1000);
GUI_Clear();
} }
PngGetData () 从外部存储器获取 PNG 文件数据
displaypng ()将 PNG 图片加载到 RAM 中,并显示到 LCD 上,显示速度快,但是需要大量的 RAM。
displaypngex () 不需要将 PNG 加载到 RAM 中,显示速度慢,但是不需要大量的 RAM。

函数 PngGetData ()用于从外部存储器中获取 PNG 图片数据,在函数 displaypngex ()显示PNG 图片的时候做为参数传递给 GUI_PNG_DrawEx ()和 GUI_PNG_GetXSizeEx()这两个函数。函数displaypng ()用于显示PNG图片,该函数首先将PNG图片的所有数据加载到RAM中,然后调用 EMWIN 中的相应函数在 LCD 上显示加载到 RAM 中的 PNG 图片,由于需要将整副PNG 图片加载到 RAM 中,所以需要大量的 RAM,但是显示速度快!此函数可以设置要显示的 PNG 图片的位置。
函数 displaypngex ()也是显示 PNG 图片的,与函数 displaypng ()不同的是,displaypngex ()不需要将 PNG 图片加载到 RAM 中,可以直接从外部存储器中读取 GIF 图片并显示,这种方法需要的 RAM 小,但是速度相比 displaypng ()要慢,此函数也可以设置要显示的 PNG 图片的位置。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_51963216/article/details/124094264
今日推荐