📄 复件 jpegdoc.cpp
字号:
r_height=height+8-height%8;
}
/////////////////////////////////////////////////////////////////////////////////////
int LumDChufco[12],LumDChufsi[12]; //存储DC数据的哈夫曼码表和码长,四个字节
int LumAChufco[251],LumAChufsi[251]; //存储AC数据的哈夫曼码表和码长,四个字节
int ChrDChufco[12],ChrDChufsi[12];
int ChrAChufco[251],ChrAChufsi[251];
//*******************************
HuffmanTable(LumDCHuffmanBit,LumDCHuffmanVal);//得到亮度DC的HUFFMAN的码表和码长
for(i=0;i<12;i++)
{
LumDChufco[i]=ehufco[i]; //DChufco是亮度哈夫曼的码表
LumDChufsi[i]=ehufsi[i]; //DChufsi是亮度哈夫曼的码长
}
//********************************
HuffmanTable(LumACHuffmanBit,LumACHuffmanVal);//得到亮度AC的HUFFMAN的码表和码长
for(i=0;i<251;i++) //实际上用不完252个数,中间一些数没有用
{
LumAChufco[i]=ehufco[i]; //AChufco是亮度哈夫曼的码表
LumAChufsi[i]=ehufsi[i]; //AChufsi是亮度哈夫曼的码长
}
//*******************************
HuffmanTable(ChrDCHuffmanBit,ChrDCHuffmanVal);//得到色度DC的HUFFMAN的码表和码长
for(i=0;i<12;i++)
{
ChrDChufco[i]=ehufco[i]; //DChufco是色度哈夫曼的码表
ChrDChufsi[i]=ehufsi[i]; //DChufsi是色度哈夫曼的码长
}
//******************************
HuffmanTable(ChrACHuffmanBit,ChrACHuffmanVal);//得到色度AC的HUFFMAN的码表和码长
for(i=0;i<251;i++)
{
ChrAChufco[i]=ehufco[i]; //AChufco是色度哈夫曼的码表
ChrAChufsi[i]=ehufsi[i]; //AChufsi是色度哈夫曼的码长
}
///////////////////////////////////////////////////////////////////////////
double xx[64];
int ii,jj;
int LumPreDC=0,CrPreDC=0,CbPreDC=0;
// FILE *fp;
if(m_bit24==1)
{
char Cr[304][400]; //需初始化为零,必须定义为有符号变量, 定义为无符号变量不能正确显示
char Cb[304][400];
char Y[608][800];
for(j=0;j<600;j++)
for(i=0;i<800;i++)
{
Y[j][i]=0;
Cr[j/2][i/2]=0;
Cb[j/2][i/2]=0;
}
for(j=0;j<height;j++)
for(i=0;i<width;i++)
{
Y[j][i]=(int)(0.114*data[j][i].Blue+0.587*data[j][i].Green+0.299*data[j][i].Red)-128;
}
for(j=0;j<height/2;j++) //height/2
for(i=0;i<width/2;i++) //width/2
{
Cr[j][i]=(int)(-0.0813*data[j*2][i*2].Blue-0.4187*data[j*2][i*2].Green+0.5*data[j*2][i*2].Red);
Cb[j][i]=(int)(0.5*data[j*2][i*2].Blue-0.3313*data[j*2][i*2].Green-0.1687*data[j*2][i*2].Red);
}
/////////////////////////////////////////////////////////////////////
/* for(i=0;i<64;i++)
{
LumQuantTable[i]=LumQuantTable[i]/2;
ChrQuantTable[i]=ChrQuantTable[i]/2;
}
*/
for(ii=0;ii<r_height/16;ii++) //r_height/16
for(jj=0;jj<r_width/16;jj++) //r_width/16
{
///////// 00 ///////////////////////
for(i=0;i<8;i++)
for(j=0;j<8;j++)
{
xx[i*8+j]=Y[ii*16+i][jj*16+j];
}
DCT(xx,64,LumQuantTable);
LumPreDC=WriteData(LumPreDC,LumDChufco,LumDChufsi,LumAChufco,LumAChufsi);
///////// 01 ////////////////////////////
for(i=0;i<8;i++)
for(j=0;j<8;j++)
{
xx[i*8+j]=Y[ii*16+i][jj*16+8+j];
}
DCT(xx,64,LumQuantTable);
LumPreDC=WriteData(LumPreDC,LumDChufco,LumDChufsi,LumAChufco,LumAChufsi);
/////////// 10 /////////////////////////////
for(i=0;i<8;i++)
for(j=0;j<8;j++)
{
xx[i*8+j]=Y[ii*16+8+i][jj*16+j];
}
DCT(xx,64,LumQuantTable);
LumPreDC=WriteData(LumPreDC,LumDChufco,LumDChufsi,LumAChufco,LumAChufsi);
///////// 11 /////////////////////////////
for(i=0;i<8;i++)
for(j=0;j<8;j++)
{
xx[i*8+j]=Y[ii*16+8+i][jj*16+8+j];
}
DCT(xx,64,LumQuantTable);
LumPreDC=WriteData(LumPreDC,LumDChufco,LumDChufsi,LumAChufco,LumAChufsi);
////////////////////// 先蓝色后红色 ///////////////////////////////////////
for(i=0;i<8;i++)
for(j=0;j<8;j++)
{
xx[i*8+j]=Cb[ii*8+i][jj*8+j]; //蓝色色差
}
DCT(xx,64,ChrQuantTable);
CbPreDC=WriteData(CbPreDC,ChrDChufco,ChrDChufsi,ChrAChufco,ChrAChufsi);
for(i=0;i<8;i++)
for(j=0;j<8;j++)
{
xx[i*8+j]=Cr[ii*8+i][jj*8+j]; //红色色差
}
DCT(xx,64,ChrQuantTable);
CrPreDC=WriteData(CrPreDC,ChrDChufco,ChrDChufsi,ChrAChufco,ChrAChufsi);
}
//////////////////////////////////////////////////////////////////////
}
else if(m_bit24==0) //灰度图像
{
for(ii=0;ii<r_height/8;ii++)
{
for(jj=0;jj<r_width/8;jj++)
{
for(i=0;i<8;i++)
{
for(j=0;j<8;j++)
xx[i*8+j]=hdata[ii*8+i][jj*8+j]-128; //灰度值减去128
}
DCT(xx,64,LumQuantTable);
LumPreDC=WriteData(LumPreDC,LumDChufco,LumDChufsi,LumAChufco,LumAChufsi);
}
}
}
return TRUE;
}
////////////////////////////////////////////////////////////////////////////
//扩展为8的倍数的图像宽度和高度,不足的位全用零补齐,
//在定义数组用以存储BMP图像时,已对数组初始化为零,
//只支持1024*1024的图像
////////////////////////////////////////////////////////////////
int CDib::WriteData(int preDC,int *DChufco,int *DChufsi,int *AChufco,int *AChufsi)
{
int abs1;
int i,j;
unsigned char zero_num,power_num; //8bit
int digit,digitcode; //32bit
unsigned char huffmanval; //8bit
// int ii,jj;
int power_dc; //DC值的数据长度位数
int dc_huffmancode,dc_huffmanbitnum;
int nowDC; //第一个DC值预先设为0,nowDC为实际编码所用的DC值
int RLE_length; //游程长度
int ac_huffmancode,ac_huffmanbitnum; //32bit
/////////////////////////////////////////////////////////////
//////////////// 对DC分量进行编码 /////////////
/////////////////////////////////////////////////////////////
nowDC=table[0]-preDC; //对DC进行差分运算,初始值为0(即DC[0]=0)
preDC=table[0]; //保留原DC的DCT值,以便下一步使用
if(nowDC!=0)
{
for(i=0;i<16;i++)
{
if(abs(nowDC)<pow(2,i+1)&&abs(nowDC)>=pow(2,i)) //计算nowDC的二进制位数(即分组值),i即为它的位数
power_dc=i+1;
}
}
else
{
power_dc=0; //DC值为零时分组为零
}
if(nowDC>0) //对直流分量编码
{
dc_huffmancode=DChufco[power_dc];
dc_huffmanbitnum=DChufsi[power_dc];
ShiftWrite(dc_huffmanbitnum,dc_huffmancode);
ShiftWrite(power_dc,nowDC);
}
else if(nowDC<0) //
{
dc_huffmancode=DChufco[power_dc];
dc_huffmanbitnum=DChufsi[power_dc];
ShiftWrite(dc_huffmanbitnum,dc_huffmancode);//
abs1=((int)pow(2,power_dc)-1)-abs(nowDC); //DC为负,求绝对值后取其反码
ShiftWrite(power_dc,abs1); //由DC值的位长和码串决定如何移入数据缓冲区并写入文件
}
else
{
ShiftWrite(2,0); //当nowDC=0时,其huffman码串为00,两位长,移入数据缓冲区
}
///////////////////////////////////////////////////
//// 对AC分量进行编码 ///////
///////////////////////////////////////////////////
RLE_length=RLEProg(); //游程编码,返回值为游程的个数
int digitTemp;
for(i=0;i<RLE_length;i++)
{
zero_num=RLE[i].zero_num; //得到第i个游程的零的个数
digit=RLE[i].digit; //得到第i个游程的数值
//**///////////////////////////////////////////////////
if(digit<0)
digitTemp=abs(digit);
else
digitTemp=digit; //可把这四句用abs()函数加到下面的的if语句中
/////////....................................
if(digit!=0)
{
for(j=0;j<=16;j++)
{
if(digitTemp<pow(2,j+1)&&digitTemp>=pow(2,j)) //pow(2,j)为求2的J次幂,此处判断digit是哪一组的数
power_num=j+1; //最小为1,即最小分组为1
}
}
else //当digit=0,分组为0
{
power_num=0;
}
/////////....................................
if(digit<0)
{
digitcode=(int)(pow(2,power_num)-1)-abs(digit); //有效位取反码,使有效位以外的位为0
}
else
{
digitcode=digit;
}
//**//////////////////////////////////////////////////
huffmanval=(zero_num<<4)|power_num; //使零的个数与该游程值所在的分组合为一个字节,以便用哈夫曼码表
ac_huffmancode=AChufco[huffmanval]; //得到哈夫曼码表
ac_huffmanbitnum=AChufsi[huffmanval]; //得到哈夫曼码表的位长度
ShiftWrite(ac_huffmanbitnum,ac_huffmancode);
if(digit==0&&zero_num==0) //当是EOI(End of Image)时,不写数字位的0,否则要写数字位的0
{
}
else
ShiftWrite(power_num,digitcode); //游程不为(0,0)时,写入数据
}
return preDC;
}
//////////////// 写最后数据缓冲区中已移到高位的码串,使其凑成整字节,不足字节位时后加1 ////////////
BOOL CDib::WriteSurplus()
{
unsigned char spare[4];
EncodeJpeg=EncodeJpeg|((int)pow(2,surplus)-1); //使数据缓冲区中有效位以外的所有位为1
if(surplus<32&&surplus>=24) //剩余位大于等于24,只写一个字节到JPEG文件
{
spare[0]=(EncodeJpeg&0xff000000)>>24;
file.Write(spare,1);
}
else if(surplus<24&&surplus>=16) //剩余位大于等于16而小于24,写2个字节
{
spare[0]=(EncodeJpeg&0xff000000)>>24;
spare[1]=(EncodeJpeg&0xff0000)>>16;
file.Write(spare,2);
}
else if(surplus<16&&surplus>=8) //剩余位大于等于8而小于16,写3个字节
{
spare[0]=(EncodeJpeg&0xff000000)>>24;
spare[1]=(EncodeJpeg&0xff0000)>>16;
spare[2]=(EncodeJpeg&0xff00)>>8;
file.Write(spare,3);
}
else //剩余位小于8,写4个字节
{
spare[0]=(EncodeJpeg&0xff000000)>>24;
spare[1]=(EncodeJpeg&0xff0000)>>16;
spare[2]=(EncodeJpeg&0xff00)>>8;
spare[3]=EncodeJpeg&0xff;
file.Write(spare,4);
}
EncodeJpeg=surplus=0;
////////////////////////////////////////////////////
return TRUE;
}
////////////////////////////////////////////////////
//
// 把一个四字节的数由高字节到低字节的顺序写入文件
//
////////////////////////////////////////////////////
void CDib::Write32bit()
{
unsigned char buf[4],insert=0x00;
int i;
buf[0]=(EncodeJpeg&0xff000000)>>24; //把32位的JPEG编码整数由高位到低位存入buf数组中
buf[1]=(EncodeJpeg&0xff0000)>>16; //以便由高位到低位写入JPEG文件中,因直接写入,
buf[2]=(EncodeJpeg&0xff00)>>8; //将由低位到高位写入文件。
buf[3]=EncodeJpeg&0xff;
for(i=0;i<4;i++) //EncodeJpeg的32位已满,写入文件
{
file.Write(buf+i,1);
if(buf[i]==0xff) //如果某一字节为0xFF,则需插入一个数0x00
file.Write(&insert,1); //已定义insert为0x00
}
}
/////////////////////////////////////////////////
//
//
//
////////////////////////////////////////////////
void CDib::ShiftWrite(int huffmanbitnum,int huffmancode)
{
int i,j,k;
if(huffmanbitnum<surplus) //需要编码的码串比数据缓冲区剩余的位少,可直接移入,不写入JPEG文件
{
EncodeJpeg=EncodeJpeg|(huffmancode<<(surplus-huffmanbitnum));//需要编码的码串移入数据缓冲区
surplus=surplus-huffmanbitnum; //当前数据缓冲区剩余的位数
}
else//需要编码的码串比数据缓冲区剩余的位多,截断码串分两次移入数据缓冲区,使EncodeJpeg=32之后写入文件
{
i=huffmanbitnum-surplus; //截断码串后第二次移入数据缓冲区的位长
j=(int)pow(2,surplus)-1; //得到从低位到高位surplus个1,即(000111...11)
EncodeJpeg=EncodeJpeg|((huffmancode&(j<<i))>>i);
Write32bit(); //32位数据缓冲区填满后写入JPEG文件
EncodeJpeg=0; //数据缓冲区清零
k=(int)pow(2,i)-1; //
EncodeJpeg=(huffmancode&k)<<(32-i); //使被截断后剩余的码串移到32位数据缓冲区的高位
surplus=32-i; //目前数据缓冲区剩余的位数
}
}
BOOL CDib::ShangInvert()
{
long x,y;
if(m_bit24==1)
{
RGBData Tempdata;
for(y=0;y<height/2;y++)
for(x=0;x<width;x++)
{
Tempdata=data[y][x];
data[y][x]=data[height-1-y][x];
data[height-1-y][x]=Tempdata;
}
}
else
{
BYTE temp;
for(y=0;y<height/2;y++)
for(x=0;x<width;x++)
{
temp=hdata[y][x];
hdata[y][x]=hdata[height-1-y][x];
hdata[height-1-y][x]=temp;
}
}
return TRUE;
}
BOOL CDib::ZheInvert()
{
long x,y;
if(m_bit24==1)
{
RGBData Tempdata;
for(y=0;y<height;y++)
for(x=0;x<width/2;x++)
{
Tempdata=data[y][x];
data[y][x]=data[y][width-1-x];
data[y][width-1-x]=Tempdata;
}
}
else if(m_bit24==0)
{
BYTE temp;
for(y=0;y<height;y++)
for(x=0;x<width/2;x++)
{
temp=hdata[y][x];
hdata[y][x]=hdata[y][width-1-x];
hdata[y][width-1-x]=temp;
}
}
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CJPEGDoc diagnostics
#ifdef _DEBUG
void CJPEGDoc::AssertValid() const
{
CDocument::AssertValid();
}
void CJPEGDoc::Dump(CDumpContext& dc) const
{
CDocument::Dump(dc);
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CJPEGDoc commands
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -