⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jpeg.c

📁 JPEG基本系统的解码器
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <windows.h>

#include "jpeg.h"

//////////////////////////////////////////////////////////////////////////////

#define WIDTHBYTES(i)    ((i+31)/32*4)

#define FUNC_OK 0

#define FUNC_MEMORY_ERROR 1

#define FUNC_FILE_ERROR 2

#define FUNC_FORMAT_ERROR 3

typedef short FUNCRET;

////////////////////////////////////////////////////////////////////////////

void    DecodeJPG(HWND hWnd,char *fn,HGLOBAL *hbi);

void 	InitTable();

void 	showerror(FUNCRET funcret);

FUNCRET InitTag();

FUNCRET Decode();

FUNCRET DecodeMCUBlock();

FUNCRET HufBlock(BYTE dchufindex,BYTE achufindex);

FUNCRET DecodeElement();

void 	IQtIZzMCUComponent(short flag);

void IQtIZzBlock(short  *s ,int * d,short flag);

void  	GetYUV(short flag);

void    StoreBuffer();

BYTE    ReadByte();

void 	DispABand();

void 	GetJPGSize(char *fn);

void 	Initialize_Fast_IDCT();

void 	Fast_IDCT(int * block);

static void idctrow(int * blk);

static void idctcol(int * blk);

////////////////////////////////////////////////////////////////////////////

extern  int imgheight,imgwidth;

static  long iclip[1024];

static  long *iclp;

////////////////////////////////////////////////////////////////////////////

HFILE   hfjpg;

unsigned char  *lpbi;

DWORD   bibufsize;

DWORD   linesize;



HGLOBAL hjpgbuf;

unsigned char  *lpjpgbuf;

unsigned char  *lp;

DWORD   jpgbufsize;



short     SampRate_Y_H,SampRate_Y_V;

short     SampRate_U_H,SampRate_U_V;

short     SampRate_V_H,SampRate_V_V;

short     H_YtoU,V_YtoU,H_YtoV,V_YtoV;

short     Y_in_MCU,U_in_MCU,V_in_MCU;



short     sizei,sizej;



short 	restart;



short     qt_table[3][64];



short     comp_num;

BYTE    comp_index[3];



BYTE    YDcIndex,YAcIndex,UVDcIndex,UVAcIndex;

BYTE    HufTabIndex;



short     *YQtTable,*UQtTable,*VQtTable;

BYTE    And[9]={0,1,3,7,0xf,0x1f,0x3f,0x7f,0xff};



short     code_pos_table[4][16],code_len_table[4][16];

unsigned short code_value_table[4][256];

unsigned short huf_max_value[4][16],huf_min_value[4][16];



short     BitPos,CurByte;

short     rrun,vvalue;

short    MCUBuffer[10*64];

int   QtZzMCUBuffer[10*64];

short    BlockBuffer[64];

short    ycoef,ucoef,vcoef;

BOOL    IntervalFlag;



	short  interval=0;

int    Y[4*64],U[4*64],V[4*64];



HGLOBAL  hbiband;

unsigned char  *lpbibandheader;

unsigned char  *lpbibandbits;

DWORD    bibandsize;

HWND     hwnd;

////////////////////////////////////////////////////////////////////////////

void DecodeJPG(HWND hWnd,char *fn,HGLOBAL *hbi)

{

	 FUNCRET  funcret;

	 BITMAPINFOHEADER bi;

	 char *pbi;

	 short  i,j;



	 hwnd=hWnd;

	 if((hfjpg=_lopen(fn,OF_READ))==HFILE_ERROR)

		{

		showerror(FUNC_FILE_ERROR);

		*hbi=NULL;

		return ;

		}



	 //get jpg file length

	 jpgbufsize=_llseek(hfjpg,0L,SEEK_END);



	 //rewind to the beginning of the file

	 _llseek(hfjpg,0L,SEEK_SET);



	if((hjpgbuf=GlobalAlloc(GHND,jpgbufsize))==NULL)

		{

		_lclose(hfjpg);

		showerror(FUNC_MEMORY_ERROR);

		*hbi=NULL;

		return ;

			}

	lpjpgbuf=(unsigned char  *)GlobalLock(hjpgbuf);



	_hread(hfjpg,(unsigned char  *)lpjpgbuf,jpgbufsize);

	_lclose(hfjpg);



	 InitTable();



	 if((funcret=InitTag())!=FUNC_OK)

		{

		GlobalUnlock(hjpgbuf);

		GlobalFree(hjpgbuf);

		showerror(funcret);

		*hbi=NULL;

		return ;

		}



		bi.biSize=(DWORD)sizeof(BITMAPINFOHEADER);

		bi.biWidth=(LONG)(imgwidth);

		bi.biHeight=(LONG)(imgheight);

		bi.biPlanes=1;

		bi.biBitCount=24;

		bi.biClrUsed=0;

	bi.biClrImportant=0;



	bi.biCompression=BI_RGB;

	linesize=WIDTHBYTES(bi.biWidth*bi.biBitCount);

	 bi.biSizeImage=(DWORD)linesize*bi.biHeight;

	 bibufsize=bi.biSizeImage+sizeof(BITMAPINFOHEADER);

		bi.biXPelsPerMeter=0;

	 bi.biYPelsPerMeter=0;



	if((*hbi=GlobalAlloc(GHND,bibufsize))==NULL)

		{

		GlobalUnlock(hjpgbuf);

			GlobalFree(hjpgbuf);

		showerror(FUNC_MEMORY_ERROR);

		*hbi=NULL;

		return ;

		}

	lpbi=(unsigned char  *)GlobalLock(*hbi);

	 pbi=(char *)&bi;



	 for(i=0;i<sizeof(bi);i++)

		*lpbi++=*pbi++;



	bibandsize=linesize*8*SampRate_Y_V+sizeof(BITMAPINFOHEADER);

	if((hbiband=GlobalAlloc(GHND,bibandsize))==NULL)

		{

		GlobalUnlock(hjpgbuf);

			GlobalFree(hjpgbuf);

		GlobalUnlock(*hbi);

		GlobalFree(*hbi);

		showerror(FUNC_MEMORY_ERROR);

		*hbi=NULL;

		return ;

		}

	lpbibandheader=(unsigned char  *)GlobalLock(hbiband);

	lpbibandbits=lpbibandheader;



	 bi.biHeight=8*SampRate_Y_V;

	 pbi=(char *)&bi;



	 for(i=0;i<sizeof(bi);i++)

		*lpbibandbits++=*pbi++;



	lpbibandbits--;



	if((SampRate_Y_H==0)||(SampRate_Y_V==0))

		{

		GlobalUnlock(hjpgbuf);

			GlobalFree(hjpgbuf);

		GlobalUnlock(*hbi);

		GlobalFree(*hbi);

		GlobalUnlock(hbiband);

		GlobalFree(hbiband);

		*hbi=NULL;

			showerror(FUNC_FORMAT_ERROR);

			return ;

			}



	i=imgwidth/(SampRate_Y_H*8);

	j=imgwidth%(SampRate_Y_H*8);



	funcret=Decode();

	if(funcret==FUNC_OK)

		{

			GlobalUnlock(hjpgbuf);

			GlobalFree(hjpgbuf);

		GlobalUnlock(hbiband);

		GlobalFree(hbiband);

		GlobalUnlock(*hbi);

		return ;

		}

	else

		{

			GlobalUnlock(hjpgbuf);

			GlobalFree(hjpgbuf);

		GlobalUnlock(*hbi);

		GlobalFree(*hbi);

		GlobalUnlock(hbiband);

		GlobalFree(hbiband);

		*hbi=NULL;

		showerror(funcret);

		return ;

		}

}

////////////////////////////////////////////////////////////////////////////////

FUNCRET InitTag()

{

	BOOL finish=FALSE;

	BYTE id;

	short  llength;

	short  i,j,k;

	short  huftab1,huftab2;

	short  huftabindex;

	BYTE hf_table_index;

	BYTE qt_table_index;

	BYTE comnum;



	unsigned char  *lptemp;

	short  ccount;



	lp=lpjpgbuf+2;



	while (!finish)

		{

		id=*(lp+1);

		lp+=2;

		switch (id)

			{

			case M_APP0:

				llength=MAKEWORD(*(lp+1),*lp);

				lp+=llength;

				break;

			case M_DQT:

				llength=MAKEWORD(*(lp+1),*lp);

				qt_table_index=(*(lp+2))&0x0f;

				lptemp=lp+3;

				if(llength<80)

					{

					for(i=0;i<64;i++)

						qt_table[qt_table_index][i]=(short)*(lptemp++);

					}

				else

					{

					for(i=0;i<64;i++)

						qt_table[qt_table_index][i]=(short)*(lptemp++);

                    qt_table_index=(*(lptemp++))&0x0f;

  					for(i=0;i<64;i++)

						qt_table[qt_table_index][i]=(short)*(lptemp++);

  					}

  				lp+=llength;		

				break;

			case M_SOF0:

	 			llength=MAKEWORD(*(lp+1),*lp);

	 			imgheight=MAKEWORD(*(lp+4),*(lp+3));

	 			imgwidth=MAKEWORD(*(lp+6),*(lp+5));

                comp_num=*(lp+7);

					 if((comp_num!=1)&&(comp_num!=3))

	  				return FUNC_FORMAT_ERROR;

				if(comp_num==3)

					{

					comp_index[0]=*(lp+8);

	  				SampRate_Y_H=(*(lp+9))>>4;

	  				SampRate_Y_V=(*(lp+9))&0x0f;

	  				YQtTable=(short *)qt_table[*(lp+10)];



					comp_index[1]=*(lp+11);

					SampRate_U_H=(*(lp+12))>>4;

	  				SampRate_U_V=(*(lp+12))&0x0f;

	  				UQtTable=(short *)qt_table[*(lp+13)];



	  				comp_index[2]=*(lp+14);

	  				SampRate_V_H=(*(lp+15))>>4;

	  				SampRate_V_V=(*(lp+15))&0x0f;

					VQtTable=(short *)qt_table[*(lp+16)];

	  				}

			  	else 

					{

	  				comp_index[0]=*(lp+8);

					SampRate_Y_H=(*(lp+9))>>4;

	  				SampRate_Y_V=(*(lp+9))&0x0f;

	  				YQtTable=(short *)qt_table[*(lp+10)];



					comp_index[1]=*(lp+8);

	  				SampRate_U_H=1;

	  				SampRate_U_V=1;

	  				UQtTable=(short *)qt_table[*(lp+10)];



					comp_index[2]=*(lp+8);

					SampRate_V_H=1;

	  				SampRate_V_V=1;

	  				VQtTable=(short *)qt_table[*(lp+10)];

					 }

  				lp+=llength;						    

				break;

			case M_DHT:             

				llength=MAKEWORD(*(lp+1),*lp);

				if (llength<0xd0)

	  				{

					huftab1=(short)(*(lp+2))>>4;     //huftab1=0,1

		 			huftab2=(short)(*(lp+2))&0x0f;   //huftab2=0,1

					huftabindex=huftab1*2+huftab2;

		 			lptemp=lp+3;

					for (i=0; i<16; i++)

						code_len_table[huftabindex][i]=(short)(*(lptemp++));

					j=0;

					for (i=0; i<16; i++)

						if(code_len_table[huftabindex][i]!=0)

							{

							k=0;

							while(k<code_len_table[huftabindex][i])

								{

								code_value_table[huftabindex][k+j]=(short)(*(lptemp++));

								k++;

								}

							j+=k;	

							}

					i=0;

					while (code_len_table[huftabindex][i]==0)

		 				i++;

				    for (j=0;j<i;j++)

				    	{

						huf_min_value[huftabindex][j]=0;

						huf_max_value[huftabindex][j]=0;

						}

					huf_min_value[huftabindex][i]=0;

					huf_max_value[huftabindex][i]=code_len_table[huftabindex][i]-1;

					for (j=i+1;j<16;j++)

						{

						huf_min_value[huftabindex][j]=(huf_max_value[huftabindex][j-1]+1)<<1;

						huf_max_value[huftabindex][j]=huf_min_value[huftabindex][j]+code_len_table[huftabindex][j]-1;

						}

						  code_pos_table[huftabindex][0]=0;

					for (j=1;j<16;j++)

		  				code_pos_table[huftabindex][j]=code_len_table[huftabindex][j-1]+code_pos_table[huftabindex][j-1];

		  			lp+=llength;

					}  //if

				else

	 				{

	 				hf_table_index=*(lp+2);

					lp+=2;

					while (hf_table_index!=0xff)

	  					{

						huftab1=(short)hf_table_index>>4;     //huftab1=0,1

			 			huftab2=(short)hf_table_index&0x0f;   //huftab2=0,1

						huftabindex=huftab1*2+huftab2;

						lptemp=lp+1;

						

						ccount=0;



						for (i=0; i<16; i++)

							{

							code_len_table[huftabindex][i]=(short)(*(lptemp++));

							ccount+=code_len_table[huftabindex][i];

							}



						ccount+=17;	

						j=0;

						for (i=0; i<16; i++)

							if(code_len_table[huftabindex][i]!=0)

								{

								k=0;

								while(k<code_len_table[huftabindex][i])

									{

									code_value_table[huftabindex][k+j]=(short)(*(lptemp++));

									k++;

									}

								j+=k;

								}

						i=0;

						while (code_len_table[huftabindex][i]==0)

							i++;

						 for (j=0;j<i;j++)

							{

							huf_min_value[huftabindex][j]=0;

							huf_max_value[huftabindex][j]=0;

							}

						huf_min_value[huftabindex][i]=0;

						huf_max_value[huftabindex][i]=code_len_table[huftabindex][i]-1;

						for (j=i+1;j<16;j++)

							{

							huf_min_value[huftabindex][j]=(huf_max_value[huftabindex][j-1]+1)<<1;

							huf_max_value[huftabindex][j]=huf_min_value[huftabindex][j]+code_len_table[huftabindex][j]-1;

							}

							  code_pos_table[huftabindex][0]=0;

						for (j=1;j<16;j++)

							code_pos_table[huftabindex][j]=code_len_table[huftabindex][j-1]+code_pos_table[huftabindex][j-1];

						lp+=ccount;

						hf_table_index=*lp;

						}  //while

					}  //else

				break;



			case M_DRI:

				 llength=MAKEWORD(*(lp+1),*lp);

			    restart=MAKEWORD(*(lp+3),*(lp+2));

			    lp+=llength;

				break;



			case M_SOS:

				llength=MAKEWORD(*(lp+1),*lp);

				comnum=*(lp+2);

				if(comnum!=comp_num)

					return FUNC_FORMAT_ERROR;

				lptemp=lp+3;

				for (i=0;i<comp_num;i++)

					{

					if(*lptemp==comp_index[0])

						{

						YDcIndex=(*(lptemp+1))>>4;   //Y

						YAcIndex=((*(lptemp+1))&0x0f)+2;

						}

					else

						{

						UVDcIndex=(*(lptemp+1))>>4;   //U,V

						UVAcIndex=((*(lptemp+1))&0x0f)+2;

						}

					lptemp+=2;

					}

				lp+=llength;

				finish=TRUE;

				break;

			

			case M_EOI:    

				return FUNC_FORMAT_ERROR;

				break;

			default:

	 			if ((id&0xf0)!=0xd0)

					{

					llength=MAKEWORD(*(lp+1),*lp);

	 				lp+=llength;

					}

				else 

					lp+=2;

				break;

  			}  //switch

		} //while

	return FUNC_OK;

}

/////////////////////////////////////////////////////////////////////////

FUNCRET Decode()

{

	FUNCRET funcret;



	Y_in_MCU=SampRate_Y_H*SampRate_Y_V;

	U_in_MCU=SampRate_U_H*SampRate_U_V;

	V_in_MCU=SampRate_V_H*SampRate_V_V;



	H_YtoU=SampRate_Y_H/SampRate_U_H;

	V_YtoU=SampRate_Y_V/SampRate_U_V;

	H_YtoV=SampRate_Y_H/SampRate_V_H;

	V_YtoV=SampRate_Y_V/SampRate_V_V;



	Initialize_Fast_IDCT();



	while((funcret=DecodeMCUBlock())==FUNC_OK)

		{

		interval++;

		if((restart)&&(interval % restart==0))

			 IntervalFlag=TRUE;

		else

			IntervalFlag=FALSE;

//lfj



		IQtIZzMCUComponent(0);

		IQtIZzMCUComponent(1);

		IQtIZzMCUComponent(2);



		  GetYUV(0);

		  GetYUV(1);

		  GetYUV(2);



		StoreBuffer();



		sizej+=SampRate_Y_H*8;



		if(sizej>=imgwidth)

			{

			DispABand();

			sizej=0;

			sizei+=SampRate_Y_V*8;

			}



		if ((sizej==0)&&(sizei>=imgheight))

			break;

		}

	return funcret;

}

/////////////////////////////////////////////////////////////////////////////////////////

void  GetYUV(short flag)

{

	short H,VV;

	short i,j,k,h;

	int *buf;

	int *pQtZzMCU;



	switch(flag)

		{



		//lfj

		case 0:

			H=SampRate_Y_H;

			VV=SampRate_Y_V;

			buf=Y;

			pQtZzMCU=QtZzMCUBuffer;

			break;

		case 1:

			H=SampRate_U_H;

			VV=SampRate_U_V;

			buf=U;

			pQtZzMCU=QtZzMCUBuffer+Y_in_MCU*64;

			break;

		case 2:

			H=SampRate_V_H;

			VV=SampRate_V_V;

			buf=V;

			pQtZzMCU=QtZzMCUBuffer+(Y_in_MCU+U_in_MCU)*64;

			break;

		}



	for (i=0;i<VV;i++)

	  for(j=0;j<H;j++)

		for(k=0;k<8;k++)

		  for(h=0;h<8;h++)

			 buf[(i*8+k)*SampRate_Y_H*8+j*8+h]=*pQtZzMCU++;

}

///////////////////////////////////////////////////////////////////////////////

void StoreBuffer()

{

	short i,j;

	unsigned char  *lpbmp;

	unsigned char  *lpbibandtemp;

	unsigned char R,G,B;

	int y,u,v,rr,gg,bb;





	for(i=0;i<SampRate_Y_V*8;i++)

		{

		if((sizei+i)<imgheight)

			{

			lpbmp=(lpbi+(DWORD)(imgheight-sizei-i-1)*linesize+sizej*3);

			lpbibandtemp=(lpbibandbits+(DWORD)(SampRate_Y_V*8-i-1)*linesize+sizej*3);

			for(j=0;j<SampRate_Y_H*8;j++)

				{

				if((sizej+j)<imgwidth)

					{

					y=Y[i*8*SampRate_Y_H+j];

					u=U[(i/V_YtoU)*8*SampRate_Y_H+j/H_YtoU];

					v=V[(i/V_YtoV)*8*SampRate_Y_H+j/H_YtoV];



					rr=((y<<8)+18*u+367*v)>>8;

					gg=((y<<8)-159*u-220*v)>>8;

					bb=((y<<8)+411*u-29*v)>>8;



					R=(unsigned char)rr;

					G=(unsigned char)gg;

					B=(unsigned char)bb;



					if (rr&0xffffff00) if (rr>255) R=255; else if (rr<0) R=0;

					if (gg&0xffffff00) if (gg>255) G=255; else if (gg<0) G=0;

					if (bb&0xffffff00) if (bb>255) B=255; else if (bb<0) B=0;



					*lpbmp++=B;

					*lpbmp++=G;

					*lpbmp++=R;



					*lpbibandtemp++=B;

					*lpbibandtemp++=G;

					*lpbibandtemp++=R;

					}

				else  break;

				}

			}

		else break;

		}

}

///////////////////////////////////////////////////////////////////////////////

FUNCRET DecodeMCUBlock()

{

	short *lpMCUBuffer;

	short i,j;

	FUNCRET funcret;



	if (IntervalFlag)

		{

		lp+=2;

		ycoef=ucoef=vcoef=0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -