STM32-EMWIN GIF画像表示(24)

EMWI

序文

GIF画像は、データネットワーク間での送信に使用されます。GIF標準は、インターレース、透明度、アプリケーション定義データ、アニメーション、および生のテキストレンダリングをサポートします。emWinは、生のテキストやアプリケーション固有のデータなど、サポートされていないデータを無視します。GIFファイルは、LZW(Lempel-Zif-Welch)ファイル圧縮方式を使用して画像データを圧縮します。これはデータを失うことなく動作します。出力画像は入力画像とまったく同じです。

1.GIFファイルのサポート

グラフィックライブラリは、最初にグラフィック情報をデコードします。GIF画像を表示する場合、デコードプロセスに長い時間がかかります。GIFファイルがウィンドウマネージャーによって頻繁に呼び出されるコールバック関数で使用される場合、デコードプロセスにもかなりの時間がかかる可能性があります。ストレージデバイスを使用することで計算時間を短縮できます。最初にストレージデバイスに画像を描画するのが最善の方法です。この場合、解凍は1回だけ実行されます。emWinのGIF解凍プロセスでは、解凍に約16キロバイトの動的に割り当てられたRAMが必要であり、解凍に使用されたRAMは、画像が描画された後に解放されます。

2.GIFファイルAPI関数

GUI_GIF_Draw() 绘制已加载到存储器的 GIF 文件的第一个图像。
GUI_GIF_DrawEx() 绘制无需加载到存储器的 GIF 文件的第一个图像。
GUI_GIF_DrawSub() 绘制已加载到存储器的 GIF 文件的给定子图像。
GUI_GIF_DrawSubEx() 绘制无需加载到存储器的 GIF 文件的给定子图像。
GUI_GIF_DrawSubScaled() 绘制已加载到存储器的带比例的 GIF 文件的给定子图像。
GUI_GIF_DrawSubScaledEx() 绘制无需加载到存储器的带比例的 GIF 文件的给定子图像。
GUI_GIF_GetComment() 返回已加载到存储器的 GIF 文件给定的注释。
GUI_GIF_GetCommentEx() 返回无需加载到存储器的 GIF 文件的给定注释
GUI_GIF_GetImageInfo() 返回已加载到存储器的 GIF 文件的相关信息。
GUI_GIF_GetImageInfoEx() 返回无需加载到存储器的 GIF 文件的相关信息。
GUI_GIF_GetInfo() 返回已加载到存储器的 GIF 文件的相关信息。
GUI_GIF_GetInfoEx() 返回无需加载到存储器的 GIF 文件的相关信息。
GUI_GIF_GetXSize() 返回加载到存储器的位图的 X 大小。
GUI_GIF_GetXSizeEx() 返回无需加载到存储器的位图的 X 大小。
GUI_GIF_GetYSize() 返回加载到存储器的位图的 Y 大小。
GUI_GIF_GetYSizeEx() 返回无需加载到存储器的位图的 Y 大小。

3.実験的デモンストレーション

#include "gifdisplay.h"
#include "EmWinHZFont.h"
#include "GUI.h"
#include "malloc.h"
#include "ff.h"
#include "lcd.h"


#if SYSTEM_SUPPORT_UCOS
#include "includes.h"					//ucos ʹÓÃ	  
#endif

static FIL GIFFile;
static char gifBuffer[GIFPERLINESIZE];
/*******************************************************************
*
*       Static functions
*
********************************************************************
*/
/*********************************************************************
*
*       GifGetData
*
* Function description
*   This routine is called by GUI_GIF_DrawEx(). The routine is responsible
*   for setting the data pointer to a valid data location with at least
*   one valid byte.
*
* Parameters:
*   p           - Pointer to application defined data.
*   NumBytesReq - Number of bytes requested.
*   ppData      - Pointer to data pointer. This pointer should be set to
*                 a valid location.
*   StartOfFile - If this flag is 1, the data pointer should be set to the
*                 beginning of the data stream.
*
* Return value:
*   Number of data bytes available.
*/
static int GifGetData(void * p, const U8 ** ppData, unsigned NumBytesReq, U32 Off) 
{
    
    
	static int readaddress=0;
	FIL * phFile;
	UINT NumBytesRead;
	#if SYSTEM_SUPPORT_UCOS
		OS_CPU_SR cpu_sr;
	#endif
	
	phFile = (FIL *)p;
	
	if (NumBytesReq > sizeof(gifBuffer)) 
	{
    
    
		NumBytesReq = sizeof(gifBuffer);
	}

	//Òƶ¯Ö¸Õëµ½Ó¦¸Ã¶ÁÈ¡µÄλÖÃ
	if(Off == 1) readaddress = 0;
	else readaddress=Off;
	
	#if SYSTEM_SUPPORT_UCOS
		OS_ENTER_CRITICAL();	//ÁÙ½çÇø
	#endif
	f_lseek(phFile,readaddress); 
	
	//¶ÁÈ¡Êý¾Ýµ½»º³åÇøÖÐ
	f_read(phFile,gifBuffer,NumBytesReq,&NumBytesRead);
	
		
	#if SYSTEM_SUPPORT_UCOS
		OS_EXIT_CRITICAL();	//Í˳öÁÙ½çÇø
	#endif
	
	*ppData = (U8 *)gifBuffer;
	return NumBytesRead;//·µ»Ø¶ÁÈ¡µ½µÄ×Ö½ÚÊý
}

//ÔÚÖ¸¶¨Î»ÖÃÏÔʾ¼ÓÔص½RAMÖеÄGIFͼƬ
//GIFFileName:ͼƬÔÚSD¿¨»òÕßÆäËû´æ´¢É豸ÖеÄ·¾¶(ÐèÎļþϵͳ֧³Ö£¡)
//mode:ÏÔʾģʽ
//		0 ÔÚÖ¸¶¨Î»ÖÃÏÔʾ£¬ÓвÎÊýx,yÈ·¶¨ÏÔʾλÖÃ
//		1 ÔÚLCDÖмäÏÔʾͼƬ£¬µ±Ñ¡Ôñ´ËģʽµÄʱºò²ÎÊýx,yÎÞЧ¡£
//x:ͼƬ×óÉϽÇÔÚLCDÖеÄxÖáλÖÃ(µ±²ÎÊýmodeΪ1ʱ£¬´Ë²ÎÊýÎÞЧ)
//y:ͼƬ×óÉϽÇÔÚLCDÖеÄyÖáλÖÃ(µ±²ÎÊýmodeΪ1ʱ£¬´Ë²ÎÊýÎÞЧ)
//member:  Ëõ·Å±ÈÀýµÄ·Ö×ÓÏî
//denom:Ëõ·Å±ÈÀýµÄ·ÖĸÏî
//·µ»ØÖµ:0 ÏÔʾÕý³£,ÆäËû ʧ°Ü
int displaygif(char *GIFFileName,u8 mode,u32 x,u32 y,int member,int denom)
{
    
    
	int i;
	u16 bread;
	char *gifbuffer;
	char result;
	int XSize,YSize;
	GUI_GIF_INFO GifInfo;
	GUI_GIF_IMAGE_INFO ImageInfo;
	float Xflag,Yflag;
	
	#if SYSTEM_SUPPORT_UCOS
		OS_CPU_SR cpu_sr;
	#endif

	result = f_open(&GIFFile,(const TCHAR*)GIFFileName,FA_READ);	//´ò¿ªÎļþ
	//Îļþ´ò¿ª´íÎó»òÕßÎļþ´óÓÚJPEGMEMORYSIZE
	if((result != FR_OK) || (GIFFile.fsize>GIFMEMORYSIZE)) 	return 1;
	
	gifbuffer=mymalloc(SRAMEX,GIFFile.fsize);
	if(gifbuffer == NULL) return 2;
	
	#if SYSTEM_SUPPORT_UCOS
		OS_ENTER_CRITICAL();	//ÁÙ½çÇø
	#endif
		
	result = f_read(&GIFFile,gifbuffer,GIFFile.fsize,(UINT *)&bread); //¶ÁÈ¡Êý¾Ý
	if(result != FR_OK) return 3;
	
	#if SYSTEM_SUPPORT_UCOS
		OS_EXIT_CRITICAL();	//Í˳öÁÙ½çÇø
	#endif
	
	GUI_GIF_GetInfo(gifbuffer,GIFFile.fsize,&GifInfo);	//»ñÈ¡GIFͼƬÐÅÏ¢
	
	XSize = GifInfo.xSize;	//»ñÈ¡GIFͼƬµÄXÖá´óС
	YSize = GifInfo.ySize;	//»ñÈ¡GIFͼƬµÄYÖá´óС
	switch(mode)
	{
    
    
		case 0:	//ÔÚÖ¸¶¨Î»ÖÃÏÔʾͼƬ
			if((member == 1) && (denom == 1)) //ÎÞÐèËõ·Å£¬Ö±½Ó»æÖÆ
			{
    
    
				//ÔÚÖ¸¶¨Î»ÖÃÏÔʾJPEGͼƬ
				for(i=0;i<GifInfo.NumImages;i++)
				{
    
    
					GUI_GIF_DrawSub(gifbuffer,GIFFile.fsize,x,y,i);
					GUI_GIF_GetImageInfo(gifbuffer,GIFFile.fsize,&ImageInfo,i);
					GUI_Delay(ImageInfo.Delay ? ImageInfo.Delay*10:100);//ÑÓʱ
				}
			}else //·ñÔòͼƬÐèÒªËõ·Å
			{
    
    
				for(i=0;i<GifInfo.NumImages;i++)
				{
    
    
					GUI_GIF_DrawSubScaled(gifbuffer,GIFFile.fsize,x,y,i,member,denom);
					GUI_GIF_GetImageInfo(gifbuffer,GIFFile.fsize,&ImageInfo,i);
					GUI_Delay(ImageInfo.Delay ? ImageInfo.Delay*10:100);//ÑÓʱ
				}
			}
			break;
		case 1:	//ÔÚLCDÖмäÏÔʾͼƬ
			if((member == 1) && (denom == 1)) //ÎÞÐèËõ·Å£¬Ö±½Ó»æÖÆ
			{
    
    
				//ÔÚLCDÖмäÏÔʾͼƬ
				for(i=0;i<GifInfo.NumImages;i++)
				{
    
    
					GUI_GIF_DrawSub(gifbuffer,GIFFile.fsize,(lcddev.width-XSize)/2-1,(lcddev.height-YSize)/2-1,i);
					GUI_GIF_GetImageInfo(gifbuffer,GIFFile.fsize,&ImageInfo,i);
					GUI_Delay(ImageInfo.Delay ? ImageInfo.Delay*10:100);//ÑÓʱ
				}
			}else //·ñÔòͼƬÐèÒªËõ·Å
			{
    
    
				Xflag = (float)XSize*((float)member/(float)denom);
				Yflag = (float)YSize*((float)member/(float)denom);
				XSize = (lcddev.width-(int)Xflag)/2-1;
				YSize = (lcddev.height-(int)Yflag)/2-1;
				
				for(i=0;i<GifInfo.NumImages;i++)
				{
    
    
					GUI_GIF_DrawSubScaled(gifbuffer,GIFFile.fsize,XSize,YSize,i,member,denom);
					GUI_GIF_GetImageInfo(gifbuffer,GIFFile.fsize,&ImageInfo,i);
					GUI_Delay(ImageInfo.Delay ? ImageInfo.Delay*10:100);//ÑÓʱ
				}
			}
			break;
	}
	f_close(&GIFFile);		//¹Ø±ÕJPEGFileÎļþ
	myfree(SRAMEX,gifbuffer);	//ÊÍ·ÅÄÚ´æ
	return 0;
}

//ÔÚÖ¸¶¨Î»ÖÃÏÔʾÎÞÐè¼ÓÔص½RAMÖеÄGIFͼƬ(ÐèÎļþϵͳ֧³Ö£¡¶ÔÓÚСRAM£¬ÍƼöʹÓô˷½·¨£¡)
//GIFFileName:ͼƬÔÚSD¿¨»òÕßÆäËû´æ´¢É豸ÖеÄ·¾¶
//mode:ÏÔʾģʽ
//		0 ÔÚÖ¸¶¨Î»ÖÃÏÔʾ£¬ÓвÎÊýx,yÈ·¶¨ÏÔʾλÖÃ
//		1 ÔÚLCDÖмäÏÔʾͼƬ£¬µ±Ñ¡Ôñ´ËģʽµÄʱºò²ÎÊýx,yÎÞЧ¡£
//x:ͼƬ×óÉϽÇÔÚLCDÖеÄxÖáλÖÃ(µ±²ÎÊýmodeΪ1ʱ£¬´Ë²ÎÊýÎÞЧ)
//y:ͼƬ×óÉϽÇÔÚLCDÖеÄyÖáλÖÃ(µ±²ÎÊýmodeΪ1ʱ£¬´Ë²ÎÊýÎÞЧ)
//member:  Ëõ·Å±ÈÀýµÄ·Ö×ÓÏî
//denom:Ëõ·Å±ÈÀýµÄ·ÖĸÏî
//·µ»ØÖµ:0 ÏÔʾÕý³£,ÆäËû ʧ°Ü
int displaygifex(char *GIFFileName,u8 mode,u32 x,u32 y,int member,int denom)
{
    
    
	char result;
	int i;
	int XSize,YSize;
	float Xflag,Yflag;
	GUI_GIF_INFO GifInfo;
	GUI_GIF_IMAGE_INFO ImageInfo;

	result = f_open(&GIFFile,(const TCHAR*)GIFFileName,FA_READ);	//´ò¿ªÎļþ
	//Îļþ´ò¿ª´íÎó
	if(result != FR_OK) 	return 1;
		
	GUI_GIF_GetInfoEx(GifGetData,&GIFFile,&GifInfo);
	XSize = GifInfo.xSize;	//GIFͼƬX´óС
	YSize = GifInfo.ySize;	//GIFͼƬY´óС
	switch(mode)
	{
    
    
		case 0:	//ÔÚÖ¸¶¨Î»ÖÃÏÔʾͼƬ
			if((member == 1) && (denom == 1)) //ÎÞÐèËõ·Å£¬Ö±½Ó»æÖÆ
			{
    
    
				//ÔÚÖ¸¶¨Î»ÖÃÏÔʾBMPͼƬ
				for(i=0;i<GifInfo.NumImages;i++)
				{
    
    
					GUI_GIF_DrawSubEx(GifGetData,&GIFFile,x,y,i);
					GUI_GIF_GetImageInfoEx(GifGetData,&GIFFile,&ImageInfo,i);
					GUI_Delay(ImageInfo.Delay ? ImageInfo.Delay*10:100);//ÑÓʱ
				}
			}else //·ñÔòͼƬÐèÒªËõ·Å
			{
    
    
				for(i=0;i<GifInfo.NumImages;i++)
				{
    
    
					GUI_GIF_DrawSubScaledEx(GifGetData,&GIFFile,x,y,i,member,denom);
					GUI_GIF_GetImageInfoEx(GifGetData,&GIFFile,&ImageInfo,i);
					GUI_Delay(ImageInfo.Delay ? ImageInfo.Delay*10:100);//ÑÓʱ
				}
			}
			break;
		case 1:	//ÔÚLCDÖмäÏÔʾͼƬ
			if((member == 1) && (denom == 1)) //ÎÞÐèËõ·Å£¬Ö±½Ó»æÖÆ
			{
    
    
				//ÔÚLCDÖмäÏÔʾͼƬ
				for(i=0;i<GifInfo.NumImages;i++)
				{
    
    
					GUI_GIF_DrawSubEx(GifGetData,&GIFFile,(lcddev.width-XSize)/2-1,(lcddev.height-YSize)/2-1,i);
					GUI_GIF_GetImageInfoEx(GifGetData,&GIFFile,&ImageInfo,i);
					GUI_Delay(ImageInfo.Delay ? ImageInfo.Delay*10:100);//ÑÓʱ
				}
			}else //·ñÔòͼƬÐèÒªËõ·Å
			{
    
    
				Xflag = (float)XSize*((float)member/(float)denom);
				Yflag = (float)YSize*((float)member/(float)denom);
				XSize = (lcddev.width-(int)Xflag)/2-1;
				YSize = (lcddev.height-(int)Yflag)/2-1;
				
				for(i=0;i<GifInfo.NumImages;i++)
				{
    
    
					GUI_GIF_DrawSubScaledEx(GifGetData,&GIFFile,XSize,YSize,i,member,denom);
					GUI_GIF_GetImageInfoEx(GifGetData,&GIFFile,&ImageInfo,i);
					GUI_Delay(ImageInfo.Delay ? ImageInfo.Delay*10:100);//ÑÓʱ
				}
			}
			break;
	}

	
	f_close(&GIFFile);		//¹Ø±ÕGIFFileÎļþ
	return 0;
}	

//GIFͼƬÏÔʾÀý³Ì
void gifdisplay_demo(void)
{
    
    
	
	GUI_SetBkColor(GUI_BLUE);
	GUI_SetFont(&GUI_FontHZ16);
	GUI_SetColor(GUI_RED);
	GUI_Clear();
	while(1)
	{
    
    
		//GUI_DispStringHCenterAt("ÔÚÖ¸¶¨Î»ÖÃÏÔʾһÕżÓÔص½RAMÖеÄGIFͼƬ",400,0);
		displaygif("0:/PICTURE/GIF/Áú.gif",1,20,20,2,1);
//		GUI_Delay(1000);
//		GUI_Clear();
//	
//		GUI_DispStringHCenterAt("ÔÚLCDÖмäÏÔʾһÕÅÀ©´ó2±¶µÄ¼ÓÔص½RAMÖеÄGIFͼƬ",400,0);
//		displaygif("0:/PICTURE/GIF/С»ÆÈË.gif",1,0,0,2,1);	
//		GUI_Delay(1000);
//		GUI_Clear();
//		
//		GUI_DispStringHCenterAt("ÔÚLCDÖмäÏÔʾһÕÅËõС1/2µÄ¼ÓÔص½RAMÖеÄGIFͼƬ",400,0);
//		displaygif("0:/PICTURE/GIF/»ð²ñÈË.gif",1,0,0,1,2);
//		GUI_Delay(1000);
//		GUI_Clear();
//		
//		GUI_DispStringHCenterAt("ÔÚÖ¸¶¨Î»ÖÃÏÔʾһÕÅÎÞÐè¼ÓÔصÄGIFͼƬ",400,0);
//		displaygifex("0:/PICTURE/GIF/Áú.gif",0,20,20,1,1);
//		GUI_Delay(1000);
//		GUI_Clear();
//		
//		GUI_DispStringHCenterAt("ÔÚLCDÖмäÏÔʾһÕÅÀ©´ó2±¶µÄÎÞÐè¼ÓÔصÄGIFͼƬ",400,0);
//		displaygifex("0:/PICTURE/GIF/С»ÆÈË.gif",1,0,0,2,1);	
//		GUI_Delay(1000);
//		GUI_Clear();
//	
//		GUI_DispStringHCenterAt("ÔÚLCDÖмäÏÔʾһÕÅËõС1/2µÄÎÞÐè¼ÓÔصÄGIFͼƬ",400,0);
//		displaygifex("0:/PICTURE/GIF/»ð²ñÈË.gif",1,0,0,1,2);
//		GUI_Delay(1000);
//		GUI_Clear();
	}
}

GifGetData () 从外部存储器获取 GIF 文件数据
displaygif ()将 GIF 图片加载到 RAM 中,并显示到 LCD 上,显示速度快,但是需要大量的 RAM。 
dispgifex() 不需要将 GIF 加载到 RAM 中,显示速度慢,但是不需要大量的 RAM。

関数GifGetData()は、外部メモリからJPEG画像データを取得するために使用され、関数displaygifex()がGIF画像を表示するときにパラメータとしてGUI_GIF_GetImageInfoEx()に渡されます。関数displaygif()は、GIF画像を表示するために使用されます。この関数は、最初にGIF画像のすべてのデータをRAMにロードし、次にEMWINの対応する関数を呼び出して、RAMにロードされたGIF画像をLCDに表示します。 RAMに入れるので、大量のRAMが必要ですが、表示は高速です。この機能は、表示するGIF画像の位置と倍率を設定できます。関数displaygifex()もGIF画像を表示します。関数displygif()とは異なり、displaygifex()はGIF画像をRAMにロードする必要がなく、外部メモリからGIF画像を直接読み取って表示できます。この方法ではRAMが必要です。小さいですが、displygif()よりも速度が遅くなります。この関数は、表示するGIF画像の位置と倍率を設定することもできます。
ここに画像の説明を挿入
ここに画像の説明を挿入

要約する

BMPやJPGと同様に、前面は画像を読み取り、最終的に表示する一連の操作です。コードを注意深く見てください。

おすすめ

転載: blog.csdn.net/qq_51963216/article/details/124088978