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

📄 jpegdecoder.cpp

📁 VS2005图像处理程序的源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include "stdafx.h"
#include "JpegDecoder.h"

#pragma warning ( disable : 4996)

// 标记符
#define SOI 0xD8
#define EOI 0xD9
#define APP0 0xE0
#define SOF 0xC0
#define DQT 0xDB
#define DHT 0xC4
#define SOS 0xDA
#define DRI 0xDD
#define COM 0xFE


#define BYTE_p(i) bp=buf[(i)++]
#define WORD_p(i) wp=(((WORD)(buf[(i)]))<<8) + buf[(i)+1]; (i)+=2

#define RIGHT_SHIFT(x,shft)  \
	((shift_temp = (x)) < 0 ? \
	(shift_temp >> (shft)) | ((~(0L)) << (32-(shft))) : \
	(shift_temp >> (shft)))
#define DESCALE(x,n)  RIGHT_SHIFT((x) + (1L << ((n)-1)), n)
#define RANGE_MASK 1023L

typedef void (JpegDecoder::*decode_MCU_func)(DWORD);

// Z字形排列后的DCT系数序号矩阵
static BYTE zigzag[64]={ 0, 1, 5, 6,14,15,27,28,
						2, 4, 7,13,16,26,29,42,
						3, 8,12,17,25,30,41,43,
						9,11,18,24,31,40,44,53,
						10,19,23,32,39,45,52,54,
						20,22,33,38,46,51,55,60,
						21,34,37,47,50,56,59,61,
						35,36,48,49,57,58,62,63 };

// 数值幅度编码表数组
static SWORD neg_pow2[17] = {0,-1,-3,-7,-15,-31,-63,-127,-255,-511,-1023,-2047,-4095,-8191,-16383,-32767};

static DWORD start_neg_pow2 = (DWORD)neg_pow2;

// 霍夫曼解码时使用的实际值
static DWORD wordval;

#define exit_func(err) { strcpy(error_string, err); return 0;}//错误提示信息

#ifdef _MSC_VER
WORD lookKbits(BYTE k)
{
	_asm {
		mov dl, k
			mov cl, 16
			sub cl, dl
			mov eax, [wordval]
		shr eax, cl
	}
}
WORD WORD_hi_lo(BYTE byte_high,BYTE byte_low)
{
	_asm {
		mov ah,byte_high
			mov al,byte_low
	}
}
SWORD get_svalue(BYTE k)
{
	_asm {
		xor ecx, ecx
			mov cl,k
			mov eax,[wordval]
		shl eax,cl
			shr eax, 16
			dec cl
			bt eax,ecx
			jc end_macro
signed_value:inc cl
			 mov ebx,[start_neg_pow2]
		add ax,word ptr [ebx+ecx*2]
end_macro:
	}
}
#endif

#ifdef __WATCOMC__

WORD lookKbits(BYTE k);
#pragma aux lookKbits=\
	"mov eax,[wordval]"\
	"mov cl, 16"\
	"sub cl, dl"\
	"shr eax, cl"\
	parm [dl] \
	value [ax] \
	modify [eax cl];
WORD WORD_hi_lo(BYTE byte_high,BYTE BYTE_low);
#pragma aux WORD_hi_lo=\
	parm [ah] [al]\
	value [ax] \
	modify [ax];

SWORD get_svalue(BYTE k);
#pragma aux get_svalue=\
	"xor ecx, ecx"\
	"mov cl, al"\
	"mov eax,[wordval]"\
	"shl eax, cl"\
	"shr eax, 16"\
	"dec cl"\
	"bt eax,ecx"\
	"jc end_macro"\
	"signed_value:inc cl"\
	"mov ebx,[start_neg_pow2]"\
	"add ax,word ptr [ebx+ecx*2]"\
	"end_macro:"\
	parm [al]\
	modify [eax ebx ecx]\
	value [ax];
#endif

/*************************************************************************** 构造函数
**************************************************************************/
JpegDecoder::JpegDecoder(FILE* f)
{
	d_k = 0;
	LoadJPEGHeader(f);
	DecodeJPEGImage();
}
/*************************************************************************** 析构函数, 释放资源
**************************************************************************/
JpegDecoder::~JpegDecoder(void)
{
	free(buf);
	free(tempTable);
	for (int i = 0; i <=3; i++)free(QT[i]);
}
/*************************************************************************** 载入JPEG文件头
**************************************************************************/
bool JpegDecoder::LoadJPEGHeader(FILE* fp)
{
	DWORD length_of_file;
	BYTE vers,units;
	WORD Xdensity,Ydensity,Xthumbnail,Ythumbnail;
	WORD length;
	float *qtable;
	DWORD old_byte_pos;
	Huffman_table *htable;
	long j;
	BYTE precision,comp_id,nr_components;
	BYTE QT_info,HT_info;
	BYTE SOS_found,SOF_found;
	//读取JPEG文件,并为其分配空间
	length_of_file=GetFileSize(fp);
	buf=(BYTE *)malloc(length_of_file+4);
	if (buf==NULL) exit_func("Not enough memory for loading file");
	fread(buf,length_of_file,1,fp);
	//判断文件是否是一个合法的JPEG文件
	if ((buf[0]!=0xFF)||(buf[1]!=SOI)) exit_func("Not a JPG file ?\n");
	if ((buf[2]!=0xFF)||(buf[3]!=APP0)) exit_func("Invalid JPG file.");
	if ( (buf[6]!='J')||(buf[7]!='F')||(buf[8]!='I')||(buf[9]!='F')||
		(buf[10]!=0) ) exit_func("Invalid JPG file.");
	//初始化
	InitJPGDecoding();
	byte_pos=11;
	//获取JPEG文件的版本并判断是否支持该版本
	BYTE_p(byte_pos);vers=bp;
	if (vers!=1) exit_func("JFIF version not supported");
	BYTE_p(byte_pos); 
	BYTE_p(byte_pos);  units=bp;
	WORD_p(byte_pos); Xdensity=wp; WORD_p(byte_pos); Ydensity=wp;
	//是否能够处理缩略图
	BYTE_p(byte_pos);Xthumbnail=bp;BYTE_p(byte_pos);Ythumbnail=bp;
	if ((Xthumbnail!=0)||(Ythumbnail!=0))
		exit_func(" Cannot process JFIF thumbnailed files\n");
	//开始解码处理, 寻找扫描线开始的位置, 以确定压缩数据的位置
	SOS_found=0; SOF_found=0; Restart_markers=0;
	while ((byte_pos<length_of_file)&&!SOS_found)
	{
		BYTE_p(byte_pos);
		if (bp!=0xFF) continue;
		// 找到一个标记符
		BYTE_p(byte_pos);
		switch(bp)
		{
		case DQT: WORD_p(byte_pos); length=wp;
			for (j=0;j<wp-2;)
			{
				old_byte_pos=byte_pos;
				BYTE_p(byte_pos); QT_info=bp;
				if ((QT_info>>4)!=0)
					exit_func("16 bit quantization table not supported");
				qtable=QT[QT_info&0xF];
				LoadQuantTable(qtable);//载入量化表
				j+=byte_pos-old_byte_pos;
			}break;
		case DHT: WORD_p(byte_pos); length=wp;
			for (j=0;j<wp-2;)
			{
				old_byte_pos=byte_pos;
				BYTE_p(byte_pos); HT_info=bp;
				if ((HT_info&0x10)!=0) htable=&HTAC[HT_info&0xF];
				else htable=&HTDC[HT_info&0xF];
				LoadHuffmanTable(htable);//载入霍夫曼表
				j+=byte_pos-old_byte_pos;
			}break;
		case COM: WORD_p(byte_pos); length=wp;
			byte_pos+=wp-2;
			break;
		case DRI: Restart_markers=1;
			WORD_p(byte_pos); length=wp; 
			WORD_p(byte_pos);  MCU_restart=wp;
			if (MCU_restart==0) Restart_markers=0;
			break;
		case SOF: WORD_p(byte_pos); length=wp; //该值应为 8+3*3=17
			BYTE_p(byte_pos); precision=bp;
			if (precision!=8) exit_func("Only 8 bit precision supported");
			WORD_p(byte_pos); height=wp; WORD_p(byte_pos); width=wp;
			BYTE_p(byte_pos); nr_components=bp;
			if (nr_components!=3) exit_func("Only truecolor JPGS supported");
			for (j=1;j<=3;j++)
			{
				BYTE_p(byte_pos); comp_id=bp;
				if ((comp_id==0)||(comp_id>3)) exit_func("Only YCbCr format supported");
				switch (comp_id)
				{
				case 1: // Y
					BYTE_p(byte_pos); YH=bp>>4;YV=bp&0xF;
					BYTE_p(byte_pos); YQ_nr=bp;
					break;
				case 2: // Cb
					BYTE_p(byte_pos); CbH=bp>>4;CbV=bp&0xF;
					BYTE_p(byte_pos); CbQ_nr=bp;
					break;
				case 3: // Cr
					BYTE_p(byte_pos); CrH=bp>>4;CrV=bp&0xF;
					BYTE_p(byte_pos); CrQ_nr=bp;
					break;
				}
			}
			SOF_found=1;break;
		case SOS: WORD_p(byte_pos); length=wp; //该值应为 = 6+3*2=12
			BYTE_p(byte_pos); nr_components=bp;
			if (nr_components!=3) exit_func("Invalid SOS marker");
			for (j=1;j<=3;j++)
			{
				BYTE_p(byte_pos); comp_id=bp;
				if ((comp_id==0)||(comp_id>3)) exit_func("Only YCbCr supported");
				switch (comp_id)
				{
				case 1: // Y
					BYTE_p(byte_pos); YDC_nr=bp>>4;YAC_nr=bp&0xF;
					break;
				case 2: // Cb
					BYTE_p(byte_pos); CbDC_nr=bp>>4;CbAC_nr=bp&0xF;
					break;
				case 3: // Cr
					BYTE_p(byte_pos); CrDC_nr=bp>>4;CrAC_nr=bp&0xF;
					break;
				}
			}
			BYTE_p(byte_pos); BYTE_p(byte_pos); BYTE_p(byte_pos);
			SOS_found=1;
			break;
			//连续出现0xFF时忽略不做处理
		case 0xFF:
			break;
			//跳过无法识别的标记符
		default:  WORD_p(byte_pos); length=wp;
			byte_pos+=wp-2; 
			break;
		}
	}
	//若为非法或无效的文件, 则提示无法处理并返回
	if (!SOS_found) exit_func("Invalid JPG file. No SOS marker found.");
	if (!SOF_found) exit_func("Progressive JPEGs not supported");
	if ((CbH>YH)||(CrH>YH)) exit_func("Vertical sampling factor for Y should be >= sampling factor for Cb,Cr");
		if ((CbV>YV)||(CrV>YV)) exit_func("Horizontal sampling factor for Y should be >= sampling factor for Cb,Cr");
			if ((CbH>=2)||(CbV>=2)) exit_func("Cb sampling factors should be = 1");
	if ((CrV>=2)||(CrV>=2)) exit_func("Cr sampling factors should be = 1");

	Hmax=YH,Vmax=YV;
	if ( width%(Hmax*8)==0) X_round=width; // X_round = Multiple of Hmax*8
	else X_round=(width/(Hmax*8)+1)*(Hmax*8);
	if ( height%(Vmax*8)==0) Y_round=height; // Y_round = Multiple of Vmax*8
	else Y_round=(height/(Vmax*8)+1)*(Vmax*8);
	//确定文件合法后, 为像素数组分配空间
	im_buffer=(BYTE *)malloc(X_round*Y_round*4);
	return true;
}
/*************************************************************************** 为sample_range_limit表分配存储空间,并进行填充
**************************************************************************/
void JpegDecoder::PrepareRangeLimitTable()
{
	int j;
	rlimit_table = (BYTE *)malloc(5 * 256L + 128) ;
	tempTable = rlimit_table;
	memset((void *)rlimit_table,0,256);
	rlimit_table += 256;
	for (j = 0; j < 256; j++) rlimit_table[j] = j;
	for (j = 256; j < 640; j++) rlimit_table[j] = 255;
	memset((void *)(rlimit_table + 640),0,384);
	for (j = 0; j < 128 ; j++) rlimit_table[j+1024] = j;
}
/*************************************************************************** 跳过k个比特
**************************************************************************/
void JpegDecoder::SkipKbits(BYTE k)
{
	BYTE b_high,b_low;
	d_k+=k;
	if (d_k>=16) 
	{ 
		d_k-=16;
		w1=w2;
		BYTE_p(byte_pos);
		if (bp!=0xFF) b_high=bp;
		else 
		{
			if (buf[byte_pos]==0) byte_pos++; 
			else byte_pos--;
			b_high=0xFF;
		}
		BYTE_p(byte_pos);
		if (bp!=0xFF) b_low=bp;
		else 
		{
			if (buf[byte_pos]==0) byte_pos++;
			else byte_pos--;
			b_low=0xFF;
		}
		w2=WORD_hi_lo(b_high,b_low);
	}
	wordval = ((DWORD)(w1)<<16) + w2;
	wordval <<= d_k;
	wordval >>= 16;
}
/*************************************************************************** 返回k个比特
**************************************************************************/
SWORD JpegDecoder::GetKbits(BYTE k)
{
	SWORD signed_wordvalue;
	signed_wordvalue=get_svalue(k);
	SkipKbits(k);
	return signed_wordvalue;
}
/*************************************************************************** 计算mask[16]数组
**************************************************************************/
void JpegDecoder::CalculateMask()
{
	BYTE k;
	DWORD tmpdv;
	for (k=0;k<=16;k++) { tmpdv=0x10000;mask[k]=(tmpdv>>k)-1;}
}
/*************************************************************************** 初始化量化表并为量化表分配存储空间
**************************************************************************/
void JpegDecoder::InitQT()
{
	BYTE i;
	for (i=0;i<=3;i++) QT[i]=(float *)malloc(sizeof(float)*64);
}
/*************************************************************************** 载入量化表
**************************************************************************/
void JpegDecoder::LoadQuantTable(float *quant_table)
{
	float scalefactor[8]={1.0f, 1.387039845f, 1.306562965f, 1.175875602f,
		1.0f, 0.785694958f, 0.541196100f, 0.275899379f};
	BYTE j,row,col;
	//从JPEG文件中载入量化表系数, 并按Z字形排序
	for (j=0;j<=63;j++) quant_table[j]=buf[byte_pos+zigzag[j]];
	j=0;
	for (row=0;row<=7;row++)
		for (col=0;col<=7;col++) {
			quant_table[j]*=scalefactor[row]*scalefactor[col];
			j++;
		}
		byte_pos+=64;
}
/*************************************************************************** 载入霍夫曼表
**************************************************************************/
void JpegDecoder::LoadHuffmanTable(Huffman_table *HT)
{
	BYTE k,j;
	DWORD code;

	for (j=1;j<=16;j++) {
		BYTE_p(byte_pos);
		HT->Length[j]=bp;
	}
	for (k=1;k<=16;k++)
		for (j=0;j<HT->Length[k];j++) {
			BYTE_p(byte_pos);
			HT->V[WORD_hi_lo(k,j)]=bp;
		}
		code=0;
		for (k=1;k<=16;k++) {
			HT->minor_code[k] = (WORD)code;
			for (j=1;j<=HT->Length[k];j++) code++;
			HT->major_code[k]=(WORD)(code-1);
			code*=2;
			if (HT->Length[k]==0) {
				HT->minor_code[k]=0xFFFF;
				HT->major_code[k]=0;
			}
		}
}
/*************************************************************************** 处理8×8子块,每个8×8子块是一个独立的数据单元
* 数据通过霍夫曼解码过程而被解压缩,最后数组被从Z字形排列方式中还原
* 计算结果DCT_coeff是一个容量为64的 DCT 系数数组
**************************************************************************/
void JpegDecoder::ProcessHuffmanDataUnit(BYTE DC_nr, BYTE AC_nr,SWORD *previous_DC)
{
	BYTE nr,k,j,EOB_found;
	register WORD tmp_Hcode;
	BYTE size_val,count_0;
	// min_code[k]表示长度为k的最小编码, maj_code[k]表示长度为k的最大编码
	WORD *min_code,*maj_code; 
	WORD *max_val, *min_val;
	BYTE *huff_values;
	SWORD DCT_tcoeff[64];
	BYTE byte_temp;

	// 开始霍夫曼解码,首先进行DC系数的解码
	min_code=HTDC[DC_nr].minor_code;
	maj_code=HTDC[DC_nr].major_code;
	huff_values=HTDC[DC_nr].V;

	for (nr = 0; nr < 64 ; nr++) DCT_tcoeff[nr] = 0; //初始化 DCT_tcoeff

	nr=0;// DC 系数

	min_val = &min_code[1]; max_val = &maj_code[1];
	for (k=1;k<=16;k++) 
	{
		tmp_Hcode=lookKbits(k);
		if ( (tmp_Hcode<=*max_val)&&(tmp_Hcode>=*min_val) ) 
		{ 
			//查找一个有效的霍夫曼编码
			SkipKbits(k);
			size_val=huff_values[WORD_hi_lo(k,(BYTE)(tmp_Hcode-*min_val))];
			if (size_val==0) DCT_tcoeff[0]=*previous_DC;
			else 
			{
				DCT_tcoeff[0]=*previous_DC+GetKbits(size_val);
				*previous_DC=DCT_tcoeff[0];
			}
			break;
		}
		min_val++; max_val++;
	}

	// AC系数解码
	min_code=HTAC[AC_nr].minor_code;
	maj_code=HTAC[AC_nr].major_code;
	huff_values=HTAC[AC_nr].V;

	nr=1; // AC 系数
	EOB_found=0;
	while ( (nr<=63)&&(!EOB_found) )
	{
		max_val = &maj_code[1]; min_val =&min_code[1];
		for (k=1;k<=16;k++)

⌨️ 快捷键说明

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