EMWI
Artikelverzeichnis
Vorwort
JPEG stellt die Standardkomprimierungsmethode für Vollfarb- und Graustufenbilder dar. JPEG wird zum Komprimieren von "realen" Szenen, Strichzeichnungen, Cartoons und anderen nicht realistischen Bildern verwendet, die nicht seine Stärke sind. JPEG ist verlustbehaftet, was bedeutet, dass das Ausgabebild nicht genau das gleiche wie das Eingabebild ist. Wenn Sie also genau die gleichen Ausgabebits erreichen müssen, können Sie JPEG nicht verwenden. Für gängige fotografische Bilder können Sie jedoch sehr gute Komprimierungsstufen ohne erkennbare Änderung erzielen. emWin unterstützt die JPEG-Bildanzeige und kann JPEG-Bilddateien direkt von einem externen Speicher (z. B. einer SD-Karte) lesen, um sie auf dem LCD anzuzeigen.
1. API-Funktionen für JPEG-Dateien
GUI_JPEG_Draw() 绘制已加载到存储器的 JPEG 文件。
GUI_JPEG_DrawEx() 绘制无需加载到存储器的 JPEG 文件。
GUI_JPEG_DrawScaled() 绘制已加载到存储器的带比例的 JPEG 文件。
GUI_JPEG_DrawScaledEx() 绘制无需加载到存储器的带比例的 JPEG 文件。
GUI_JPEG_GetInfo() 基于已加载到存储器的 JPEG 文件填充 UGI_JPEG_INFO 结构。
GUI_JPEG_GetInfoEx() 基于无需加载到存储器的 JPEG 文件填充 GUI_JPEG_INFO 结构。
2. Experimentelle Demonstration
#include "jpegdisplay.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 JPEGFile;
static char jpegBuffer[JPEGPERLINESIZE];
static int JpegGetData(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(jpegBuffer))
{
NumBytesReq = sizeof(jpegBuffer);
}
//Òƶ¯Ö¸Õëµ½Ó¦¸Ã¶ÁÈ¡µÄλÖÃ
if(Off == 1) readaddress = 0;
else readaddress=Off;
#if SYSTEM_SUPPORT_UCOS
OS_ENTER_CRITICAL(); //ÁÙ½çÇø
#endif
f_lseek(phFile,readaddress);
//¶ÁÈ¡Êý¾Ýµ½»º³åÇøÖÐ
f_read(phFile,jpegBuffer,NumBytesReq,&NumBytesRead);
#if SYSTEM_SUPPORT_UCOS
OS_EXIT_CRITICAL(); //Í˳öÁÙ½çÇø
#endif
*ppData = (U8 *)jpegBuffer;
return NumBytesRead;//·µ»Ø¶ÁÈ¡µ½µÄ×Ö½ÚÊý
}
//ÔÚÖ¸¶¨Î»ÖÃÏÔʾ¼ÓÔص½RAMÖеÄJPEGͼƬ
//JPEGFileName:ͼƬÔÚSD¿¨»òÕßÆäËû´æ´¢É豸ÖеÄ·¾¶(ÐèÎļþϵͳ֧³Ö£¡)
//mode:ÏÔʾģʽ
// 0 ÔÚÖ¸¶¨Î»ÖÃÏÔʾ£¬ÓвÎÊýx,yÈ·¶¨ÏÔʾλÖÃ
// 1 ÔÚLCDÖмäÏÔʾͼƬ£¬µ±Ñ¡Ôñ´ËģʽµÄʱºò²ÎÊýx,yÎÞЧ¡£
//x:ͼƬ×óÉϽÇÔÚLCDÖеÄxÖáλÖÃ(µ±²ÎÊýmodeΪ1ʱ£¬´Ë²ÎÊýÎÞЧ)
//y:ͼƬ×óÉϽÇÔÚLCDÖеÄyÖáλÖÃ(µ±²ÎÊýmodeΪ1ʱ£¬´Ë²ÎÊýÎÞЧ)
//member: Ëõ·Å±ÈÀýµÄ·Ö×ÓÏî
//denom:Ëõ·Å±ÈÀýµÄ·ÖĸÏî
//·µ»ØÖµ:0 ÏÔʾÕý³£,ÆäËû ʧ°Ü
int displyjpeg(u8 *JPEGFileName,u8 mode,u32 x,u32 y,int member,int denom)
{
u16 bread;
char *jpegbuffer;
char result;
int XSize,YSize;
GUI_JPEG_INFO JpegInfo;
float Xflag,Yflag;
#if SYSTEM_SUPPORT_UCOS
OS_CPU_SR cpu_sr;
#endif
result = f_open(&JPEGFile,(const TCHAR*)JPEGFileName,FA_READ); //´ò¿ªÎļþ
//Îļþ´ò¿ª´íÎó»òÕßÎļþ´óÓÚJPEGMEMORYSIZE
if((result != FR_OK) || (JPEGFile.fsize>JPEGMEMORYSIZE)) return 1;
jpegbuffer=mymalloc(SRAMEX,JPEGFile.fsize); //ÉêÇëÄÚ´æ
if(jpegbuffer == NULL) return 2;
#if SYSTEM_SUPPORT_UCOS
OS_ENTER_CRITICAL(); //ÁÙ½çÇø
#endif
result = f_read(&JPEGFile,jpegbuffer,JPEGFile.fsize,(UINT *)&bread); //¶ÁÈ¡Êý¾Ý
if(result != FR_OK) return 3;
#if SYSTEM_SUPPORT_UCOS
OS_EXIT_CRITICAL(); //Í˳öÁÙ½çÇø
#endif
GUI_JPEG_GetInfo(jpegbuffer,JPEGFile.fsize,&JpegInfo); //»ñÈ¡JEGPͼƬÐÅÏ¢
XSize = JpegInfo.XSize; //»ñÈ¡JPEGͼƬµÄXÖá´óС
YSize = JpegInfo.YSize; //»ñÈ¡JPEGͼƬµÄYÖá´óС
switch(mode)
{
case 0: //ÔÚÖ¸¶¨Î»ÖÃÏÔʾͼƬ
if((member == 1) && (denom == 1)) //ÎÞÐèËõ·Å£¬Ö±½Ó»æÖÆ
{
GUI_JPEG_Draw(jpegbuffer,JPEGFile.fsize,x,y); //ÔÚÖ¸¶¨Î»ÖÃÏÔʾJPEGͼƬ
}else //·ñÔòͼƬÐèÒªËõ·Å
{
GUI_JPEG_DrawScaled(jpegbuffer,JPEGFile.fsize,x,y,member,denom);
}
break;
case 1: //ÔÚLCDÖмäÏÔʾͼƬ
if((member == 1) && (denom == 1)) //ÎÞÐèËõ·Å£¬Ö±½Ó»æÖÆ
{
//ÔÚLCDÖмäÏÔʾͼƬ
GUI_JPEG_Draw(jpegbuffer,JPEGFile.fsize,(lcddev.width-XSize)/2-1,(lcddev.height-YSize)/2-1);
}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;
GUI_JPEG_DrawScaled(jpegbuffer,JPEGFile.fsize,XSize,YSize,member,denom);
}
break;
}
f_close(&JPEGFile); //¹Ø±ÕJPEGFileÎļþ
myfree(SRAMEX,jpegbuffer); //ÊÍ·ÅÄÚ´æ
return 0;
}
//ÔÚÖ¸¶¨Î»ÖÃÏÔʾÎÞÐè¼ÓÔص½RAMÖеÄBMPͼƬ(ÐèÎļþϵͳ֧³Ö£¡¶ÔÓÚСRAM£¬ÍƼöʹÓô˷½·¨£¡)
//JPEGFileName:ͼƬÔÚSD¿¨»òÕßÆäËû´æ´¢É豸ÖеÄ·¾¶
//mode:ÏÔʾģʽ
// 0 ÔÚÖ¸¶¨Î»ÖÃÏÔʾ£¬ÓвÎÊýx,yÈ·¶¨ÏÔʾλÖÃ
// 1 ÔÚLCDÖмäÏÔʾͼƬ£¬µ±Ñ¡Ôñ´ËģʽµÄʱºò²ÎÊýx,yÎÞЧ¡£
//x:ͼƬ×óÉϽÇÔÚLCDÖеÄxÖáλÖÃ(µ±²ÎÊýmodeΪ1ʱ£¬´Ë²ÎÊýÎÞЧ)
//y:ͼƬ×óÉϽÇÔÚLCDÖеÄyÖáλÖÃ(µ±²ÎÊýmodeΪ1ʱ£¬´Ë²ÎÊýÎÞЧ)
//member: Ëõ·Å±ÈÀýµÄ·Ö×ÓÏî
//denom:Ëõ·Å±ÈÀýµÄ·ÖĸÏî
//·µ»ØÖµ:0 ÏÔʾÕý³£,ÆäËû ʧ°Ü
int displayjpegex(u8 *JPEGFileName,u8 mode,u32 x,u32 y,int member,int denom)
{
char result;
int XSize,YSize;
float Xflag,Yflag;
GUI_JPEG_INFO JpegInfo;
result = f_open(&JPEGFile,(const TCHAR*)JPEGFileName,FA_READ); //´ò¿ªÎļþ
//Îļþ´ò¿ª´íÎó
if(result != FR_OK) return 1;
GUI_JPEG_GetInfoEx(JpegGetData,&JPEGFile,&JpegInfo);
XSize = JpegInfo.XSize; //JPEGͼƬX´óС
YSize = JpegInfo.YSize; //JPEGͼƬY´óС
switch(mode)
{
case 0: //ÔÚÖ¸¶¨Î»ÖÃÏÔʾͼƬ
if((member == 1) && (denom == 1)) //ÎÞÐèËõ·Å£¬Ö±½Ó»æÖÆ
{
GUI_JPEG_DrawEx(JpegGetData,&JPEGFile,x,y);//ÔÚÖ¸¶¨Î»ÖÃÏÔʾBMPͼƬ
}else //·ñÔòͼƬÐèÒªËõ·Å
{
GUI_JPEG_DrawScaledEx(JpegGetData,&JPEGFile,x,y,member,denom);
}
break;
case 1: //ÔÚLCDÖмäÏÔʾͼƬ
if((member == 1) && (denom == 1)) //ÎÞÐèËõ·Å£¬Ö±½Ó»æÖÆ
{
//ÔÚLCDÖмäÏÔʾͼƬ
GUI_JPEG_DrawEx(JpegGetData,&JPEGFile,(lcddev.width-XSize)/2-1,(lcddev.height-YSize)/2-1);
}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;
GUI_JPEG_DrawScaledEx(JpegGetData,&JPEGFile,XSize,YSize,member,denom);
}
break;
}
f_close(&JPEGFile); //¹Ø±ÕBMPFileÎļþ
return 0;
}
void jpegdisplay_demo(void)
{
GUI_SetBkColor(GUI_BLUE);
GUI_SetColor(GUI_RED);
GUI_SetFont(&GUI_FontHZ16);
GUI_Clear();
while(1)
{
displyjpeg("0:/PICTURE/JPEG/ʵÀýͼƬ.jpg",0,0,0, 1,1);
}
}
JpegGetData() 从外部存储器获取 JPEG 文件数据
displyjpeg ()
将 JPEG 图片加载到 RAM 中,并显示到 LCD 上,显示速度快,但是需要
大量的 RAM。
displyjpegex() 不需要将 JPEG 加载到 RAM 中,显示速度慢,但是不需要大量的 RAM。
jpegdisplay_demo () 本章实验的演示函数,在 LCD 上显示图片。
Die Funktion JpegGetData() wird verwendet, um die JPEG-Bilddaten aus dem externen Speicher zu erhalten, und wird als Parameter an GUI_JPEG_GetInfoEx() übergeben, wenn die Funktion displayjpegex() das JPEG-Bild anzeigt.
Zur Anzeige des JPEG-Bildes dient die Funktion displyjpeg(), die zunächst alle Daten des JPEG-Bildes in den RAM lädt und dann die entsprechende Funktion in EMWIN aufruft, um das in den RAM geladene JPEG-Bild auf dem LCD
anzuzeigen in RAM, benötigt also viel RAM, aber die Anzeige ist schnell! Diese Funktion kann die Position und Vergrößerung des anzuzeigenden JPEG-Bildes festlegen.
Die Funktion displayjpegex () stellt auch JPEG-Bilder dar. Im Gegensatz zur Funktion displyjpeg () muss displayjpegex () keine JPEG-Bilder in den Arbeitsspeicher laden, sondern kann JPEG-Bilder direkt aus dem externen Speicher lesen und anzeigen. Diese Methode erfordert das Arbeitsspeicher klein, aber langsamer als displyjpeg ().Diese Funktion kann auch die Position und Vergrößerung des anzuzeigenden JPEG-Bildes einstellen.
Die Routinen wurden von mir modifiziert, um zu verstehen, wie jede Funktion funktioniert.
Dies ist das Phänomen der punktuellen Atome. Wenn man es sich anschaut, kann man es immer noch verstehen.