STM32 - EMWIN JPEG-Bildanzeige (23)

EMWI

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.
Bildbeschreibung hier einfügen
Dies ist das Phänomen der punktuellen Atome. Wenn man es sich anschaut, kann man es immer noch verstehen.

Supongo que te gusta

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