• 方案介紹
    • 一、項(xiàng)目介紹
    • 二、設(shè)計(jì)思路
    • 三、代碼設(shè)計(jì)
  • 附件下載
  • 相關(guān)推薦
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

基于STM32設(shè)計(jì)的數(shù)碼相冊(cè)

04/15 09:08
637
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

更多詳細(xì)資料請(qǐng)聯(lián)系.docx

共1個(gè)文件

一、項(xiàng)目介紹

項(xiàng)目是基于STM32設(shè)計(jì)的數(shù)碼相冊(cè),能夠通過(guò)LCD顯示屏解碼顯示主流的圖片,支持bmp、jpg、gif等格式。用戶可以通過(guò)按鍵或者觸摸屏來(lái)切換圖片,同時(shí)還可以旋轉(zhuǎn)顯示,并能夠自適應(yīng)居中顯示,小尺寸圖片居中顯示,大尺寸圖片自動(dòng)縮小顯示(超出屏幕范圍)。圖片從SD卡中獲取。

image-20230618135436038

二、設(shè)計(jì)思路

2.1 硬件設(shè)計(jì)

本項(xiàng)目所需的主要硬件

  • STM32F103ZET6
  • LCD屏幕
  • SD卡模塊
  • 按鍵和觸摸屏

2.2 軟件設(shè)計(jì)

(1)解碼圖片

在STM32芯片中,解碼圖片需要將讀取到的數(shù)據(jù)存入圖形緩沖區(qū)中,以便進(jìn)行圖畫(huà)顯示。常用的解碼算法有JPEG解碼和BMP解碼。

(2)圖片顯示

為了更好的實(shí)現(xiàn)圖片旋轉(zhuǎn)和縮放功能,在顯示圖片時(shí)需對(duì)其進(jìn)行矩陣運(yùn)算。通過(guò)左右翻轉(zhuǎn)和上下翻轉(zhuǎn),可實(shí)現(xiàn)圖片的旋轉(zhuǎn)功能。通過(guò)計(jì)算圖片與顯示屏幕之間的比例關(guān)系并進(jìn)行縮放,實(shí)現(xiàn)自適應(yīng)居中和圖片的縮放功能。

(3)SD卡

SD卡模塊可通過(guò)SPI接口與STM32芯片進(jìn)行通信,讀取SD卡中的圖片數(shù)據(jù),實(shí)現(xiàn)對(duì)圖片的加載和顯示。

(4)按鍵和觸摸屏

在使用過(guò)程中,用戶可以通過(guò)按鍵和觸摸屏對(duì)圖片進(jìn)行切換、旋轉(zhuǎn)和縮放等操作。通過(guò)設(shè)置中斷處理函數(shù),響應(yīng)用戶的操作并及時(shí)更新顯示屏幕上的圖片。

2.3 圖片播放流程圖

image-20230618135212377

2.4 顯示效果

image-20230618135436038

三、代碼設(shè)計(jì)

3.1 主函數(shù)

#include "stm32f10x.h"
#include "led.h"
#include "delay.h"
#include "key.h"
#include "usart.h"
#include <string.h>
#include <stdio.h>
#include "sd.h" //SD卡
#include "ff.h" //文件系統(tǒng)
#include "bmp.h" //文件系統(tǒng)
#include "iic.h"
#include "at24c02.h"
#include "xpt2046.h"
#include "lcd.h"


FATFS fs;  // 用戶定義的文件系統(tǒng)結(jié)構(gòu)體
int main()
{
	DIR  dir_dp;
	FILINFO file_info;
	u32 sd_size;    //存放SD卡返回的容量
	BeepInit();		  //蜂鳴器初始化
	LedInit();      //LED燈初始化 
	UsartInit(USART1,72,115200);
	KeyInit();     //按鍵初始化
	IICInit();
	LcdInit();
	TOUCH_Init(); 
	//TOUCH_ADJUST(); //觸摸屏校準(zhǔn)
	
	printf("串口工作正常!rn");
	if(SDCardDeviceInit()) 
	{
	   printf("SD卡初始化失敗!rn");
	}
	
	sd_size=GetSDCardSectorCount();	//檢測(cè)SD卡大小,返回值右移11位得到以M為單位的容量
	printf("SD卡Sizeof:%drn",sd_size>>11);
	
  f_mount(&fs,"0:",1);  // 注冊(cè)文件系統(tǒng)工作區(qū),驅(qū)動(dòng)器號(hào) 0,初始化后其他函數(shù)可使用里面的參數(shù)
	LcdClear(0xFFFF);
	
	//f_mkdir("0:/目錄創(chuàng)建測(cè)試!"); //測(cè)試OK
	//f_unlink("0:/123"); //刪除目錄,注意只能刪除空目錄
	//f_unlink("0:/1.bmp");//刪除文件
	//printf("%drn",Show_BMP("1.bmp"));
	
	if(f_opendir(&dir_dp,"0:/bmp")!=FR_OK)printf("目錄打開(kāi)失敗!rn");
	
	//循環(huán)讀取目錄
	while(f_readdir(&dir_dp,&file_info)==FR_OK)
	{
			if(file_info.fname[0]==0)break;    //判斷目錄跳出條件,表示目錄已經(jīng)讀取完畢
			if(strstr(file_info.fname,".bmp")) //過(guò)濾目錄
			{
				 	printf("文件名稱: %s,文件大小: %ld 字節(jié)rn",file_info.fname,file_info.fsize);
			}else 	printf("文件名稱: %s,文件大小: %ld 字節(jié)rn",file_info.fname,file_info.fsize);
	}
	if(f_closedir(&dir_dp)!=FR_OK)printf("目錄關(guān)閉失敗!rn");
	while(1)
	{	
		 LED1=!LED1;
		 DelayMs(100);
	}
}

3.2 BMP圖片解碼

#include "bmp.h"
unsigned short RGB888ToRGB565(unsigned int n888Color)  
{  
    unsigned short n565Color = 0;  
  
    // 獲取RGB單色,并截取高位  
    unsigned char cRed   = (n888Color & RGB888_RED)   >> 19;  
    unsigned char cGreen = (n888Color & RGB888_GREEN) >> 10;  
    unsigned char cBlue  = (n888Color & RGB888_BLUE)  >> 3;  
  
    // 連接  
    n565Color = (cRed << 11) + (cGreen << 5) + (cBlue << 0);  
    return n565Color;  
}  

unsigned int RGB565ToRGB888(unsigned short n565Color)  
{  
    unsigned int n888Color = 0;  
  
    // 獲取RGB單色,并填充低位  
    unsigned char cRed   = (n565Color & RGB565_RED)    >> 8;  
    unsigned char cGreen = (n565Color & RGB565_GREEN)  >> 3;  
    unsigned char cBlue  = (n565Color & RGB565_BLUE)   << 3;  
  
    // 連接  
    n888Color = (cRed << 16) + (cGreen << 8) + (cBlue << 0);  
    return n888Color;  
}  



/*
函數(shù)功能:實(shí)現(xiàn)截圖功能
參    數(shù):
				char filename:文件名稱
返 回 值:0表示成功,1表示失敗
*/
u8 C_BMP(const char *filename,u32 Width,u32 Height)
{
	FIL  file; // 用戶定義的文件系統(tǒng)結(jié)構(gòu)體
	u8   res;  // 保存文件操作的返回值
	BITMAPFILEHEADER BmpHead; //保存圖片文件頭的信息
  BITMAPINFOHEADER BmpInfo; //圖片參數(shù)信息
	char *p;
	u32 cnt,c_32;
	int x,y;
	u16 c_16; //存放16位的顏色
	
	/*1. 創(chuàng)建一張BMP圖片*/
	res = f_open(&file,filename, FA_OPEN_ALWAYS | FA_WRITE);
	if(res!=0)return 1;
	
	/*2. 創(chuàng)建BMP的圖片頭參數(shù)*/
	memset(&BmpHead,0,sizeof(BITMAPFILEHEADER)); //將指定空間賦值為指定的值
	p=(char*)&BmpHead.bfType; //填充BMP圖片的類型
	*p='B';
	*(p+1)='M';

	//BmpHead.bfType=0x4d42;//'B''M'   //0x4d42
	BmpHead.bfSize=Width*Height*3+54;  //圖片的總大小
	BmpHead.bfOffBits=54;              //圖片數(shù)據(jù)的偏移量
  res =f_write(&file,&BmpHead,sizeof(BITMAPFILEHEADER),&cnt);
	if(res!=0)return 1;
	
	/*3. 創(chuàng)建BMP圖片的參數(shù)*/
	memset(&BmpInfo,0,sizeof(BITMAPINFOHEADER));
	BmpInfo.biSize=sizeof(BITMAPINFOHEADER); //當(dāng)前結(jié)構(gòu)體大小
	BmpInfo.biWidth=Width;
	BmpInfo.biHeight=Height;
	BmpInfo.biPlanes=1;
	BmpInfo.biBitCount=24;
	res =f_write(&file,&BmpInfo,sizeof(BITMAPINFOHEADER),&cnt);
	if(res!=0)return 1;
		
	/*4. 讀取LCD屏的顏色數(shù)據(jù),用于創(chuàng)建BMP圖片*/
	for(y=Height-1;y>=0;y--)
	{
		  for(x=0;x<Width;x++)
		  {
			    c_16=LcdReadPoint(x,y); //讀取LCD屏上一個(gè)點(diǎn)的顏色
				  c_32=RGB565ToRGB888(c_16); //顏色的轉(zhuǎn)換
				  res =f_write(&file,&c_32,3,&cnt);
				  if(res!=0)return 1;
			}
	}
	
	/*5. 關(guān)閉文件*/
	f_close(&file);
}


/*
函數(shù)功能:BMP圖片顯示功能
參    數(shù):
				char filename:文件名稱
返 回 值:0表示成功,1表示失敗
*/
u8 Show_BMP(const char *filename)
{
	FIL  file; // 用戶定義的文件系統(tǒng)結(jié)構(gòu)體
	u8   res;  // 保存文件操作的返回值
	BITMAPFILEHEADER BmpHead; //保存圖片文件頭的信息
  BITMAPINFOHEADER BmpInfo; //圖片參數(shù)信息
	char *p;
	u32 cnt,c_24;
	int x,y;
	u16 c_16; //存放16位的顏色
	
	/*1. 打開(kāi)一張BMP圖片*/
	res = f_open(&file,filename,FA_READ);
	if(res!=0)return 1;
	
	/*2. 讀取BMP的圖片頭參數(shù)*/
  res =f_read(&file,&BmpHead,sizeof(BITMAPFILEHEADER),&cnt);
	if(res!=0)return 1;
	
	/*3. 讀取BMP圖片的參數(shù)*/
	res =f_read(&file,&BmpInfo,sizeof(BITMAPINFOHEADER),&cnt);
	if(res!=0)return 1;
	
	/*4.顯示BMP圖片*/
	f_lseek(&file,BmpHead.bfOffBits); //移動(dòng)到RGB數(shù)據(jù)的存放位置
	
	//后期的優(yōu)化:讀取一行的數(shù)據(jù),再顯示一行。
   for(y=0;y<BmpInfo.biHeight;y++)
	 {
			for(x=0;x<BmpInfo.biWidth;x++)
		 {
			    res =f_read(&file,&c_24,3,&cnt);
					if(res!=0)return 1;
			    c_16=RGB888ToRGB565(c_24); //轉(zhuǎn)換顏色
			    LcdDrawPoint(x,y,c_16);
		 }
	 }
	/*5. 關(guān)閉文件*/
	f_close(&file);
}


3.3 jpeg圖片解碼

#include "piclib.h"
#include "nt35310_lcd.h"
_pic_info picinfo;	 	//圖片信息
_pic_phy pic_phy;		  //圖片顯示物理接口	

/*
函數(shù)功能: 劃?rùn)M線函數(shù),需要自己實(shí)現(xiàn)
*/
void Picture_DrawLine(u16 x0,u16 y0,u16 len,u16 color)
{
	NT35310_Fill(x0,y0,x0+len-1,y0,color);	
}

/*
函數(shù)功能: 矩形填充顏色
函數(shù)參數(shù):
		x,y:起始坐標(biāo)
		width,height:寬度和高度。
		color:顏色數(shù)組
*/
void Picture_FillColor(u16 x,u16 y,u16 width,u16 height,u16 *color)
{  
	NT35310_DrawRectangle(x,y,x+width-1,y+height-1,*color);	
}

/*
函數(shù)功能: 畫(huà)圖初始化,在畫(huà)圖之前,必須先調(diào)用此函數(shù)
函數(shù)參數(shù): 指定畫(huà)點(diǎn)/讀點(diǎn)
*/
void Picture_DisplayInit(void)
{
	pic_phy.draw_point=NT35310_DrawPoint;    //畫(huà)點(diǎn)函數(shù)實(shí)現(xiàn)
	pic_phy.fill=NT35310_Fill;					     //填充函數(shù)實(shí)現(xiàn),僅GIF需要
	pic_phy.draw_hline=Picture_DrawLine;  	 //畫(huà)線函數(shù)實(shí)現(xiàn),僅GIF需要
	pic_phy.fillcolor=Picture_FillColor;  	 //顏色填充函數(shù)實(shí)現(xiàn),僅TJPGD需要 
	picinfo.lcdwidth=Lcd_Width;							 //得到LCD的寬度像素
	picinfo.lcdheight=Lcd_Height;						 //得到LCD的高度像素

	picinfo.ImgWidth=0;	//初始化寬度為0
	picinfo.ImgHeight=0;//初始化高度為0
	picinfo.Div_Fac=0;	//初始化縮放系數(shù)為0
	picinfo.S_Height=0;	//初始化設(shè)定的高度為0
	picinfo.S_Width=0;	//初始化設(shè)定的寬度為0
	picinfo.S_XOFF=0;	  //初始化x軸的偏移量為0
	picinfo.S_YOFF=0;	  //初始化y軸的偏移量為0
	picinfo.staticx=0;	//初始化當(dāng)前顯示到的x坐標(biāo)為0
	picinfo.staticy=0;	//初始化當(dāng)前顯示到的y坐標(biāo)為0
}


/*
函數(shù)功能: 初始化智能畫(huà)點(diǎn)
說(shuō)明: 內(nèi)部調(diào)用
*/
void Picture_PointInit(void)
{
	float temp,temp1;	   
	temp=(float)picinfo.S_Width/picinfo.ImgWidth;
	temp1=(float)picinfo.S_Height/picinfo.ImgHeight;						 
	if(temp<temp1)temp1=temp;//取較小的那個(gè)	 
	if(temp1>1)temp1=1;	  
	//使圖片處于所給區(qū)域的中間
	picinfo.S_XOFF+=(picinfo.S_Width-temp1*picinfo.ImgWidth)/2;
	picinfo.S_YOFF+=(picinfo.S_Height-temp1*picinfo.ImgHeight)/2;
	temp1*=8192;//擴(kuò)大8192倍	 
	picinfo.Div_Fac=temp1;
	picinfo.staticx=0xffff;
	picinfo.staticy=0xffff;//放到一個(gè)不可能的值上面			 										    
}  

/*
函數(shù)功能: 判斷這個(gè)像素是否可以顯示
函數(shù)參數(shù):
			(x,y) :像素原始坐標(biāo)
			chg   :功能變量.
返回值:0,不需要顯示.1,需要顯示
*/
u8 Picture_is_Pixel(u16 x,u16 y,u8 chg)
{				  
	if(x!=picinfo.staticx||y!=picinfo.staticy)
	{
		if(chg==1)
		{
			picinfo.staticx=x;
			picinfo.staticy=y;
		} 
		return 1;
	}else return 0;
}

extern u8 jpg_decode(const u8 *filename);

/*
函數(shù)功能: 繪制圖片
函數(shù)參數(shù):
				FileName:要顯示的圖片文件  BMP/JPG/JPEG/GIF
				x,y,width,height:坐標(biāo)及顯示區(qū)域尺寸
				fast:使能jpeg/jpg小圖片(圖片尺寸小于等于液晶分辨率)快速解碼,0,不使能;1,使能.
				函數(shù)說(shuō)明: 圖片在開(kāi)始和結(jié)束的坐標(biāo)點(diǎn)范圍內(nèi)顯示
*/
u8 Picture_DisplayJPG(const u8 *filename,u16 x,u16 y,u16 width,u16 height,u8 fast)
{	
	u8	res;//返回值
	
	//顯示的圖片高度、寬度
	picinfo.S_Height=height;
	picinfo.S_Width=width;

	//顯示的開(kāi)始坐標(biāo)點(diǎn)
	picinfo.S_YOFF=y;
	picinfo.S_XOFF=x;
	
	//解碼JPG/JPEG	  	 
  res=jpg_decode(filename);				//解碼JPG/JPEG	  	  										   
	return res;
}

3.4 gif圖片解碼

#include "piclib.h"
#include <stm32f10x.h>
#include "gif.h"	 
#include "ff.h"	
#include "delay.h"	    
#include <string.h>

const u16 _aMaskTbl[16] =
{
	0x0000, 0x0001, 0x0003, 0x0007,
	0x000f, 0x001f, 0x003f, 0x007f,
	0x00ff, 0x01ff, 0x03ff, 0x07ff,
	0x0fff, 0x1fff, 0x3fff, 0x7fff,
};	  
const u8 _aInterlaceOffset[]={8,8,4,2};
const u8 _aInterlaceYPos  []={0,4,2,1};
 
u8 gifdecoding=0;//標(biāo)記GIF正在解碼.

//檢測(cè)GIF頭
//返回值:0,是GIF89a/87a;非零,非GIF89a/87a
u8 gif_check_head(FIL *file)
{
	u8 gifversion[6];
	u32 readed;
	u8 res;
	res=f_read(file,gifversion,6,(UINT*)&readed);
	if(res)return 1;	   
	if((gifversion[0]!='G')||(gifversion[1]!='I')||(gifversion[2]!='F')||
	(gifversion[3]!='8')||((gifversion[4]!='7')&&(gifversion[4]!='9'))||
	(gifversion[5]!='a'))return 2;
	else return 0;	
}

//將RGB888轉(zhuǎn)為RGB565
//ctb:RGB888顏色數(shù)組首地址.
//返回值:RGB565顏色.
u16 gif_getrgb565(u8 *ctb) 
{
	u16 r,g,b;
	r=(ctb[0]>>3)&0X1F;
	g=(ctb[1]>>2)&0X3F;
	b=(ctb[2]>>3)&0X1F;
	return b+(g<<5)+(r<<11);
}

//讀取顏色表
//file:文件;
//gif:gif信息;
//num:tbl大小.
//返回值:0,OK;其他,失敗;
u8 gif_readcolortbl(FIL *file,gif89a * gif,u16 num)
{
	u8 rgb[3];
	u16 t;
	u8 res;
	u32 readed;
	for(t=0;t<num;t++)
	{
		res=f_read(file,rgb,3,(UINT*)&readed);
		if(res)return 1;//讀錯(cuò)誤
		gif->colortbl[t]=gif_getrgb565(rgb);
	}
	return 0;
} 
//得到邏輯屏幕描述,圖像尺寸等
//file:文件;
//gif:gif信息;
//返回值:0,OK;其他,失敗;
u8 gif_getinfo(FIL *file,gif89a * gif)
{
	u32 readed;	 
	u8 res;   
	res=f_read(file,(u8*)&gif->gifLSD,7,(UINT*)&readed);
	if(res)return 1;
	if(gif->gifLSD.flag&0x80)//存在全局顏色表
	{
		gif->numcolors=2<<(gif->gifLSD.flag&0x07);//得到顏色表大小
		if(gif_readcolortbl(file,gif,gif->numcolors))return 1;//讀錯(cuò)誤	
	}	   
	return 0;
}
//保存全局顏色表	 
//gif:gif信息;
void gif_savegctbl(gif89a* gif)
{
	u16 i=0;
	for(i=0;i<256;i++)gif->bkpcolortbl[i]=gif->colortbl[i];//保存全局顏色.
}
//恢復(fù)全局顏色表	 
//gif:gif信息;
void gif_recovergctbl(gif89a* gif)
{
	u16 i=0;
	for(i=0;i<256;i++)gif->colortbl[i]=gif->bkpcolortbl[i];//恢復(fù)全局顏色.
}

//初始化LZW相關(guān)參數(shù)	   
//gif:gif信息;
//codesize:lzw碼長(zhǎng)度
void gif_initlzw(gif89a* gif,u8 codesize) 
{
 	memset((u8 *)gif->lzw, 0, sizeof(LZW_INFO));
	gif->lzw->SetCodeSize  = codesize;
	gif->lzw->CodeSize     = codesize + 1;
	gif->lzw->ClearCode    = (1 << codesize);
	gif->lzw->EndCode      = (1 << codesize) + 1;
	gif->lzw->MaxCode      = (1 << codesize) + 2;
	gif->lzw->MaxCodeSize  = (1 << codesize) << 1;
	gif->lzw->ReturnClear  = 1;
	gif->lzw->LastByte     = 2;
	gif->lzw->sp           = gif->lzw->aDecompBuffer;
}

//讀取一個(gè)數(shù)據(jù)塊
//gfile:gif文件;
//buf:數(shù)據(jù)緩存區(qū)
//maxnum:最大讀寫(xiě)數(shù)據(jù)限制
u16 gif_getdatablock(FIL *gfile,u8 *buf,u16 maxnum) 
{
	u8 cnt;
	u32 readed;
	u32 fpos;
	f_read(gfile,&cnt,1,(UINT*)&readed);//得到LZW長(zhǎng)度			 
	if(cnt) 
	{
		if (buf)//需要讀取 
		{
			if(cnt>maxnum)
			{
				fpos=f_tell(gfile);
				f_lseek(gfile,fpos+cnt);//跳過(guò)
				return cnt;//直接不讀
			}
			f_read(gfile,buf,cnt,(UINT*)&readed);//得到LZW長(zhǎng)度	
		}else 	//直接跳過(guò)
		{
			fpos=f_tell(gfile);
			f_lseek(gfile,fpos+cnt);//跳過(guò)
		}
	}
	return cnt;
}

//ReadExtension		 
//Purpose:
//Reads an extension block. One extension block can consist of several data blocks.
//If an unknown extension block occures, the routine failes.
//返回值:0,成功;
// 		 其他,失敗
u8 gif_readextension(FIL *gfile,gif89a* gif, int *pTransIndex,u8 *pDisposal)
{
	u8 temp;
	u32 readed;	 
	u8 buf[4];  
	f_read(gfile,&temp,1,(UINT*)&readed);//得到長(zhǎng)度		 
	switch(temp)
	{
		case GIF_PLAINTEXT:
		case GIF_APPLICATION:
		case GIF_COMMENT:
			while(gif_getdatablock(gfile,0,256)>0);			//獲取數(shù)據(jù)塊
			return 0;
		case GIF_GRAPHICCTL://圖形控制擴(kuò)展塊
			if(gif_getdatablock(gfile,buf,4)!=4)return 1;	//圖形控制擴(kuò)展塊的長(zhǎng)度必須為4 
 		 	gif->delay=(buf[2]<<8)|buf[1];					//得到延時(shí) 
			*pDisposal=(buf[0]>>2)&0x7; 	    			//得到處理方法
			if((buf[0]&0x1)!=0)*pTransIndex=buf[3];			//透明色表 
			f_read(gfile,&temp,1,(UINT*)&readed);	 		//得到LZW長(zhǎng)度	
 			if(temp!=0)return 1;							//讀取數(shù)據(jù)塊結(jié)束符錯(cuò)誤.
			return 0;
	}
	return 1;//錯(cuò)誤的數(shù)據(jù)
}

//從LZW緩存中得到下一個(gè)LZW碼,每個(gè)碼包含12位
//返回值:<0,錯(cuò)誤.
//		 其他,正常.
int gif_getnextcode(FIL *gfile,gif89a* gif) 
{
	int i,j,End;
	long Result;
	if(gif->lzw->ReturnClear)
	{
		//The first code should be a clearcode.
		gif->lzw->ReturnClear=0;
		return gif->lzw->ClearCode;
	}
	End=gif->lzw->CurBit+gif->lzw->CodeSize;
	if(End>=gif->lzw->LastBit)
	{
		int Count;
		if(gif->lzw->GetDone)return-1;//Error 
		gif->lzw->aBuffer[0]=gif->lzw->aBuffer[gif->lzw->LastByte-2];
		gif->lzw->aBuffer[1]=gif->lzw->aBuffer[gif->lzw->LastByte-1];
		if((Count=gif_getdatablock(gfile,&gif->lzw->aBuffer[2],300))==0)gif->lzw->GetDone=1;
		if(Count<0)return -1;//Error 
		gif->lzw->LastByte=2+Count;
		gif->lzw->CurBit=(gif->lzw->CurBit-gif->lzw->LastBit)+16;
		gif->lzw->LastBit=(2+Count)*8;
		End=gif->lzw->CurBit+gif->lzw->CodeSize;
	}
	j=End>>3;
	i=gif->lzw->CurBit>>3;
	if(i==j)Result=(long)gif->lzw->aBuffer[i];
	else if(i+1==j)Result=(long)gif->lzw->aBuffer[i]|((long)gif->lzw->aBuffer[i+1]<<8);
	else Result=(long)gif->lzw->aBuffer[i]|((long)gif->lzw->aBuffer[i+1]<<8)|((long)gif->lzw->aBuffer[i+2]<<16);
	Result=(Result>>(gif->lzw->CurBit&0x7))&_aMaskTbl[gif->lzw->CodeSize];
	gif->lzw->CurBit+=gif->lzw->CodeSize;
	return(int)Result;
}


//得到LZW的下一個(gè)碼
//返回值:<0,錯(cuò)誤(-1,不成功;-2,讀到結(jié)束符了)
//		 >=0,OK.(LZW的第一個(gè)碼)
int gif_getnextbyte(FIL *gfile,gif89a* gif) 
{
	int i,Code,Incode;
	while((Code=gif_getnextcode(gfile,gif))>=0)
	{
		if(Code==gif->lzw->ClearCode)
		{
			//Corrupt GIFs can make this happen  
			if(gif->lzw->ClearCode>=(1<<MAX_NUM_LWZ_BITS))return -1;//Error 
			//Clear the tables 
			memset((u8*)gif->lzw->aCode,0,sizeof(gif->lzw->aCode));
			for(i=0;i<gif->lzw->ClearCode;++i)gif->lzw->aPrefix[i]=i;
			//Calculate the'special codes' independence of the initial code size
			//and initialize the stack pointer 
			gif->lzw->CodeSize=gif->lzw->SetCodeSize+1;
			gif->lzw->MaxCodeSize=gif->lzw->ClearCode<<1;
			gif->lzw->MaxCode=gif->lzw->ClearCode+2;
			gif->lzw->sp=gif->lzw->aDecompBuffer;
			//Read the first code from the stack after clear ingand initializing*/
			do
			{
				gif->lzw->FirstCode=gif_getnextcode(gfile,gif);
			}while(gif->lzw->FirstCode==gif->lzw->ClearCode);
			gif->lzw->OldCode=gif->lzw->FirstCode;
			return gif->lzw->FirstCode;
		}
		if(Code==gif->lzw->EndCode)return -2;//End code
		Incode=Code;
		if(Code>=gif->lzw->MaxCode)
		{
			*(gif->lzw->sp)++=gif->lzw->FirstCode;
			Code=gif->lzw->OldCode;
		}
		while(Code>=gif->lzw->ClearCode)
		{
			*(gif->lzw->sp)++=gif->lzw->aPrefix[Code];
			if(Code==gif->lzw->aCode[Code])return Code;
			if((gif->lzw->sp-gif->lzw->aDecompBuffer)>=sizeof(gif->lzw->aDecompBuffer))return Code;
			Code=gif->lzw->aCode[Code];
		}
		*(gif->lzw->sp)++=gif->lzw->FirstCode=gif->lzw->aPrefix[Code];
		if((Code=gif->lzw->MaxCode)<(1<<MAX_NUM_LWZ_BITS))
		{
			gif->lzw->aCode[Code]=gif->lzw->OldCode;
			gif->lzw->aPrefix[Code]=gif->lzw->FirstCode;
			++gif->lzw->MaxCode;
			if((gif->lzw->MaxCode>=gif->lzw->MaxCodeSize)&&(gif->lzw->MaxCodeSize<(1<<MAX_NUM_LWZ_BITS)))
			{
				gif->lzw->MaxCodeSize<<=1;
				++gif->lzw->CodeSize;
			}
		}
		gif->lzw->OldCode=Incode;
		if(gif->lzw->sp>gif->lzw->aDecompBuffer)return *--(gif->lzw->sp);
	}
	return Code;
}
//DispGIFImage		 
//Purpose:
//   This routine draws a GIF image from the current pointer which should point to a
//   valid GIF data block. The size of the desired image is given in the image descriptor.
//Return value:
//  0 if succeed
//  1 if not succeed
//Parameters:
//  pDescriptor  - Points to a IMAGE_DESCRIPTOR structure, which contains infos about size, colors and interlacing.
//  x0, y0       - Obvious.
//  Transparency - Color index which should be treated as transparent.
//  Disposal     - Contains the disposal method of the previous image. If Disposal == 2, the transparent pixels
//                 of the image are rendered with the background color.
u8 gif_dispimage(FIL *gfile,gif89a* gif,u16 x0,u16 y0,int Transparency, u8 Disposal) 
{
	u32 readed;	   
  u8 lzwlen;
	int Index,OldIndex,XPos,YPos,YCnt,Pass,Interlace,XEnd;
	int Width,Height,Cnt,ColorIndex;
	u16 bkcolor;
	u16 *pTrans;

	Width=gif->gifISD.width;
	Height=gif->gifISD.height;
	XEnd=Width+x0-1;
	bkcolor=gif->colortbl[gif->gifLSD.bkcindex];
	pTrans=(u16*)gif->colortbl;
	f_read(gfile,&lzwlen,1,(UINT*)&readed);//得到LZW長(zhǎng)度	 
	gif_initlzw(gif,lzwlen);//Initialize the LZW stack with the LZW code size 
	Interlace=gif->gifISD.flag&0x40;//是否交織編碼
	for(YCnt=0,YPos=y0,Pass=0;YCnt<Height;YCnt++)
	{
		Cnt=0;
		OldIndex=-1;
		for(XPos=x0;XPos<=XEnd;XPos++)
		{
			if(gif->lzw->sp>gif->lzw->aDecompBuffer)Index=*--(gif->lzw->sp);
		    else Index=gif_getnextbyte(gfile,gif);	   
			if(Index==-2)return 0;//Endcode     
			if((Index<0)||(Index>=gif->numcolors))
			{
				//IfIndex out of legal range stop decompressing
				return 1;//Error
			}
			//If current index equals old index increment counter
			if((Index==OldIndex)&&(XPos<=XEnd))Cnt++;
	 		else
			{
				if(Cnt)
				{
					if(OldIndex!=Transparency)
					{									    
						pic_phy.draw_hline(XPos-Cnt-1,YPos,Cnt+1,*(pTrans+OldIndex));
					}else if(Disposal==2)
					{
						pic_phy.draw_hline(XPos-Cnt-1,YPos,Cnt+1,bkcolor);
					}
					Cnt=0;
				}else
				{
					if(OldIndex>=0)
					{
						if(OldIndex!=Transparency)pic_phy.draw_point(XPos-1,YPos,*(pTrans+OldIndex));
					 	else if(Disposal==2)pic_phy.draw_point(XPos-1,YPos,bkcolor); 
					}
				}
			}
			OldIndex=Index;
		}
		if((OldIndex!=Transparency)||(Disposal==2))
		{
			if(OldIndex!=Transparency)ColorIndex=*(pTrans+OldIndex);
		  else ColorIndex=bkcolor;
	 		if(Cnt)
			{
				pic_phy.draw_hline(XPos-Cnt-1,YPos,Cnt+1,ColorIndex);
			}else pic_phy.draw_point(XEnd,YPos,ColorIndex);	 
		}
		//Adjust YPos if image is interlaced 
		if(Interlace)//交織編碼
		{
			YPos+=_aInterlaceOffset[Pass];
			if((YPos-y0)>=Height)
			{
				++Pass;
				YPos=_aInterlaceYPos[Pass]+y0;
			}
		}else YPos++;	    
	}
	return 0;
}


/*
函數(shù)功能: 恢復(fù)成背景色
函數(shù)參數(shù):
					x,y:坐標(biāo)
					gif:gif信息.
					pimge:圖像描述塊信息
*/
void gif_clear2bkcolor(u16 x,u16 y,gif89a* gif,ImageScreenDescriptor pimge)
{
	u16 x0,y0,x1,y1;
	u16 color=gif->colortbl[gif->gifLSD.bkcindex];
	if(pimge.width==0||pimge.height==0)return;//直接不用清除了,原來(lái)沒(méi)有圖像!!
	if(gif->gifISD.yoff>pimge.yoff)
	{
   		x0=x+pimge.xoff;
		y0=y+pimge.yoff;
		x1=x+pimge.xoff+pimge.width-1;;
		y1=y+gif->gifISD.yoff-1;
		if(x0<x1&&y0<y1&&x1<320&&y1<320)pic_phy.fill(x0,y0,x1,y1,color); //設(shè)定xy,的范圍不能太大.
	}
	if(gif->gifISD.xoff>pimge.xoff)
	{
   		x0=x+pimge.xoff;
		y0=y+pimge.yoff;
		x1=x+gif->gifISD.xoff-1;;
		y1=y+pimge.yoff+pimge.height-1;
		if(x0<x1&&y0<y1&&x1<320&&y1<320)pic_phy.fill(x0,y0,x1,y1,color);
	}
	if((gif->gifISD.yoff+gif->gifISD.height)<(pimge.yoff+pimge.height))
	{
   		x0=x+pimge.xoff;
		y0=y+gif->gifISD.yoff+gif->gifISD.height-1;
		x1=x+pimge.xoff+pimge.width-1;;
		y1=y+pimge.yoff+pimge.height-1;
		if(x0<x1&&y0<y1&&x1<320&&y1<320)pic_phy.fill(x0,y0,x1,y1,color);
	}
 	if((gif->gifISD.xoff+gif->gifISD.width)<(pimge.xoff+pimge.width))
	{
   		x0=x+gif->gifISD.xoff+gif->gifISD.width-1;
		y0=y+pimge.yoff;
		x1=x+pimge.xoff+pimge.width-1;;
		y1=y+pimge.yoff+pimge.height-1;
		if(x0<x1&&y0<y1&&x1<320&&y1<320)pic_phy.fill(x0,y0,x1,y1,color);
	}   
}


/*
函數(shù)功能: 畫(huà)GIF圖像的一幀
函數(shù)參數(shù):
				gfile:gif文件
				x0,y0:開(kāi)始顯示的坐標(biāo)
*/
u8 gif_drawimage(FIL *gfile,gif89a* gif,u16 x0,u16 y0)
{		  
	u32 readed;
	u8 res,temp;    
	u16 numcolors;
	ImageScreenDescriptor previmg;

	u8 Disposal;
	int TransIndex;
	u8 Introducer;
	TransIndex=-1;				  
	do
	{
		res=f_read(gfile,&Introducer,1,(UINT*)&readed);//讀取一個(gè)字節(jié)
		if(res)return 1;   
		switch(Introducer)
		{		 
			case GIF_INTRO_IMAGE://圖像描述
				previmg.xoff=gif->gifISD.xoff;
 				previmg.yoff=gif->gifISD.yoff;
				previmg.width=gif->gifISD.width;
				previmg.height=gif->gifISD.height;

				res=f_read(gfile,(u8*)&gif->gifISD,9,(UINT*)&readed);//讀取一個(gè)字節(jié)
				if(res)return 1;			 
				if(gif->gifISD.flag&0x80)//存在局部顏色表
				{							  
					gif_savegctbl(gif);//保存全局顏色表
					numcolors=2<<(gif->gifISD.flag&0X07);//得到局部顏色表大小
					if(gif_readcolortbl(gfile,gif,numcolors))return 1;//讀錯(cuò)誤	
				}
				if(Disposal==2)gif_clear2bkcolor(x0,y0,gif,previmg); 
				gif_dispimage(gfile,gif,x0+gif->gifISD.xoff,y0+gif->gifISD.yoff,TransIndex,Disposal);
 				while(1)
				{
					f_read(gfile,&temp,1,(UINT*)&readed);//讀取一個(gè)字節(jié)
					if(temp==0)break;
					readed=f_tell(gfile);//還存在塊.	
					if(f_lseek(gfile,readed+temp))break;//繼續(xù)向后偏移	 
			  }
				if(temp!=0)return 1;//Error 
				return 0;
			case GIF_INTRO_TERMINATOR://得到結(jié)束符了
				return 2;								//代表圖像解碼完成了.
			case GIF_INTRO_EXTENSION:
				res=gif_readextension(gfile,gif,&TransIndex,&Disposal);//讀取圖像擴(kuò)展塊消息
				if(res)return 1;
	 			break;
			default:
				return 1;
		}
	}while(Introducer!=GIF_INTRO_TERMINATOR);//讀到結(jié)束符了
	return 0;
}


/*
函數(shù)功能: 退出當(dāng)前解碼
*/
void gif_quit(void)
{
	gifdecoding=0;
}


/*
函數(shù)功能: 解碼一個(gè)gif文件
函數(shù)參數(shù):
			filename:帶路徑的gif文件名字
			x,y,width,height:顯示坐標(biāo)及區(qū)域大小.
*/
u8 gif_decode(const u8 *filename,u16 x,u16 y,u16 width,u16 height)
{
	u8 res=0;
	u16 dtime=0;//解碼延時(shí)
	gif89a *mygif89a;
	FIL *gfile;
	gfile=(FIL*)SRAM_Malloc(sizeof(FIL));
	if(gfile==NULL)res=PIC_MEM_ERR;//申請(qǐng)內(nèi)存失敗 
	mygif89a=(gif89a*)SRAM_Malloc(sizeof(gif89a));
	if(mygif89a==NULL)res=PIC_MEM_ERR;//申請(qǐng)內(nèi)存失敗    
	mygif89a->lzw=(LZW_INFO*)SRAM_Malloc(sizeof(LZW_INFO));
	if(mygif89a->lzw==NULL)res=PIC_MEM_ERR;//申請(qǐng)內(nèi)存失敗 
	if(res==0)//OK
	{
		res=f_open(gfile,(TCHAR *)filename,FA_READ);
		if(res==0)//打開(kāi)文件ok
		{
			if(gif_check_head(gfile))res=PIC_FORMAT_ERR;
			if(gif_getinfo(gfile,mygif89a))res=PIC_FORMAT_ERR;
			if(mygif89a->gifLSD.width>width||mygif89a->gifLSD.height>height)res=PIC_SIZE_ERR;//尺寸太大.
			else
			{
				x=(width-mygif89a->gifLSD.width)/2+x;
				y=(height-mygif89a->gifLSD.height)/2+y;
			}
			gifdecoding=1;
			while(gifdecoding&&res==0)//解碼循環(huán)
			{	 
				res=gif_drawimage(gfile,mygif89a,x,y);//顯示一張圖片
				if(mygif89a->gifISD.flag&0x80)gif_recovergctbl(mygif89a);//恢復(fù)全局顏色表
				if(mygif89a->delay)dtime=mygif89a->delay;
				else dtime=10;//默認(rèn)延時(shí)
				while(dtime--&&gifdecoding)delay_ms(10);//延遲
				if(res==2)
				{
					res=0;
					break;
				}
			}
		}
		f_close(gfile);
	}
	SRAM_Free(gfile);
	SRAM_Free(mygif89a->lzw);
	SRAM_Free(mygif89a); 
	return res;
}

  • 更多詳細(xì)資料請(qǐng)聯(lián)系.docx
    下載
意法半導(dǎo)體

意法半導(dǎo)體

意法半導(dǎo)體(ST)集團(tuán)于1987年6月成立,是由意大利的SGS微電子公司和法國(guó)Thomson半導(dǎo)體公司合并而成。1998年5月,SGS-THOMSON Microelectronics將公司名稱改為意法半導(dǎo)體有限公司。意法半導(dǎo)體是世界最大的半導(dǎo)體公司之一,公司銷售收入在半導(dǎo)體工業(yè)五大高速增長(zhǎng)市場(chǎng)之間分布均衡(五大市場(chǎng)占2007年銷售收入的百分比):通信(35%),消費(fèi)(17%),計(jì)算機(jī)(16%),汽車(16%),工業(yè)(16%)。 據(jù)最新的工業(yè)統(tǒng)計(jì)數(shù)據(jù),意法半導(dǎo)體是全球第五大半導(dǎo)體廠商,在很多市場(chǎng)居世界領(lǐng)先水平。例如,意法半導(dǎo)體是世界第一大專用模擬芯片和電源轉(zhuǎn)換芯片制造商,世界第一大工業(yè)半導(dǎo)體和機(jī)頂盒芯片供應(yīng)商,而且在分立器件、手機(jī)相機(jī)模塊和車用集成電路領(lǐng)域居世界前列.

意法半導(dǎo)體(ST)集團(tuán)于1987年6月成立,是由意大利的SGS微電子公司和法國(guó)Thomson半導(dǎo)體公司合并而成。1998年5月,SGS-THOMSON Microelectronics將公司名稱改為意法半導(dǎo)體有限公司。意法半導(dǎo)體是世界最大的半導(dǎo)體公司之一,公司銷售收入在半導(dǎo)體工業(yè)五大高速增長(zhǎng)市場(chǎng)之間分布均衡(五大市場(chǎng)占2007年銷售收入的百分比):通信(35%),消費(fèi)(17%),計(jì)算機(jī)(16%),汽車(16%),工業(yè)(16%)。 據(jù)最新的工業(yè)統(tǒng)計(jì)數(shù)據(jù),意法半導(dǎo)體是全球第五大半導(dǎo)體廠商,在很多市場(chǎng)居世界領(lǐng)先水平。例如,意法半導(dǎo)體是世界第一大專用模擬芯片和電源轉(zhuǎn)換芯片制造商,世界第一大工業(yè)半導(dǎo)體和機(jī)頂盒芯片供應(yīng)商,而且在分立器件、手機(jī)相機(jī)模塊和車用集成電路領(lǐng)域居世界前列.收起

查看更多

相關(guān)推薦

方案定制

去合作
方案開(kāi)發(fā)定制化,2000+方案商即時(shí)響應(yīng)!