📄 jpegdecoder.cpp
字号:
{
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 + -