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と同様に、前面は画像を読み取り、最終的に表示する一連の操作です。コードを注意深く見てください。