STM32 - EMWIN отображение изображений в формате GIF (24)

ЭМИ

предисловие

Изображения GIF используются для передачи по сетям передачи данных. Стандарт GIF поддерживает чересстрочную развертку, прозрачность, данные, определяемые приложением, анимацию и рендеринг необработанного текста. emWin игнорирует неподдерживаемые данные, такие как необработанный текст или данные, специфичные для приложения. Файлы GIF используют метод сжатия файлов LZW (Lempel-Zif-Welch) для сжатия данных изображения, который работает без потери данных. Выходное изображение точно такое же, как и входное изображение.

1. Поддержка файлов GIF

Графическая библиотека сначала декодирует графическую информацию.При отображении изображений GIF процесс декодирования займет много времени. Если файл GIF используется в функции обратного вызова, которая часто вызывается оконным менеджером, процесс декодирования также может занять значительное время. Время вычислений можно сократить, используя запоминающее устройство. Лучше всего сначала нарисовать изображение на запоминающем устройстве, и в этом случае распаковка будет выполнена только один раз. Процесс декомпрессии GIF в emWin требует около 16 килобайт динамически выделяемой оперативной памяти для распаковки, и оперативная память, используемая для распаковки, освобождается после отрисовки изображения.

2. API-функция файла GIF

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 из внешней памяти и передается в качестве параметра в GUI_GIF_GetImageInfoEx(), когда функция displaygifex() отображает изображение GIF. Для отображения GIF-изображения используется функция displaygif().Эта функция сначала загружает все данные GIF-изображения в оперативную память, а затем вызывает соответствующую функцию в EMWIN для отображения загруженного в оперативную память GIF-изображения на ЖК-дисплее.Загружено в ОЗУ, поэтому требует много ОЗУ, но дисплей быстрый! Эта функция позволяет установить положение и масштаб отображаемого изображения GIF. Функция displaygifex() также отображает GIF-изображения. В отличие от функции displygif(), displaygifex() не требует загрузки GIF-изображений в ОЗУ и может напрямую считывать GIF-изображения из внешней памяти и отображать их.Для этого метода требуется ОЗУ маленький, но скорость медленнее, чем displygif ().Эта функция также может установить положение и увеличение отображаемого изображения GIF.
вставьте сюда описание изображения
вставьте сюда описание изображения

Подведем итог

Подобно BMP и JPG, передняя часть представляет собой серию операций для чтения изображений и, наконец, их отображения.Просто внимательно посмотрите на код.

Supongo que te gusta

Origin blog.csdn.net/qq_51963216/article/details/124088978
Recomendado
Clasificación