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

📄 jpegdecoder.cpp

📁 VS2005图像处理程序的源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		{
			tmp_Hcode=lookKbits(k);
			if ( (tmp_Hcode<=*max_val)&&(tmp_Hcode>=*min_val) )
			{
				SkipKbits(k);
				byte_temp=huff_values[WORD_hi_lo(k,(BYTE)(tmp_Hcode-
					*min_val))];
				size_val=byte_temp&0xF;
				count_0=byte_temp>>4;
				if (size_val==0) 
				{
					if (count_0==0) EOB_found=1;
					else if (count_0==0xF) nr+=16; //跳过16 个0
				}
				else
				{
					nr+=count_0; 
					DCT_tcoeff[nr++]=GetKbits(size_val);
				}
				break;
			}
			min_val++; max_val++;
		}
		if (k>16) nr++; 
	}
	for (j=0;j<=63;j++) DCT_coeff[j]=DCT_tcoeff[zigzag[j]]; 
}
/***************************************************************************快速离散反余弦变换
**************************************************************************/
void JpegDecoder::IDCTTransform(SWORD *incoeff,BYTE *outcoeff,BYTE Q_nr)
{
	BYTE x;
	SBYTE y;
	SWORD *inptr;
	BYTE *outptr;
	float workspace[64];
	float *wsptr;//工作区指针
	float *quantptr; //量化表指针
	float dcval;
	float tmp0,tmp1,tmp2,tmp3,tmp4,tmp5,tmp6,tmp7;
	float tmp10,tmp11,tmp12,tmp13;
	float z5,z10,z11,z12,z13;
	BYTE *range_limit=rlimit_table+128;
	//处理输入的COLUMNS 信息并存入工作区数组
	wsptr=workspace;
	inptr=incoeff;
	quantptr=QT[Q_nr];
	for (y=0;y<=7;y++)
	{
		if( (inptr[8]|inptr[16]|inptr[24]|inptr[32]|inptr[40]|inptr[48]|inptr[56])==0)
		{
			dcval=inptr[0]*quantptr[0];
			wsptr[0]  = dcval;
			wsptr[8]  = dcval;
			wsptr[16] = dcval;
			wsptr[24] = dcval;
			wsptr[32] = dcval;
			wsptr[40] = dcval;
			wsptr[48] = dcval;
			wsptr[56] = dcval;
			inptr++;quantptr++;wsptr++;//将指针指向下一列
			continue ;
		}
		//偶数部分
		tmp0 = inptr[0] *quantptr[0];
		tmp1 = inptr[16]*quantptr[16];
		tmp2 = inptr[32]*quantptr[32];
		tmp3 = inptr[48]*quantptr[48];

		tmp10 = tmp0 + tmp2;
		tmp11 = tmp0 - tmp2;

		tmp13 = tmp1 + tmp3;
		tmp12 = (tmp1 - tmp3) * 1.414213562f - tmp13;

		tmp0 = tmp10 + tmp13;
		tmp3 = tmp10 - tmp13;
		tmp1 = tmp11 + tmp12;
		tmp2 = tmp11 - tmp12;

		//奇数部分
		tmp4 = inptr[8] *quantptr[8];
		tmp5 = inptr[24]*quantptr[24];
		tmp6 = inptr[40]*quantptr[40];
		tmp7 = inptr[56]*quantptr[56];

		z13 = tmp6 + tmp5;
		z10 = tmp6 - tmp5;
		z11 = tmp4 + tmp7;
		z12 = tmp4 - tmp7;

		tmp7 = z11 + z13;
		tmp11= (z11 - z13) * 1.414213562f;

		z5 = (z10 + z12) * 1.847759065f; 
		tmp10 = 1.082392200f * z12 - z5; 
		tmp12 = -2.613125930f * z10 + z5;

		tmp6 = tmp12 - tmp7;
		tmp5 = tmp11 - tmp6;
		tmp4 = tmp10 + tmp5;

		wsptr[0]  = tmp0 + tmp7;
		wsptr[56] = tmp0 - tmp7;
		wsptr[8]  = tmp1 + tmp6;
		wsptr[48] = tmp1 - tmp6;
		wsptr[16] = tmp2 + tmp5;
		wsptr[40] = tmp2 - tmp5;
		wsptr[32] = tmp3 + tmp4;
		wsptr[24] = tmp3 - tmp4;
		inptr++;
		quantptr++;
		wsptr++;//将指针指向下一列
	}

	// 处理来自工作数组的ROWS信息并将结果存入输出数组中
	outptr=outcoeff;
	wsptr=workspace;
	for (x=0;x<=7;x++)
	{
		// 偶数部分
		tmp10 = wsptr[0] + wsptr[4];
		tmp11 = wsptr[0] - wsptr[4];

		tmp13 = wsptr[2] + wsptr[6];
		tmp12 =(wsptr[2] - wsptr[6]) * 1.414213562f - tmp13;

		tmp0 = tmp10 + tmp13;
		tmp3 = tmp10 - tmp13;
		tmp1 = tmp11 + tmp12;
		tmp2 = tmp11 - tmp12;

		// 奇数部分
		z13 = wsptr[5] + wsptr[3];
		z10 = wsptr[5] - wsptr[3];
		z11 = wsptr[1] + wsptr[7];
		z12 = wsptr[1] - wsptr[7];

		tmp7 = z11 + z13;
		tmp11= (z11 - z13) * 1.414213562f;

		z5 = (z10 + z12) * 1.847759065f;
		tmp10 = 1.082392200f * z12 - z5;
		tmp12 = -2.613125930f * z10 + z5;

		tmp6 = tmp12 - tmp7;
		tmp5 = tmp11 - tmp6;
		tmp4 = tmp10 + tmp5;

		// 最终输出: 按比例缩小
		outptr[0] = range_limit[(DESCALE((int) (tmp0 + tmp7), 3)) & 1023L];
		outptr[7] = range_limit[(DESCALE((int) (tmp0 - tmp7), 3)) & 1023L];
		outptr[1] = range_limit[(DESCALE((int) (tmp1 + tmp6), 3)) & 1023L];
		outptr[6] = range_limit[(DESCALE((int) (tmp1 - tmp6), 3)) & 1023L];
		outptr[2] = range_limit[(DESCALE((int) (tmp2 + tmp5), 3)) & 1023L];
		outptr[5] = range_limit[(DESCALE((int) (tmp2 - tmp5), 3)) & 1023L];
		outptr[4] = range_limit[(DESCALE((int) (tmp3 + tmp4), 3)) & 1023L];
		outptr[3] = range_limit[(DESCALE((int) (tmp3 - tmp4), 3)) & 1023L];

		wsptr+=8;//将指针指向下一行
		outptr+=8;
	}
}
/***************************************************************************为色彩空间转换进行预处理,参见3.3.4中的公式
**************************************************************************/
void JpegDecoder::Precalculate_Cr_Cb_Tables()
{
	WORD k;
	WORD Cr_v,Cb_v;
	for (k=0;k<=255;k++) Cr_tab[k]=(SWORD)((k-128.0)*1.402);
	for (k=0;k<=255;k++) Cb_tab[k]=(SWORD)((k-128.0)*1.772);

	for (Cr_v=0;Cr_v<=255;Cr_v++)
		for (Cb_v=0;Cb_v<=255;Cb_v++)
			Cr_Cb_green_tab[((WORD)(Cr_v)<<8)+Cb_v]=(int)(-0.34414*(Cb_v-
			128.0)-0.71414*(Cr_v-128.0));
}
/***************************************************************************将YCbCr空间转换到RGB空间
**************************************************************************/
void JpegDecoder::Convert8x8YCbCrToRGB(BYTE *Y, BYTE *Cb, BYTE *Cr, DWORD im_loc, DWORD X_image_bytes, BYTE *im_buffer)
{
	DWORD x,y;
	BYTE im_nr;
	BYTE *Y_val = Y, *Cb_val = Cb, *Cr_val = Cr;
	BYTE *ibuffer = im_buffer + im_loc;

	for (y=0;y<8;y++)
	{
		im_nr=0;
		for (x=0;x<8;x++)
		{
			ibuffer[im_nr++] = rlimit_table[*Y_val + Cb_tab[*Cb_val]]; //B
			ibuffer[im_nr++] = rlimit_table[*Y_val + 
				Cr_Cb_green_tab[WORD_hi_lo(*Cr_val,*Cb_val)]]; //G
			ibuffer[im_nr++] = rlimit_table[*Y_val + Cr_tab[*Cr_val]]; // R
			Y_val++; Cb_val++; Cr_val++; im_nr++;
		}
		ibuffer+=X_image_bytes;
	}
}
/***************************************************************************将YCbCr空间转换到RGB空间
*与Convert8x8YCbCrToRGB()函数的区别在于对应的YCbCr标准不同
**************************************************************************/
void JpegDecoder::Convert8x8YCbCrToRGBTab(BYTE *Y, BYTE *Cb, BYTE *Cr, BYTE *tab, DWORD im_loc, DWORD X_image_bytes, BYTE *im_buffer)
{
	DWORD x,y;
	BYTE nr, im_nr;
	BYTE Y_val,Cb_val,Cr_val;
	BYTE *ibuffer = im_buffer + im_loc;

	nr=0;
	for (y=0;y<8;y++)
	{
		im_nr=0;
		for (x=0;x<8;x++)
		{
			Y_val=Y[nr];
			Cb_val=Cb[tab[nr]]; Cr_val=Cr[tab[nr]]; 
			ibuffer[im_nr++] = rlimit_table[Y_val + Cb_tab[Cb_val]]; //B
			ibuffer[im_nr++] = rlimit_table[Y_val + 
				Cr_Cb_green_tab[WORD_hi_lo(Cr_val,Cb_val)]]; //G
			ibuffer[im_nr++] = rlimit_table[Y_val + Cr_tab[Cr_val]]; // R
			nr++; im_nr++;
		}
		ibuffer+=X_image_bytes;
	}
}
/*************************************************************************** 分块操作
**************************************************************************/
void JpegDecoder::CalculateTabs()
{
	BYTE tab_temp[256];
	BYTE x,y;

	//将线性存放的数组变成16x16的二维矩阵
	for (y=0;y<16;y++)
		for (x=0;x<16;x++)
			tab_temp[y*16+x] = (y/YV)* 8 + x/YH;

	// 分成4个8x8子块
	for (y=0;y<8;y++)
	{
		for (x=0;x<8;x++)
			tab_1[y*8+x]=tab_temp[y*16+x];
		for (x=8;x<16;x++)
			tab_2[y*8+(x-8)]=tab_temp[y*16+x];
	}
	for (y=8;y<16;y++)
	{
		for (x=0;x<8;x++)
			tab_3[(y-8)*8+x]=tab_temp[y*16+x];
		for (x=8;x<16;x++)
			tab_4[(y-8)*8+(x-8)]=tab_temp[y*16+x];
	}
}
/*************************************************************************** 初始化JPEG解码
**************************************************************************/
int JpegDecoder::InitJPGDecoding()
{
	byte_pos=0;
	InitQT();
	CalculateMask();
	PrepareRangeLimitTable();
	Precalculate_Cr_Cb_Tables();
	return 1;
}
/*************************************************************************** 返回文件的大小
**************************************************************************/
DWORD JpegDecoder::GetFileSize(FILE *fp)
{
	DWORD pos;
	DWORD pos_cur;
	pos_cur=ftell(fp);
	fseek(fp,0,SEEK_END);
	pos=ftell(fp);
	fseek(fp,pos_cur,SEEK_SET);
	return pos;
}
/*************************************************************************** 解码子块前的准备工作,包括重定位等
**************************************************************************/
void JpegDecoder::Resync()
{
	byte_pos+=2;
	BYTE_p(byte_pos);
	if (bp==0xFF) byte_pos++; 
	w1=WORD_hi_lo(bp, 0);
	BYTE_p(byte_pos);
	if (bp==0xFF) byte_pos++; 
	w1+=bp;
	BYTE_p(byte_pos);
	if (bp==0xFF) byte_pos++; 
	w2=WORD_hi_lo(bp, 0);
	BYTE_p(byte_pos);
	if (bp==0xFF) byte_pos++; 
	w2+=bp;
	wordval=w1; d_k=0;
	DCY=0; DCCb=0; DCCr=0; // 初始 DC 系数
}
/*************************************************************************** 当MCU编码子块采用的是YCbCr 4:4:4模式的时候采用该函数进行MCU解码
* 这个处理函数中采用的色彩空间转换函数是Convert8x8YCbCrToRGB()
* 而后面的三个函数均采用Convert8x8YCbCrToRGBTab()
* 区别在于采用YCbCr 4:4:4模式时,CbCr的排列不再使用2×2的形式记录,
* 因此原始图像也不是16×16 的整数块,解码时无需分块处理
**************************************************************************/
void JpegDecoder::DecodeMCU1x1(DWORD im_loc)
{
	// Y
	ProcessHuffmanDataUnit(YDC_nr,YAC_nr,&DCY);
	IDCTTransform(DCT_coeff,Y,YQ_nr);
	// Cb
	ProcessHuffmanDataUnit(CbDC_nr,CbAC_nr,&DCCb);
	IDCTTransform(DCT_coeff,Cb,CbQ_nr);
	// Cr
	ProcessHuffmanDataUnit(CrDC_nr,CrAC_nr,&DCCr);
	IDCTTransform(DCT_coeff,Cr,CrQ_nr);

	Convert8x8YCbCrToRGB(Y,Cb,Cr,im_loc,X_image_bytes,im_buffer);
}
/*************************************************************************** 当MCU编码子块采用的是YCbCr 4:2:2模式的时候采用该函数进行MCU解码
**************************************************************************/
void JpegDecoder::DecodeMCU2x1(DWORD im_loc)
{
	// Y
	ProcessHuffmanDataUnit(YDC_nr,YAC_nr,&DCY);
	IDCTTransform(DCT_coeff,Y_1,YQ_nr);
	ProcessHuffmanDataUnit(YDC_nr,YAC_nr,&DCY);
	IDCTTransform(DCT_coeff,Y_2,YQ_nr);
	// Cb
	ProcessHuffmanDataUnit(CbDC_nr,CbAC_nr,&DCCb);
	IDCTTransform(DCT_coeff,Cb,CbQ_nr);
	// Cr
	ProcessHuffmanDataUnit(CrDC_nr,CrAC_nr,&DCCr);
	IDCTTransform(DCT_coeff,Cr,CrQ_nr);

	Convert8x8YCbCrToRGBTab(Y_1,Cb,Cr,tab_1,im_loc,X_image_bytes,im_buffer);
	Convert8x8YCbCrToRGBTab(Y_2,Cb,Cr,tab_2,im_loc+32,X_image_bytes,im_buffer);
}
/*************************************************************************** 当MCU编码子块采用的是YCbCr 4:2:0模式的时候采用该函数进行MCU解码
**************************************************************************/
void JpegDecoder::DecodeMCU2x2(DWORD im_loc)
{
	// Y
	ProcessHuffmanDataUnit(YDC_nr,YAC_nr,&DCY);
	IDCTTransform(DCT_coeff,Y_1,YQ_nr);
	ProcessHuffmanDataUnit(YDC_nr,YAC_nr,&DCY);
	IDCTTransform(DCT_coeff,Y_2,YQ_nr);
	ProcessHuffmanDataUnit(YDC_nr,YAC_nr,&DCY);
	IDCTTransform(DCT_coeff,Y_3,YQ_nr);
	ProcessHuffmanDataUnit(YDC_nr,YAC_nr,&DCY);
	IDCTTransform(DCT_coeff,Y_4,YQ_nr);
	// Cb
	ProcessHuffmanDataUnit(CbDC_nr,CbAC_nr,&DCCb);
	IDCTTransform(DCT_coeff,Cb,CbQ_nr);
	// Cr
	ProcessHuffmanDataUnit(CrDC_nr,CrAC_nr,&DCCr);
	IDCTTransform(DCT_coeff,Cr,CrQ_nr);

	Convert8x8YCbCrToRGBTab(Y_1,Cb,Cr,tab_1,im_loc,X_image_bytes,im_buffer);
	Convert8x8YCbCrToRGBTab(Y_2,Cb,Cr,tab_2,im_loc+32,X_image_bytes,im_buffer);
	Convert8x8YCbCrToRGBTab(Y_3,Cb,Cr,tab_3,im_loc+y_inc_value,X_image_bytes,im_buffer);
	Convert8x8YCbCrToRGBTab(Y_4,Cb,Cr,tab_4,im_loc+y_inc_value+32,X_image_bytes,im_buffer);
}
/*************************************************************************** 当MCU编码子块采用的是YCbCr 4:1:1模式的时候采用该函数进行MCU解码
**************************************************************************/
void JpegDecoder::DecodeMCU1x2(DWORD im_loc)
{
	// Y
	ProcessHuffmanDataUnit(YDC_nr,YAC_nr,&DCY);
	IDCTTransform(DCT_coeff,Y_1,YQ_nr);
	ProcessHuffmanDataUnit(YDC_nr,YAC_nr,&DCY);
	IDCTTransform(DCT_coeff,Y_2,YQ_nr);
	// Cb
	ProcessHuffmanDataUnit(CbDC_nr,CbAC_nr,&DCCb);
	IDCTTransform(DCT_coeff,Cb,CbQ_nr);
	// Cr
	ProcessHuffmanDataUnit(CrDC_nr,CrAC_nr,&DCCr);
	IDCTTransform(DCT_coeff,Cr,CrQ_nr);

	Convert8x8YCbCrToRGBTab(Y_1,Cb,Cr,tab_1,im_loc,X_image_bytes,im_buffer);
	Convert8x8YCbCrToRGBTab(Y_2,Cb,Cr,tab_3,im_loc+y_inc_value,X_image_bytes,im_buffer);
}
/***************************************************************************解码JPEG中的MCU子块
**************************************************************************/
void JpegDecoder::DecodeJPEGImage()
{
	decode_MCU_func decode_MCU;

	WORD x_mcu_cnt,y_mcu_cnt;
	DWORD nr_mcu;
	WORD X_MCU_nr,Y_MCU_nr; 
	DWORD MCU_dim_x; //dimensiunea in bufferul imagine a unui MCU pe axa x
	DWORD im_loc_inc; // = 7 * X_round * 4 sau 15*X_round*4;
	DWORD im_loc; //locatia in bufferul imagine

	byte_pos-=2;
	Resync();

	y_inc_value = 32*X_round;
	// 计算 YH 和 YV 的值
	CalculateTabs(); 
	//通过判定MCU子块采用的颜色空间模式来选择适当的处理函数
	if ((YH==1)&&(YV==1)) decode_MCU=&JpegDecoder::DecodeMCU1x1;
	else {
		if (YH==2)
		{
			if (YV==2) decode_MCU=&JpegDecoder::DecodeMCU2x2;
			else decode_MCU=&JpegDecoder::DecodeMCU2x1;
		}
		else decode_MCU=&JpegDecoder::DecodeMCU1x2;
	}
	MCU_dim_x=Hmax*8*4;

	Y_MCU_nr=Y_round/(Vmax*8); // MCU子块在垂直方向上的数目
	X_MCU_nr=X_round/(Hmax*8); // MCU子块在水平方向上的数目

	X_image_bytes=X_round*4; im_loc_inc = (Vmax*8-1) * X_image_bytes;
	nr_mcu=0; im_loc=0; 
	//对MCU子块进行逐个解码直到所有的子块解码完成
	for (y_mcu_cnt=0;y_mcu_cnt<Y_MCU_nr;y_mcu_cnt++)
	{
		for (x_mcu_cnt=0;x_mcu_cnt<X_MCU_nr;x_mcu_cnt++)
		{
			(this->*decode_MCU)(im_loc);
			if ((Restart_markers)&&((nr_mcu+1)%MCU_restart==0)) Resync();
			nr_mcu++;
			im_loc+=MCU_dim_x;
		}
		im_loc+=im_loc_inc;
	}
}
/*************************************************************************** 返回被填充后的像素数组
**************************************************************************/
int JpegDecoder::GetJPEGBuffer(WORD X_image,WORD Y_image, BYTE **address_dest_buffer)
{
	WORD y;
	DWORD dest_loc=0;
	BYTE *src_buffer=im_buffer;
	BYTE *dest_buffer_start, *dest_buffer;

	DWORD src_bytes_per_line=X_round*4;
	DWORD dest_bytes_per_line=X_image*4;
	//填充像素数组
	if ((X_round==X_image)&&(Y_round==Y_image))
		*address_dest_buffer=im_buffer;
	//当不满足上面的条件时,图像将会发生扭曲
	//为了克服图像的扭曲问题,将采取下面的操作重新为每一行像素分配空间
	else
	{
		dest_buffer_start = (BYTE *)malloc(X_image*Y_image*4);
		if (dest_buffer_start==NULL) exit_func("Not enough memory for storing image");
		dest_buffer = dest_buffer_start;
		for (y=0;y<Y_image;y++) {
			memcpy(dest_buffer,src_buffer,dest_bytes_per_line);
			src_buffer += src_bytes_per_line;
			dest_buffer += dest_bytes_per_line;
		}
		*address_dest_buffer = dest_buffer_start;
		free(im_buffer);
	}
	return 1;
}

⌨️ 快捷键说明

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