STM32-EMWIN JPEG画像表示(23)

EMWI

序文

JPEGは、フルカラーおよびグレースケール画像の標準的な圧縮方法です。JPEGは、「現実世界」のシーン、線画、漫画、およびその他の非現実的な画像を圧縮するために使用されます。JPEGは不可逆です。つまり、出力画像は入力画像とまったく同じではないため、まったく同じ出力ビットを実現する必要がある場合は、JPEGを使用できません。ただし、一般的な写真画像の場合、認識できる変化なしに非常に優れた圧縮レベルを得ることができます。emWinはJPEG画像表示をサポートしており、外部ストレージ(SDカードなど)からJPEG画像ファイルを直接読み取ってLCDに表示できます。

1.JPEGファイルAPI関数

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.実験的デモンストレーション

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

関数JpegGetData()は、外部メモリからJPEG画像データを取得するために使用され、関数displayjpegex()がJPEG画像を表示するときにパラメータとしてGUI_JPEG_GetInfoEx()に渡されます。
関数displyjpeg()は、JPEG画像を表示するために使用されます。この関数は、最初にJPEG画像のすべてのデータをRAMにロードし、次にEMWINの対応する関数を呼び出して、RAMにロードされたJPEG画像をLCDに表示します
。 RAMに入れるので、大量のRAMが必要ですが、表示は高速です。この機能は、表示するJPEG画像の位置と倍率を設定できます。
関数displayjpegex()もJPEG画像を表示します。関数displyjpeg()とは異なり、displayjpegex()はJPEG画像をRAMにロードする必要がなく、外部メモリからJPEG画像を直接読み取って表示できます。この方法ではRAMが必要です。小さいですが、displyjpeg()よりも速度が遅くなります。この関数は、表示するJPEG画像の位置と倍率を設定することもできます。

各関数がどのように機能するかを理解するために、ルーチンは私によって変更されました。
ここに画像の説明を挿入
これは時間厳守の原子の現象です。見れば理解できます。

おすすめ

転載: blog.csdn.net/qq_51963216/article/details/124079792