STM32 - EMWIN JPEG picture display (23)

EMWI

foreword

JPEG is the standard compression method for full-color and grayscale images. JPEG is used to compress "real-world" scenes, line drawings, cartoons, and other non-realistic images that are not its strong suit. JPEG is lossy, meaning that the output image is not exactly the same as the input image, so if you need to achieve exactly the same output bits, you cannot use JPEG. However, for common photographic images, you can get very good compression levels with no discernible change. emWin supports JPEG image display, and can directly read JPEG image files from external storage (such as SD card) to display on LCD.

1. JPEG file API functions

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. Experimental 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 上显示图片。

The function JpegGetData () is used to obtain the JPEG image data from the external memory, and is passed as a parameter to GUI_JPEG_GetInfoEx() when the function displayjpegex() displays the JPEG image.
The function displyjpeg () is used to display the JPEG image. This function first loads all the data of the JPEG image into the RAM, and then calls the corresponding function in EMWIN to display the JPEG image loaded into the RAM on the LCD
. Loaded into RAM, so requires a lot of RAM, but the display is fast! This function can set the position and magnification of the JPEG image to be displayed.
The function displayjpegex () also displays JPEG images. Different from the function displyjpeg (), displayjpegex () does not need to load JPEG images into RAM, and can directly read JPEG images from external memory and display them. This method requires The RAM is small, but the speed is slower than displyjpeg (). This function can also set the position and magnification of the JPEG image to be displayed.

The routines have been modified by me in order to understand how each function works.
insert image description here
This is the phenomenon of punctual atoms. If you look at it, you can still understand it.

Guess you like

Origin blog.csdn.net/qq_51963216/article/details/124079792