📄 jpeg_code.cpp
字号:
{
size_t yBufLen = _msize(lpYBuf); //亮度Y缓冲长度
size_t uBufLen = _msize(lpUBuf); //色差U缓冲长度
size_t vBufLen = _msize(lpVBuf); //色差V缓冲长度
FLOAT dctYBuf[DCTBLOCKSIZE]; //Y信号FDCT编码临时缓冲
FLOAT dctUBuf[DCTBLOCKSIZE]; //U信号FDCT编码临时缓冲
FLOAT dctVBuf[DCTBLOCKSIZE]; //V信号FDCT编码临时缓冲
UINT mcuNum = 0; //存放MCU的数量
SHORT yDC = 0; //Y信号的当前块的DC
SHORT uDC = 0; //U信号的当前块的DC
SHORT vDC = 0; //V信号的当前块的DC
BYTE yCounter = 0; //YUV信号各自的写入计数器
BYTE uCounter = 0;
BYTE vCounter = 0;
UINT i = 0; //临时变量
UINT j = 0;
UINT k = 0;
UINT p = 0;
UINT m = 0;
UINT n = 0;
UINT s = 0;
mcuNum = (this->buffHeight * this->buffWidth * 3)
/ (DCTBLOCKSIZE * 3); //计算MCU的数量
for (p = 0;p < mcuNum; p++) //依次生成MCU并写入
{
yCounter = 1;//MCUIndex[SamplingType][0]; //按采样方式初始化各信号计数器
uCounter = 1;//MCUIndex[SamplingType][1];
vCounter = 1;//MCUIndex[SamplingType][2];
for (; i < yBufLen; i += DCTBLOCKSIZE)
{
for (j = 0; j < DCTBLOCKSIZE; j++)
{
dctYBuf[j] = FLOAT(lpYBuf[i + j] - 128);
}
if (yCounter > 0)
{
--yCounter;
ProcessDU(dctYBuf,YQT_DCT,STD_DC_Y_HT,STD_AC_Y_HT,&yDC);
}
else
{
break;
}
}
//------------------------------------------------------------------
for (; m < uBufLen; m += DCTBLOCKSIZE)
{
for (n = 0; n < DCTBLOCKSIZE; n++)
{
dctUBuf[n] = FLOAT(lpUBuf[m + n] - 128);
}
if (uCounter > 0)
{
--uCounter;
ProcessDU(dctUBuf,UVQT_DCT,STD_DC_UV_HT,STD_AC_UV_HT,&uDC);
}
else
{
break;
}
}
//-------------------------------------------------------------------
for (; s < vBufLen; s += DCTBLOCKSIZE)
{
for (k = 0; k < DCTBLOCKSIZE; k++)
{
dctVBuf[k] = FLOAT(lpVBuf[s + k] - 128);
}
if (vCounter > 0)
{
--vCounter;
ProcessDU(dctVBuf,UVQT_DCT,STD_DC_UV_HT,STD_AC_UV_HT,&vDC);
}
else
{
break;
}
}
}
}
//////////////////////////////////////////////////////////////////////////
// 8x8的浮点离散余弦变换
void JPEG_CODE::FDCT(FLOAT* lpBuff)
{
FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
FLOAT tmp10, tmp11, tmp12, tmp13;
FLOAT z1, z2, z3, z4, z5, z11, z13;
FLOAT* dataptr;
int ctr;
/* 第一部分,对行进行计算 */
dataptr = lpBuff;
for (ctr = DCTSIZE-1; ctr >= 0; ctr--)
{
tmp0 = dataptr[0] + dataptr[7];
tmp7 = dataptr[0] - dataptr[7];
tmp1 = dataptr[1] + dataptr[6];
tmp6 = dataptr[1] - dataptr[6];
tmp2 = dataptr[2] + dataptr[5];
tmp5 = dataptr[2] - dataptr[5];
tmp3 = dataptr[3] + dataptr[4];
tmp4 = dataptr[3] - dataptr[4];
/* 对偶数项进行运算 */
tmp10 = tmp0 + tmp3; /* phase 2 */
tmp13 = tmp0 - tmp3;
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
dataptr[0] = tmp10 + tmp11; /* phase 3 */
dataptr[4] = tmp10 - tmp11;
z1 = (tmp12 + tmp13) * (0.707106781); /* c4 */
dataptr[2] = tmp13 + z1; /* phase 5 */
dataptr[6] = tmp13 - z1;
/* 对奇数项进行计算 */
tmp10 = tmp4 + tmp5; /* phase 2 */
tmp11 = tmp5 + tmp6;
tmp12 = tmp6 + tmp7;
z5 = (tmp10 - tmp12) * ( 0.382683433); /* c6 */
z2 = (0.541196100) * tmp10 + z5; /* c2-c6 */
z4 = (1.306562965) * tmp12 + z5; /* c2+c6 */
z3 = tmp11 * (0.707106781); /* c4 */
z11 = tmp7 + z3; /* phase 5 */
z13 = tmp7 - z3;
dataptr[5] = z13 + z2; /* phase 6 */
dataptr[3] = z13 - z2;
dataptr[1] = z11 + z4;
dataptr[7] = z11 - z4;
dataptr += DCTSIZE; /* 将指针指向下一行 */
}
/* 第二部分,对列进行计算 */
dataptr = lpBuff;
for (ctr = DCTSIZE-1; ctr >= 0; ctr--)
{
tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7];
tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7];
tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6];
tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6];
tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5];
tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5];
tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4];
tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4];
/* 对偶数项进行运算 */
tmp10 = tmp0 + tmp3; /* phase 2 */
tmp13 = tmp0 - tmp3;
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */
dataptr[DCTSIZE*4] = tmp10 - tmp11;
z1 = (tmp12 + tmp13) * (0.707106781); /* c4 */
dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */
dataptr[DCTSIZE*6] = tmp13 - z1;
/* 对奇数项进行计算 */
tmp10 = tmp4 + tmp5; /* phase 2 */
tmp11 = tmp5 + tmp6;
tmp12 = tmp6 + tmp7;
z5 = (tmp10 - tmp12) * (0.382683433); /* c6 */
z2 = (0.541196100) * tmp10 + z5; /* c2-c6 */
z4 = (1.306562965) * tmp12 + z5; /* c2+c6 */
z3 = tmp11 * (0.707106781); /* c4 */
z11 = tmp7 + z3; /* phase 5 */
z13 = tmp7 - z3;
dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */
dataptr[DCTSIZE*3] = z13 - z2;
dataptr[DCTSIZE*1] = z11 + z4;
dataptr[DCTSIZE*7] = z11 - z4;
++dataptr; /* 将指针指向下一列 */
}
}
//////////////////////////////////////////////////////////////////////////
// 写入二进制流
void JPEG_CODE::WriteBits(HUFFCODE huffCode)
{
WriteBitsStream(huffCode.code,huffCode.length);
}
void JPEG_CODE::WriteBits(SYM2 sym)
{
WriteBitsStream(sym.amplitude,sym.codeLen);
}
//////////////////////////////////////////////////////////////////////////
//写入二进制流
void JPEG_CODE::WriteBitsStream(USHORT value,BYTE codeLen)
{
CHAR posval;//bit position in the bitstring we read, should be<=15 and >=0
posval=codeLen-1;
while (posval>=0)
{
if (value & mask[posval])
{
bytenew|=mask[bytepos];
}
posval--;bytepos--;
if (bytepos<0)
{
if (bytenew==0xFF)
{
WriteByte(0xFF);
WriteByte(0);
}
else
{
WriteByte(bytenew);
}
bytepos=7;bytenew=0;
}
}
}
//////////////////////////////////////////////////////////////////////////
// 方法说明:使用RLE算法对AC压缩,假设输入数据1,0,0,0,3,0,5
// 输出为(0,1)(3,3)(1,5),左位表示右位数据前0的个数
// 左位用4bits表示,0的个数超过表示范围则输出为(15,0)
// 其余的0数据在下一个符号中表示.
void JPEG_CODE::RLEComp(SHORT* lpbuf,ACSYM* lpOutBuf,BYTE &resultLen)
{
BYTE zeroNum = 0; //0行程计数器
UINT EOBPos = 0; //EOB出现位置
const BYTE MAXZEROLEN = 15; //最大0行程
UINT i = 0; //临时变量
UINT j = 0;
EOBPos = DCTBLOCKSIZE - 1; //设置起始位置,从最后一个信号开始
for (i = EOBPos; i > 0; i--) //从最后的AC信号数0的个数
{
if (lpbuf[i] == 0) //判断数据是否为0
{
--EOBPos; //向前一位
}
else //遇到非0,跳出
{
break;
}
}
for (i = 1; i <= EOBPos; i++) //从第二个信号,即AC信号开始编码
{
if (lpbuf[i] == 0 && zeroNum < MAXZEROLEN) //如果信号为0并连续长度小于15
{
++zeroNum;
}
else
{
lpOutBuf[j].zeroLen = zeroNum; //0行程(连续长度)
lpOutBuf[j].codeLen = ComputeVLI(lpbuf[i]); //幅度编码长度
lpOutBuf[j].amplitude = lpbuf[i]; //振幅
zeroNum = 0; //0计数器复位
++resultLen; //符号数量++
++j; //符号计数
}
}
}
//////////////////////////////////////////////////////////////////////////
// 将信号的振幅VLI编码,返回编码长度和信号振幅的反码
SYM2 JPEG_CODE::BuildSym2(SHORT value)
{
SYM2 Symbol;
Symbol.codeLen = ComputeVLI(value); //获取编码长度
Symbol.amplitude = 0;
if (value >= 0)
{
Symbol.amplitude = value;
}
else
{
Symbol.amplitude = SHORT(pow(2,Symbol.codeLen)-1) + value; //计算反码
}
return Symbol;
}
//////////////////////////////////////////////////////////////////////////
//返回符号的长度
BYTE JPEG_CODE::ComputeVLI(SHORT val)
{
BYTE binStrLen = 0;
val = abs(val);
//获取二进制码长度
if(val == 1)
{
binStrLen = 1;
}
else if(val >= 2 && val <= 3)
{
binStrLen = 2;
}
else if(val >= 4 && val <= 7)
{
binStrLen = 3;
}
else if(val >= 8 && val <= 15)
{
binStrLen = 4;
}
else if(val >= 16 && val <= 31)
{
binStrLen = 5;
}
else if(val >= 32 && val <= 63)
{
binStrLen = 6;
}
else if(val >= 64 && val <= 127)
{
binStrLen = 7;
}
else if(val >= 128 && val <= 255)
{
binStrLen = 8;
}
else if(val >= 256 && val <= 511)
{
binStrLen = 9;
}
else if(val >= 512 && val <= 1023)
{
binStrLen = 10;
}
else if(val >= 1024 && val <= 2047)
{
binStrLen = 11;
}
return binStrLen;
}
//////////////////////////////////////////////////////////////////////////
// 生成VLI表
void JPEG_CODE::BuildVLITable(void)
{
int i = 0;
for (i = 0; i < DC_MAX_QUANTED; ++i)
{
pVLITAB[i] = ComputeVLI(i);
}
for (i = DC_MIN_QUANTED; i < 0; ++i)
{
pVLITAB[i] = ComputeVLI(i);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -