📄 jpeg_code.cpp
字号:
{
n = 0; //复位临时缓冲区偏移量
for (j = 0; j < xBufs; ++j) //循环X方向切割数量
{
bufOffset = yLen * xLen * i * xBufs + j * xLen; //计算单元信号块的首行偏移量
for (k = 0; k < yLen; ++k) //循环块的行数
{
memcpy(&tmpBuf[n],&pBuf[bufOffset],xLen); //复制一行到临时缓冲
n += xLen; //计算临时缓冲区偏移量
bufOffset += width; //计算输入缓冲区偏移量
}
}
memcpy(&pBuf[i * tmpBufLen],tmpBuf,tmpBufLen); //复制临时缓冲数据到输入缓冲
}
delete[] tmpBuf; //删除临时缓冲
}
//////////////////////////////////////////////////////////////////////////
// 方法说明:根据所需质量设置量化表
// 根据所需质量设置量化表
void JPEG_CODE::SetQuantTable(const BYTE* std_QT,BYTE* QT, int Q)
{
INT tmpVal = 0; //临时变量
DWORD i = 0;
if (Q < 1) Q = 1; //限制质量系数
if (Q > 100) Q = 100;
//非线性映射 1->5000, 10->500, 25->200, 50->100, 75->50, 100->0
if (Q < 50)
{
Q = 5000 / Q;
}
else
{
Q = 200 - Q * 2;
}
for (i = 0; i < DCTBLOCKSIZE; ++i)
{
tmpVal = (std_QT[i] * Q + 50L) / 100L;
if (tmpVal < 1) //数值范围限定
{
tmpVal = 1L;
}
if (tmpVal > 255)
{
tmpVal = 255L;
}
QT[FZBT[i]] = static_cast<BYTE>(tmpVal);
}
}
//////////////////////////////////////////////////////////////////////////
//为float AA&N IDCT算法初始化量化表
void JPEG_CODE::InitQTForAANDCT()
{
UINT i = 0; //临时变量
UINT j = 0;
UINT k = 0;
for (i = 0; i < DCTSIZE; i++) //初始化亮度信号量化表
{
for (j = 0; j < DCTSIZE; j++)
{
YQT_DCT[k] = (FLOAT) (1.0 / ((DOUBLE) YQT[FZBT[k]] *
aanScaleFactor[i] * aanScaleFactor[j] * 8.0));
++k;
}
}
k = 0;
for (i = 0; i < DCTSIZE; i++) //初始化色差信号量化表
{
for (j = 0; j < DCTSIZE; j++)
{
UVQT_DCT[k] = (FLOAT) (1.0 / ((DOUBLE) UVQT[FZBT[k]] *
aanScaleFactor[i] * aanScaleFactor[j] * 8.0));
++k;
}
}
}
//////////////////////////////////////////////////////////////////////////
//写文件开始标记
void JPEG_CODE::WriteSOI(void)
{
fwrite(&SOITAG,sizeof(SOITAG),1,this->pOutFile);
}
//////////////////////////////////////////////////////////////////////////
//写APP0段
void JPEG_CODE::WriteAPP0(void)
{
JPEGAPP0 APP0;
APP0.segmentTag = 0xE0FF;
APP0.length = 0x1000;
APP0.id[0] = 'J';
APP0.id[1] = 'F';
APP0.id[2] = 'I';
APP0.id[3] = 'F';
APP0.id[4] = 0;
APP0.ver = 0x0101;
APP0.densityUnit = 0x00;
APP0.densityX = 0x0100;
APP0.densityY = 0x0100;
APP0.thp = 0x00;
APP0.tvp = 0x00;
fwrite(&APP0,sizeof(APP0),1,this->pOutFile);
}
//////////////////////////////////////////////////////////////////////////
//写入DQT段
void JPEG_CODE::WriteDQT(void)
{
UINT i = 0;
JPEGDQT_8BITS DQT_Y;
DQT_Y.segmentTag = 0xDBFF;
DQT_Y.length = 0x4300;
DQT_Y.tableInfo = 0x00;
for (i = 0; i < DCTBLOCKSIZE; i++)
{
DQT_Y.table[i] = YQT[i];
}
fwrite(&DQT_Y,sizeof(DQT_Y),1,this->pOutFile);
DQT_Y.tableInfo = 0x01;
for (i = 0; i < DCTBLOCKSIZE; i++)
{
DQT_Y.table[i] = UVQT[i];
}
fwrite(&DQT_Y,sizeof(DQT_Y),1,this->pOutFile);
}
//////////////////////////////////////////////////////////////////////////
//写入SOF段
void JPEG_CODE::WriteSOF(void)
{
JPEGSOF0_24BITS SOF;
SOF.segmentTag = 0xC0FF;
SOF.length = 0x1100;
SOF.precision = 0x08;
SOF.height = Intel2Moto(USHORT(this->imgHeight));
SOF.width = Intel2Moto(USHORT(this->imgWidth));
SOF.sigNum = 0x03;
SOF.YID = 0x01;
SOF.QTY = 0x00;
SOF.UID = 0x02;
SOF.QTU = 0x01;
SOF.VID = 0x03;
SOF.QTV = 0x01;
SOF.HVU = 0x11;
SOF.HVV = 0x11;
/*switch (this->SamplingType)
{
case 1:
SOF.HVY = 0x11;
break;
case 2:
SOF.HVY = 0x12;
break;
case 3:
SOF.HVY = 0x21;
break;
case 4:
SOF.HVY = 0x22;
break;
}*/
SOF.HVY = 0x11;
fwrite(&SOF,sizeof(SOF),1,this->pOutFile);
}
//////////////////////////////////////////////////////////////////////////
//写入DHT段
void JPEG_CODE::WriteDHT(void)
{
UINT i = 0;
JPEGDHT DHT;
DHT.segmentTag = 0xC4FF;
DHT.length = Intel2Moto(19 + 12);
DHT.tableInfo = 0x00;
for (i = 0; i < 16; i++)
{
DHT.huffCode[i] = STD_DC_Y_NRCODES[i + 1];
}
fwrite(&DHT,sizeof(DHT),1,this->pOutFile);
for (i = 0; i <= 11; i++)
{
WriteByte(STD_DC_Y_VALUES[i]);
}
//------------------------------------------------
DHT.tableInfo = 0x01;
for (i = 0; i < 16; i++)
{
DHT.huffCode[i] = STD_DC_UV_NRCODES[i + 1];
}
fwrite(&DHT,sizeof(DHT),1,this->pOutFile);
for (i = 0; i <= 11; i++)
{
WriteByte(STD_DC_UV_VALUES[i]);
}
//----------------------------------------------------
DHT.length = Intel2Moto(19 + 162);
DHT.tableInfo = 0x10;
for (i = 0; i < 16; i++)
{
DHT.huffCode[i] = STD_AC_Y_NRCODES[i + 1];
}
fwrite(&DHT,sizeof(DHT),1,this->pOutFile);
for (i = 0; i <= 161; i++)
{
WriteByte(STD_AC_Y_VALUES[i]);
}
//-----------------------------------------------------
DHT.tableInfo = 0x11;
for (i = 0; i < 16; i++)
{
DHT.huffCode[i] = STD_AC_UV_NRCODES[i + 1];
}
fwrite(&DHT,sizeof(DHT),1,this->pOutFile);
for (i = 0; i <= 161; i++)
{
WriteByte(STD_AC_UV_VALUES[i]);
}
}
//////////////////////////////////////////////////////////////////////////
//写入SOS段
void JPEG_CODE::WriteSOS(void)
{
JPEGSOS_24BITS SOS;
SOS.segmentTag = 0xDAFF;
SOS.length = 0x0C00;
SOS.sigNum = 0x03;
SOS.YID = 0x01;
SOS.HTY = 0x00;
SOS.UID = 0x02;
SOS.HTU = 0x11;
SOS.VID = 0x03;
SOS.HTV = 0x11;
SOS.Se = 0x3F;
SOS.Ss = 0x00;
SOS.Bf = 0x00;
fwrite(&SOS,sizeof(SOS),1,this->pOutFile);
}
//////////////////////////////////////////////////////////////////////////
//写入文件结束标记
void JPEG_CODE::WriteEOI(void)
{
fwrite(&EOITAG,sizeof(EOITAG),1,this->pOutFile);
}
//////////////////////////////////////////////////////////////////////////
// 将高8位和低8位交换
USHORT JPEG_CODE::Intel2Moto(USHORT val)
{
BYTE highBits = BYTE(val / 256);
BYTE lowBits = BYTE(val % 256);
return lowBits * 256 + highBits;
}
//////////////////////////////////////////////////////////////////////////
//写1字节到文件
void JPEG_CODE::WriteByte(BYTE val)
{
fwrite(&val,sizeof(val),1,this->pOutFile);
}
//////////////////////////////////////////////////////////////////////////
// 生成标准Huffman表
void JPEG_CODE::BuildSTDHuffTab(BYTE* nrcodes,BYTE* stdTab,HUFFCODE* huffCode)
{
BYTE i = 0; //临时变量
BYTE j = 0;
BYTE k = 0;
USHORT code = 0;
for (i = 1; i <= 16; i++)
{
for (j = 1; j <= nrcodes[i]; j++)
{
huffCode[stdTab[k]].code = code;
huffCode[stdTab[k]].length = i;
++k;
++code;
}
code*=2;
}
for (i = 0; i < k; i++)
{
huffCode[i].val = stdTab[i];
}
}
//////////////////////////////////////////////////////////////////////////
// 处理DU(数据单元)
void JPEG_CODE::ProcessDU(FLOAT* lpBuf,FLOAT* quantTab,HUFFCODE* dcHuffTab,HUFFCODE* acHuffTab,SHORT* DC)
{
BYTE i = 0; //临时变量
UINT j = 0;
SHORT diffVal = 0; //DC差异值
BYTE acLen = 0; //熵编码后AC中间符号的数量
SHORT sigBuf[DCTBLOCKSIZE]; //量化后信号缓冲
ACSYM acSym[DCTBLOCKSIZE]; //AC中间符号缓冲
FDCT(lpBuf); //离散余弦变换
for (i = 0; i < DCTBLOCKSIZE; i++) //量化操作
{
sigBuf[FZBT[i]] = (lpBuf[i] * quantTab[i] + 16384.5) - 16384;
}
//-----------------------------------------------------
//对DC信号编码,写入文件
//DPCM编码
diffVal = sigBuf[0] - *DC;
*DC = sigBuf[0];
//搜索Huffman表,写入相应的码字
if (diffVal == 0)
{
WriteBits(dcHuffTab[0]);
}
else
{
WriteBits(dcHuffTab[pVLITAB[diffVal]]);
WriteBits(BuildSym2(diffVal));
}
//-------------------------------------------------------
//对AC信号编码并写入文件
for (i = 63; (i > 0) && (sigBuf[i] == 0); i--) //判断ac信号是否全为0
{
//注意,空循环
}
if (i == 0) //如果全为0
{
WriteBits(acHuffTab[0x00]); //写入块结束标记
}
else
{
RLEComp(sigBuf,&acSym[0],acLen); //对AC运行长度编码
for (j = 0; j < acLen; j++) //依次对AC中间符号Huffman编码
{
if (acSym[j].codeLen == 0) //是否有连续16个0
{
WriteBits(acHuffTab[0xF0]); //写入(15,0)
}
else
{
WriteBits(acHuffTab[acSym[j].zeroLen * 16 + acSym[j].codeLen]); //
WriteBits(BuildSym2(acSym[j].amplitude));
}
}
if (i != 63) //如果最后位以0结束就写入EOB
{
WriteBits(acHuffTab[0x00]);
}
}
}
//////////////////////////////////////////////////////////////////////////
// 处理图像数据FDCT-QUANT-HUFFMAN
void JPEG_CODE::ProcessData(BYTE* lpYBuf,BYTE* lpUBuf,BYTE* lpVBuf)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -