ЭМИ
Каталог статей
предисловие
Изображения 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, передняя часть представляет собой серию операций для чтения изображений и, наконец, их отображения.Просто внимательно посмотрите на код.