谁有关于CIF的资料?我想将得到的CIF数据转换成JPG文件,有办法吗? rt 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 http://expert.csdn.net/Expert/topic/2114/2114017.xml?temp=.5375788 我查找了很多jpeg的资料,了解了关于静止图象压缩标准,总结了有损压缩编码的文章,自己完成了一个jpeg编码类,虽然效率不高,最终还还是解决了我的问题,算是点经验吧,共享给大家。编码码的主要过程及环节:源图象数据-》块准备-》8*8DCT正变换-》量化器-》编码器-》压缩后的图象数据-》加上文件头尾-》jpeg文件下面把主要的函数贴上来,供大家参考:主编码函数:void CJpeg::Compress(BYTE *pInBuf, BYTE *pOutBuf, UINT nWidth, UINT nHeight, DWORD& dwOutSize){ ASSERT(pInBuf != NULL); ASSERT(pOutBuf != NULL); ASSERT(nWidth > 0); ASSERT(nHeight > 0); DWORD dwSize = nWidth * nHeight; dwOutSize = 0; UINT nOut = 0; int m; BYTE *pOut = pOutBuf; //开始分块 BYTE *pY0; BYTE *pY1; BYTE *pY2; BYTE *pY3; BYTE *pU; BYTE *pV; //开辟一个临时缓冲 BYTE *pTmp = new BYTE[1152]; BYTE *pTY0 = pTmp; BYTE *pTY1 = pTmp + 64; BYTE *pTY2 = pTmp + 128; BYTE *pTY3 = pTmp + 192; BYTE *pTU = pTmp + 256; BYTE *pTV = pTmp + 320; UINT x,y; UINT cx,cy; //得出总共够多少个MCU cx = nWidth / 16; cy = nHeight / 16; //对Y数据分块,取出其中的16*16 for(y = 0;y < cy; y++) { for(x = 0;x < cx;x++) { //准备MCU pY0 = pInBuf + (16 * x + nWidth * y * 16); pY1 = pY0 + 8; pY2 = pY0 + 8 * nWidth; pY3 = pY0 + 8 * nWidth + 8; pU = pInBuf + dwSize + (8 * x + 4 * nWidth * y); pV = pInBuf + dwSize + dwSize/2 + (8 * x + 4 * nWidth * y); for(m = 0;m < 8;m++) { memcpy(pTY0 + (8*m),pY0 + m*nWidth,8); memcpy(pTY1 + (8*m),pY1 + m*nWidth,8); memcpy(pTY2 + (8*m),pY2 + m*nWidth,8); memcpy(pTY3 + (8*m),pY3 + m*nWidth,8); memcpy(pTU + (8*m),pU + m*nWidth,8); memcpy(pTV + (8*m),pV + m*nWidth,8); }/* //把提取出来的一个MCU打印出来 TRACE("以下是一个MCU:\n"); for(int d = 0;d < 384;d++) { TRACE("%2X ",pTmp[d]); if((d+1)%8 == 0) { TRACE("\n"); } if((d+1)%64 == 0) { TRACE("\n"); } }*/ //压缩MCU CompressMCU(pTmp,nOut); memcpy(pOut,pTmp,nOut); pOut += nOut; } } delete [] pTmp; //如果全局的缓存中还有值的话,则把它们补足8位也写入。 if(m_nBufBit > 0) { WriteBits(0x7F,7,pOut,nOut); pOut += nOut; m_nBufBit = 0; m_BitBuf = 0; } dwOutSize = pOut - pOutBuf; //TRACE("最终输出大小为:%u\n",dwOutSize); // m_dcY = m_dcU = m_dcV = 0;}这篇文章对我起了很大作用;http://www.csdn.net/develop/article/22/22948.shtm CIF格式是YUV422格式的所以需要一个函数把YUV422转成RGB://将YUV422数据转换成RGB数据,bVertFlip决定是得到顺序RGB还是得到倒序RGB,默认倒序void CJpeg::YUVToRGB(BYTE *pInBuf, BYTE *pOutBuf, UINT nWidth, UINT nHeight,bool bVertFlip){ ASSERT(pInBuf != NULL); ASSERT(pOutBuf != NULL); ASSERT(nWidth > 0); ASSERT(nHeight > 0); BYTE Y,U,V; DWORD dwSize = nWidth * nHeight * 3; BYTE *pY = pInBuf; BYTE *pU = pInBuf + nWidth * nHeight; BYTE *pV = pInBuf + nWidth * nHeight + nWidth * nHeight/2; for(UINT y = 0;y < nHeight;y++) { //因为RGB图象的读取是从最后一行开始的,所以存储要从最后一行开始 for(UINT x = 0;x < nWidth;x++) { UINT nPos = y * nWidth + x; Y = pY[nPos]; U = pU[(DWORD)(nPos/2)]; V = pV[(DWORD)(nPos/2)]; if(bVertFlip) { //倒序 nPos = nWidth * 3 * (nHeight - y - 1) + x * 3; } else { //正序 nPos = nWidth * 3 * y + x * 3; } pOutBuf[nPos+2] = (BYTE)(Y + 1.402 * (V - 128)); pOutBuf[nPos+1] = (BYTE)(Y - 0.34414 * (U - 128) - 0.71414 * (V - 128)); pOutBuf[nPos] = (BYTE)(Y - 1.772 * (U - 128)); } }} //对一个MCU进行编码//输入为384的MCUvoid CJpeg::CompressMCU(BYTE *pBuf, UINT& nOutSize){ ASSERT(pBuf != NULL); BYTE *pIn = pBuf; UINT nOut = 0; nOutSize = 0; char *pInChar = new char[64]; short *pInt = new short[64]; BYTE *pOut = new BYTE[1152]; for(UINT i = 0;i < 6;i++) { //把输入到FDCT变换的数据缩减到-128~127 ByteToChar(pIn,pInChar); //FDCT变换 //一维变换 Fdct_1_1(pInChar,pInt); //Fdct64(pInChar,pInt); //Fdct1(pInChar,pInt); //二维变换 //Fdct2(pInChar,pInt); //量化 Quantize(pInt,i); //Huffman编码 Huffman(pInt,pOut + nOutSize,i,nOut); nOutSize += nOut; pIn += 64; } delete [] pInChar; delete [] pInt; memcpy(pBuf,pOut,nOutSize); delete [] pOut;/* TRACE("MCU编码结果:\n"); for(UINT d = 0;d < nOutSize;d++) { TRACE("%4u ",pBuf[d]); if((((d+1)%8 == 0) && (d !=0)) || (d+1 == nOutSize)) { TRACE("\n"); } }*/}void CJpeg::Fdct_1_1(char *pInBuf, short *pOutBuf){ char *pIn = pInBuf; short *pOut = pOutBuf; short tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; short tmp10, tmp11, tmp12, tmp13; short z1, z2, z3, z4, z5, z11, z13; int i; for(i = 0; i < 8; i++) { tmp0 = pIn[0] + pIn[7]; tmp7 = pIn[0] - pIn[7]; tmp1 = pIn[1] + pIn[6]; tmp6 = pIn[1] - pIn[6]; tmp2 = pIn[2] + pIn[5]; tmp5 = pIn[2] - pIn[5]; tmp3 = pIn[3] + pIn[4]; tmp4 = pIn[3] - pIn[4]; tmp10 = tmp0 + tmp3; tmp13 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp12 = tmp1 - tmp2; pOut[0] = tmp10 + tmp11; pOut[4] = tmp10 - tmp11; z1 = (short)((tmp12 + tmp13) * 0.707106781); pOut[2] = tmp13 + z1; pOut[6] = tmp13 - z1; tmp10 = tmp4 + tmp5; tmp11 = tmp5 + tmp6; tmp12 = tmp6 + tmp7; z5 = (short)((tmp10 - tmp12) * 0.382683433); z2 = (short)(0.541196100 * tmp10 + z5); z4 = (short)(1.306562965 * tmp12 + z5); z3 = (short)(tmp11 * 0.707106781); z11 = tmp7 + z3; z13 = tmp7 - z3; pOut[5] = z13 + z2; pOut[3] = z13 - z2; pOut[1] = z11 + z4; pOut[7] = z11 - z4; pIn += 8; pOut += 8; } pOut = pOutBuf; for (i = 0; i < 8; i++) { tmp0 = pOut[0] + pOut[56]; tmp7 = pOut[0] - pOut[56]; tmp1 = pOut[8] + pOut[48]; tmp6 = pOut[8] - pOut[48]; tmp2 = pOut[16] + pOut[40]; tmp5 = pOut[16] - pOut[40]; tmp3 = pOut[24] + pOut[32]; tmp4 = pOut[24] - pOut[32]; tmp10 = tmp0 + tmp3; tmp13 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp12 = tmp1 - tmp2; pOut[0] = tmp10 + tmp11; pOut[32] = tmp10 - tmp11; z1 = (short)((tmp12 + tmp13) * 0.707106781); pOut[16] = tmp13 + z1; pOut[48] = tmp13 - z1; tmp10 = tmp4 + tmp5; tmp11 = tmp5 + tmp6; tmp12 = tmp6 + tmp7; z5 = (short)((tmp10 - tmp12) * 0.382683433); z2 = (short)(0.541196100 * tmp10 + z5); z4 = (short)(1.306562965 * tmp12 + z5); z3 = (short)(tmp11 * 0.707106781); z11 = tmp7 + z3; z13 = tmp7 - z3; pOut[40] = z13 + z2; pOut[24] = z13 - z2; pOut[8] = z11 + z4; pOut[56] = z11 - z4; pOut++; }/* TRACE("以下是经过一维FDCT变换后的数据:\n"); for(int d = 0;d<64;d++) { TRACE("%5d ",pOutBuf[d]); if((d+1)%8 ==0) { TRACE("\n"); } }*/}//量化函数void CJpeg::Quantize(short *pBuf, UINT nType){ BYTE *pQuanTbl; double f; pQuanTbl = (nType < 4)?m_QuanYEnc:m_QuanUVEnc; for(UINT i = 0;i < 64;i++) { //取整 f = pBuf[i]/pQuanTbl[i]; if(f >= 0) { f += 0.5; } else { f -= 0.5; } pBuf[i] = (short)f; }/* TRACE("%u量化后的结果:\n",nType); TRACE("输入地址为:%u\n",pBuf); for(int d = 0;d < 64;d++) { TRACE("%3d,",pBuf[d]); if((d+1)%8==0) { TRACE("\n"); } }*/}//对Y8*8矩阵进行Huffman编码//其中首先包含了对DC进行的DPCM编码和对AC的RLN编码//接着进行Huffman编码void CJpeg::Huffman(short *pInBuf, BYTE *pOutBuf, UINT nType, UINT &nOutBytes){ ASSERT(pInBuf != NULL); ASSERT(pOutBuf != NULL); ASSERT(nType >=0 && nType < 6); //输出指针 BYTE *pOut = pOutBuf; //数据、差值的位数 USHORT nBits = 0; //差值或者数据 int iDiff0,iDiff1; //最终输出数据字节数 nOutBytes = 0; //临时输出数据长度,每个WriteBits写入的字节数 UINT nOut = 0; //指定使用的Huffman表 BYTE *bitDC; USHORT *valDC; BYTE *bitAC; USHORT *valAC; //上次保留下来的DC值的指针 short *pLastDC; //根据不同的类型给出不同的Huffman编码表 //pLastDC代表上一个8*8矩阵中DC的值,并保留下在本矩阵中DC值 if(nType < 4) { bitDC = m_bitYDC; valDC = m_valYDC; bitAC = m_bitYAC; valAC = m_valYAC; pLastDC = &m_dcY; } else { bitDC = m_bitUVDC; valDC = m_valUVDC; bitAC = m_bitUVAC; valAC = m_valUVAC; pLastDC = (nType == 4)?&m_dcU:&m_dcV; } ////////////////////////////////////////////////////////////////////////// // 对DC采用APCM编码,差分编码 //开始DC Huffman编码 iDiff0 = iDiff1 = pInBuf[0] - *pLastDC; *pLastDC = pInBuf[0]; //如果是负数,则求绝对值和反码 if(iDiff0 < 0) { //求绝对值 iDiff0 = -iDiff0; //取绝对值的反码 iDiff1 = ~iDiff0; } //求得码长 while(iDiff0) { nBits++; iDiff0 >>= 1; } //写入DC Huffman 识别码(标志码)/* TRACE("DC标志码 : Value : 0x%X Bits : %u \n",valDC[nBits],bitDC[nBits]); TRACE("DC : Value : 0x%X Bits : %u \n",iDiff1,nBits);*/ WriteBits(valDC[nBits],bitDC[nBits],pOut,nOut); pOut += nOut; //写入DC差值二进制码 WriteBits(iDiff1,nBits,pOut,nOut); pOut += nOut; //DC Hufman编码结束 ////////////////////////////////////////////////////////////////////////// // 对AC采用RLE编码,游程编码 //开始AC Huffman编码 BYTE nZeroAc = 0; BYTE n = 0; for(UINT i = 1;i < 64;i++) { iDiff0 = iDiff1 = pInBuf[m_ZagZig[i]]; if(iDiff0 == 0) { //统计连续零的个数 nZeroAc++; } else { while(nZeroAc > 15) { //如果连续的零超过15个则写入一个F0标志,代表此处有16个零 WriteBits(valAC[0xF0],bitAC[0xF0],pOut,nOut); //WriteBits(0x7F9,11,pOut,nOut); pOut += nOut; nZeroAc -= 16; } //求绝对值和反码 if(iDiff0 < 0) { iDiff0 = -iDiff0; //取反码 iDiff1 = ~iDiff0; } //求得码长,码长至少为1,不可能为零 nBits = 1; while(iDiff0 >>= 1) { nBits++; }/* TRACE("0的个数 : 0x%X \n",nZeroAc); TRACE("AC标志码 : Value : 0x%X Bits : %u \n",valAC[nBits],bitAC[nBits]); TRACE("AC : Value : 0x%X Bits : %u \n",iDiff1,nBits);*/ //编码格式为:(零的个数+AC值编码位数)(正好一个字节,Huffman编码)+AC值(Huffman编码) //1. 把0的个数和AC值编码位数合并成一个字节 n = (nZeroAc << 4) + nBits; WriteBits(valAC[n],bitAC[n],pOut,nOut); pOut += nOut; //2. 写入AC数据 WriteBits(iDiff1,nBits,pOut,nOut); pOut += nOut; nZeroAc = 0; } } if(nZeroAc > 0) { //说明后面全是零 WriteBits(valAC[0],bitAC[0],pOut,nOut); //WriteBits(10,4,pOut,nOut); pOut += nOut; } //AC 编码结束 nOutBytes = pOut - pOutBuf;/* TRACE("Huffman编码后,%u块输出大小为:%u\n",nType,nOutBytes); for(UINT d = 0;d < nOutBytes;d++) { TRACE("%3d ",pOutBuf[d]); if((d+1)%8==0 || d+1 == nOutBytes) { TRACE("\n"); } }*/} //对一个MCU进行编码//输入为384的MCUvoid CJpeg::CompressMCU(BYTE *pBuf, UINT& nOutSize){ ASSERT(pBuf != NULL); BYTE *pIn = pBuf; UINT nOut = 0; nOutSize = 0; char *pInChar = new char[64]; short *pInt = new short[64]; BYTE *pOut = new BYTE[1152]; for(UINT i = 0;i < 6;i++) { //把输入到FDCT变换的数据缩减到-128~127 ByteToChar(pIn,pInChar); //FDCT变换 //一维变换 Fdct_1_1(pInChar,pInt); //Fdct64(pInChar,pInt); //Fdct1(pInChar,pInt); //二维变换 //Fdct2(pInChar,pInt); //量化 Quantize(pInt,i); //Huffman编码 Huffman(pInt,pOut + nOutSize,i,nOut); nOutSize += nOut; pIn += 64; } delete [] pInChar; delete [] pInt; memcpy(pBuf,pOut,nOutSize); delete [] pOut;/* TRACE("MCU编码结果:\n"); for(UINT d = 0;d < nOutSize;d++) { TRACE("%4u ",pBuf[d]); if((((d+1)%8 == 0) && (d !=0)) || (d+1 == nOutSize)) { TRACE("\n"); } }*/}void CJpeg::Fdct_1_1(char *pInBuf, short *pOutBuf){ char *pIn = pInBuf; short *pOut = pOutBuf; short tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; short tmp10, tmp11, tmp12, tmp13; short z1, z2, z3, z4, z5, z11, z13; int i; for(i = 0; i < 8; i++) { tmp0 = pIn[0] + pIn[7]; tmp7 = pIn[0] - pIn[7]; tmp1 = pIn[1] + pIn[6]; tmp6 = pIn[1] - pIn[6]; tmp2 = pIn[2] + pIn[5]; tmp5 = pIn[2] - pIn[5]; tmp3 = pIn[3] + pIn[4]; tmp4 = pIn[3] - pIn[4]; tmp10 = tmp0 + tmp3; tmp13 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp12 = tmp1 - tmp2; pOut[0] = tmp10 + tmp11; pOut[4] = tmp10 - tmp11; z1 = (short)((tmp12 + tmp13) * 0.707106781); pOut[2] = tmp13 + z1; pOut[6] = tmp13 - z1; tmp10 = tmp4 + tmp5; tmp11 = tmp5 + tmp6; tmp12 = tmp6 + tmp7; z5 = (short)((tmp10 - tmp12) * 0.382683433); z2 = (short)(0.541196100 * tmp10 + z5); z4 = (short)(1.306562965 * tmp12 + z5); z3 = (short)(tmp11 * 0.707106781); z11 = tmp7 + z3; z13 = tmp7 - z3; pOut[5] = z13 + z2; pOut[3] = z13 - z2; pOut[1] = z11 + z4; pOut[7] = z11 - z4; pIn += 8; pOut += 8; } pOut = pOutBuf; for (i = 0; i < 8; i++) { tmp0 = pOut[0] + pOut[56]; tmp7 = pOut[0] - pOut[56]; tmp1 = pOut[8] + pOut[48]; tmp6 = pOut[8] - pOut[48]; tmp2 = pOut[16] + pOut[40]; tmp5 = pOut[16] - pOut[40]; tmp3 = pOut[24] + pOut[32]; tmp4 = pOut[24] - pOut[32]; tmp10 = tmp0 + tmp3; tmp13 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp12 = tmp1 - tmp2; pOut[0] = tmp10 + tmp11; pOut[32] = tmp10 - tmp11; z1 = (short)((tmp12 + tmp13) * 0.707106781); pOut[16] = tmp13 + z1; pOut[48] = tmp13 - z1; tmp10 = tmp4 + tmp5; tmp11 = tmp5 + tmp6; tmp12 = tmp6 + tmp7; z5 = (short)((tmp10 - tmp12) * 0.382683433); z2 = (short)(0.541196100 * tmp10 + z5); z4 = (short)(1.306562965 * tmp12 + z5); z3 = (short)(tmp11 * 0.707106781); z11 = tmp7 + z3; z13 = tmp7 - z3; pOut[40] = z13 + z2; pOut[24] = z13 - z2; pOut[8] = z11 + z4; pOut[56] = z11 - z4; pOut++; }/* TRACE("以下是经过一维FDCT变换后的数据:\n"); for(int d = 0;d<64;d++) { TRACE("%5d ",pOutBuf[d]); if((d+1)%8 ==0) { TRACE("\n"); } }*/}//量化函数void CJpeg::Quantize(short *pBuf, UINT nType){ BYTE *pQuanTbl; double f; pQuanTbl = (nType < 4)?m_QuanYEnc:m_QuanUVEnc; for(UINT i = 0;i < 64;i++) { //取整 f = pBuf[i]/pQuanTbl[i]; if(f >= 0) { f += 0.5; } else { f -= 0.5; } pBuf[i] = (short)f; }/* TRACE("%u量化后的结果:\n",nType); TRACE("输入地址为:%u\n",pBuf); for(int d = 0;d < 64;d++) { TRACE("%3d,",pBuf[d]); if((d+1)%8==0) { TRACE("\n"); } }*/}//对Y8*8矩阵进行Huffman编码//其中首先包含了对DC进行的DPCM编码和对AC的RLN编码//接着进行Huffman编码void CJpeg::Huffman(short *pInBuf, BYTE *pOutBuf, UINT nType, UINT &nOutBytes){ ASSERT(pInBuf != NULL); ASSERT(pOutBuf != NULL); ASSERT(nType >=0 && nType < 6); //输出指针 BYTE *pOut = pOutBuf; //数据、差值的位数 USHORT nBits = 0; //差值或者数据 int iDiff0,iDiff1; //最终输出数据字节数 nOutBytes = 0; //临时输出数据长度,每个WriteBits写入的字节数 UINT nOut = 0; //指定使用的Huffman表 BYTE *bitDC; USHORT *valDC; BYTE *bitAC; USHORT *valAC; //上次保留下来的DC值的指针 short *pLastDC; //根据不同的类型给出不同的Huffman编码表 //pLastDC代表上一个8*8矩阵中DC的值,并保留下在本矩阵中DC值 if(nType < 4) { bitDC = m_bitYDC; valDC = m_valYDC; bitAC = m_bitYAC; valAC = m_valYAC; pLastDC = &m_dcY; } else { bitDC = m_bitUVDC; valDC = m_valUVDC; bitAC = m_bitUVAC; valAC = m_valUVAC; pLastDC = (nType == 4)?&m_dcU:&m_dcV; } ////////////////////////////////////////////////////////////////////////// // 对DC采用APCM编码,差分编码 //开始DC Huffman编码 iDiff0 = iDiff1 = pInBuf[0] - *pLastDC; *pLastDC = pInBuf[0]; //如果是负数,则求绝对值和反码 if(iDiff0 < 0) { //求绝对值 iDiff0 = -iDiff0; //取绝对值的反码 iDiff1 = ~iDiff0; } //求得码长 while(iDiff0) { nBits++; iDiff0 >>= 1; } //写入DC Huffman 识别码(标志码)/* TRACE("DC标志码 : Value : 0x%X Bits : %u \n",valDC[nBits],bitDC[nBits]); TRACE("DC : Value : 0x%X Bits : %u \n",iDiff1,nBits);*/ WriteBits(valDC[nBits],bitDC[nBits],pOut,nOut); pOut += nOut; //写入DC差值二进制码 WriteBits(iDiff1,nBits,pOut,nOut); pOut += nOut; //DC Hufman编码结束 ////////////////////////////////////////////////////////////////////////// // 对AC采用RLE编码,游程编码 //开始AC Huffman编码 BYTE nZeroAc = 0; BYTE n = 0; for(UINT i = 1;i < 64;i++) { iDiff0 = iDiff1 = pInBuf[m_ZagZig[i]]; if(iDiff0 == 0) { //统计连续零的个数 nZeroAc++; } else { while(nZeroAc > 15) { //如果连续的零超过15个则写入一个F0标志,代表此处有16个零 WriteBits(valAC[0xF0],bitAC[0xF0],pOut,nOut); //WriteBits(0x7F9,11,pOut,nOut); pOut += nOut; nZeroAc -= 16; } //求绝对值和反码 if(iDiff0 < 0) { iDiff0 = -iDiff0; //取反码 iDiff1 = ~iDiff0; } //求得码长,码长至少为1,不可能为零 nBits = 1; while(iDiff0 >>= 1) { nBits++; }/* TRACE("0的个数 : 0x%X \n",nZeroAc); TRACE("AC标志码 : Value : 0x%X Bits : %u \n",valAC[nBits],bitAC[nBits]); TRACE("AC : Value : 0x%X Bits : %u \n",iDiff1,nBits);*/ //编码格式为:(零的个数+AC值编码位数)(正好一个字节,Huffman编码)+AC值(Huffman编码) //1. 把0的个数和AC值编码位数合并成一个字节 n = (nZeroAc << 4) + nBits; WriteBits(valAC[n],bitAC[n],pOut,nOut); pOut += nOut; //2. 写入AC数据 WriteBits(iDiff1,nBits,pOut,nOut); pOut += nOut; nZeroAc = 0; } } if(nZeroAc > 0) { //说明后面全是零 WriteBits(valAC[0],bitAC[0],pOut,nOut); //WriteBits(10,4,pOut,nOut); pOut += nOut; } //AC 编码结束 nOutBytes = pOut - pOutBuf;/* TRACE("Huffman编码后,%u块输出大小为:%u\n",nType,nOutBytes); for(UINT d = 0;d < nOutBytes;d++) { TRACE("%3d ",pOutBuf[d]); if((d+1)%8==0 || d+1 == nOutBytes) { TRACE("\n"); } }*/} 如何使得程序能在没有人使用时执行指定操作 关于串口复用的重重疑云 如何将注册表一个项的子项列表导入到 listview中 如果不用MFC 消息映射如何实现? 急,有没有像打开文件对话框中显示的那系列控件? 在运行时的错误,看不懂! 请问在Web Browser控件时如何隐藏滚动条并且自由设置网页在控件中的位置? 关于编码的问题 关于《C++大学教程》第二版第六章中的程序例怎么用VC++6.0实现? ICMPV6的困惑 ::HttpSendRequest 不返回怎么办? 如何在PreTranslateMessage中捕获组合键?比如Shift+Tab
主编码函数:
void CJpeg::Compress(BYTE *pInBuf, BYTE *pOutBuf, UINT nWidth, UINT nHeight, DWORD& dwOutSize)
{
ASSERT(pInBuf != NULL);
ASSERT(pOutBuf != NULL);
ASSERT(nWidth > 0);
ASSERT(nHeight > 0);
DWORD dwSize = nWidth * nHeight;
dwOutSize = 0;
UINT nOut = 0;
int m;
BYTE *pOut = pOutBuf; //开始分块
BYTE *pY0;
BYTE *pY1;
BYTE *pY2;
BYTE *pY3;
BYTE *pU;
BYTE *pV; //开辟一个临时缓冲
BYTE *pTmp = new BYTE[1152];
BYTE *pTY0 = pTmp;
BYTE *pTY1 = pTmp + 64;
BYTE *pTY2 = pTmp + 128;
BYTE *pTY3 = pTmp + 192;
BYTE *pTU = pTmp + 256;
BYTE *pTV = pTmp + 320; UINT x,y;
UINT cx,cy;
//得出总共够多少个MCU
cx = nWidth / 16;
cy = nHeight / 16; //对Y数据分块,取出其中的16*16
for(y = 0;y < cy; y++)
{
for(x = 0;x < cx;x++)
{
//准备MCU
pY0 = pInBuf + (16 * x + nWidth * y * 16);
pY1 = pY0 + 8;
pY2 = pY0 + 8 * nWidth;
pY3 = pY0 + 8 * nWidth + 8;
pU = pInBuf + dwSize + (8 * x + 4 * nWidth * y);
pV = pInBuf + dwSize + dwSize/2 + (8 * x + 4 * nWidth * y); for(m = 0;m < 8;m++)
{
memcpy(pTY0 + (8*m),pY0 + m*nWidth,8);
memcpy(pTY1 + (8*m),pY1 + m*nWidth,8);
memcpy(pTY2 + (8*m),pY2 + m*nWidth,8);
memcpy(pTY3 + (8*m),pY3 + m*nWidth,8);
memcpy(pTU + (8*m),pU + m*nWidth,8);
memcpy(pTV + (8*m),pV + m*nWidth,8);
}
/*
//把提取出来的一个MCU打印出来
TRACE("以下是一个MCU:\n");
for(int d = 0;d < 384;d++)
{
TRACE("%2X ",pTmp[d]);
if((d+1)%8 == 0)
{
TRACE("\n");
}
if((d+1)%64 == 0)
{
TRACE("\n");
}
}
*/
//压缩MCU
CompressMCU(pTmp,nOut);
memcpy(pOut,pTmp,nOut);
pOut += nOut;
}
} delete [] pTmp; //如果全局的缓存中还有值的话,则把它们补足8位也写入。
if(m_nBufBit > 0)
{
WriteBits(0x7F,7,pOut,nOut);
pOut += nOut;
m_nBufBit = 0;
m_BitBuf = 0;
}
dwOutSize = pOut - pOutBuf;
//TRACE("最终输出大小为:%u\n",dwOutSize);
//
m_dcY = m_dcU = m_dcV = 0;
}
这篇文章对我起了很大作用;
http://www.csdn.net/develop/article/22/22948.shtm
//将YUV422数据转换成RGB数据,bVertFlip决定是得到顺序RGB还是得到倒序RGB,默认倒序
void CJpeg::YUVToRGB(BYTE *pInBuf, BYTE *pOutBuf, UINT nWidth, UINT nHeight,bool bVertFlip)
{
ASSERT(pInBuf != NULL);
ASSERT(pOutBuf != NULL);
ASSERT(nWidth > 0);
ASSERT(nHeight > 0); BYTE Y,U,V;
DWORD dwSize = nWidth * nHeight * 3;
BYTE *pY = pInBuf;
BYTE *pU = pInBuf + nWidth * nHeight;
BYTE *pV = pInBuf + nWidth * nHeight + nWidth * nHeight/2;
for(UINT y = 0;y < nHeight;y++)
{
//因为RGB图象的读取是从最后一行开始的,所以存储要从最后一行开始
for(UINT x = 0;x < nWidth;x++)
{
UINT nPos = y * nWidth + x;
Y = pY[nPos];
U = pU[(DWORD)(nPos/2)];
V = pV[(DWORD)(nPos/2)]; if(bVertFlip)
{
//倒序
nPos = nWidth * 3 * (nHeight - y - 1) + x * 3;
}
else
{
//正序
nPos = nWidth * 3 * y + x * 3;
}
pOutBuf[nPos+2] = (BYTE)(Y + 1.402 * (V - 128));
pOutBuf[nPos+1] = (BYTE)(Y - 0.34414 * (U - 128) - 0.71414 * (V - 128));
pOutBuf[nPos] = (BYTE)(Y - 1.772 * (U - 128));
}
}
}
//输入为384的MCU
void CJpeg::CompressMCU(BYTE *pBuf, UINT& nOutSize)
{
ASSERT(pBuf != NULL);
BYTE *pIn = pBuf;
UINT nOut = 0;
nOutSize = 0; char *pInChar = new char[64];
short *pInt = new short[64];
BYTE *pOut = new BYTE[1152]; for(UINT i = 0;i < 6;i++)
{
//把输入到FDCT变换的数据缩减到-128~127
ByteToChar(pIn,pInChar); //FDCT变换
//一维变换
Fdct_1_1(pInChar,pInt); //Fdct64(pInChar,pInt); //Fdct1(pInChar,pInt); //二维变换
//Fdct2(pInChar,pInt);
//量化
Quantize(pInt,i); //Huffman编码
Huffman(pInt,pOut + nOutSize,i,nOut);
nOutSize += nOut; pIn += 64;
} delete [] pInChar;
delete [] pInt;
memcpy(pBuf,pOut,nOutSize);
delete [] pOut;/*
TRACE("MCU编码结果:\n");
for(UINT d = 0;d < nOutSize;d++)
{
TRACE("%4u ",pBuf[d]);
if((((d+1)%8 == 0) && (d !=0)) || (d+1 == nOutSize))
{
TRACE("\n");
}
}
*/
}
void CJpeg::Fdct_1_1(char *pInBuf, short *pOutBuf)
{
char *pIn = pInBuf;
short *pOut = pOutBuf; short tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
short tmp10, tmp11, tmp12, tmp13;
short z1, z2, z3, z4, z5, z11, z13;
int i;
for(i = 0; i < 8; i++)
{
tmp0 = pIn[0] + pIn[7];
tmp7 = pIn[0] - pIn[7];
tmp1 = pIn[1] + pIn[6];
tmp6 = pIn[1] - pIn[6];
tmp2 = pIn[2] + pIn[5];
tmp5 = pIn[2] - pIn[5];
tmp3 = pIn[3] + pIn[4];
tmp4 = pIn[3] - pIn[4];
tmp10 = tmp0 + tmp3;
tmp13 = tmp0 - tmp3;
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
pOut[0] = tmp10 + tmp11;
pOut[4] = tmp10 - tmp11;
z1 = (short)((tmp12 + tmp13) * 0.707106781);
pOut[2] = tmp13 + z1;
pOut[6] = tmp13 - z1;
tmp10 = tmp4 + tmp5;
tmp11 = tmp5 + tmp6;
tmp12 = tmp6 + tmp7;
z5 = (short)((tmp10 - tmp12) * 0.382683433);
z2 = (short)(0.541196100 * tmp10 + z5);
z4 = (short)(1.306562965 * tmp12 + z5);
z3 = (short)(tmp11 * 0.707106781);
z11 = tmp7 + z3;
z13 = tmp7 - z3;
pOut[5] = z13 + z2;
pOut[3] = z13 - z2;
pOut[1] = z11 + z4;
pOut[7] = z11 - z4; pIn += 8;
pOut += 8;
} pOut = pOutBuf;
for (i = 0; i < 8; i++)
{
tmp0 = pOut[0] + pOut[56];
tmp7 = pOut[0] - pOut[56];
tmp1 = pOut[8] + pOut[48];
tmp6 = pOut[8] - pOut[48];
tmp2 = pOut[16] + pOut[40];
tmp5 = pOut[16] - pOut[40];
tmp3 = pOut[24] + pOut[32];
tmp4 = pOut[24] - pOut[32];
tmp10 = tmp0 + tmp3;
tmp13 = tmp0 - tmp3;
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
pOut[0] = tmp10 + tmp11;
pOut[32] = tmp10 - tmp11;
z1 = (short)((tmp12 + tmp13) * 0.707106781);
pOut[16] = tmp13 + z1;
pOut[48] = tmp13 - z1;
tmp10 = tmp4 + tmp5;
tmp11 = tmp5 + tmp6;
tmp12 = tmp6 + tmp7;
z5 = (short)((tmp10 - tmp12) * 0.382683433);
z2 = (short)(0.541196100 * tmp10 + z5);
z4 = (short)(1.306562965 * tmp12 + z5);
z3 = (short)(tmp11 * 0.707106781);
z11 = tmp7 + z3;
z13 = tmp7 - z3;
pOut[40] = z13 + z2;
pOut[24] = z13 - z2;
pOut[8] = z11 + z4;
pOut[56] = z11 - z4; pOut++;
}
/*
TRACE("以下是经过一维FDCT变换后的数据:\n");
for(int d = 0;d<64;d++)
{
TRACE("%5d ",pOutBuf[d]);
if((d+1)%8 ==0)
{
TRACE("\n");
}
}
*/
}//量化函数
void CJpeg::Quantize(short *pBuf, UINT nType)
{
BYTE *pQuanTbl;
double f; pQuanTbl = (nType < 4)?m_QuanYEnc:m_QuanUVEnc; for(UINT i = 0;i < 64;i++)
{
//取整
f = pBuf[i]/pQuanTbl[i];
if(f >= 0)
{
f += 0.5;
}
else
{
f -= 0.5;
}
pBuf[i] = (short)f;
}
/*
TRACE("%u量化后的结果:\n",nType);
TRACE("输入地址为:%u\n",pBuf);
for(int d = 0;d < 64;d++)
{
TRACE("%3d,",pBuf[d]);
if((d+1)%8==0)
{
TRACE("\n");
}
}
*/
}//对Y8*8矩阵进行Huffman编码
//其中首先包含了对DC进行的DPCM编码和对AC的RLN编码
//接着进行Huffman编码
void CJpeg::Huffman(short *pInBuf, BYTE *pOutBuf, UINT nType, UINT &nOutBytes)
{
ASSERT(pInBuf != NULL);
ASSERT(pOutBuf != NULL);
ASSERT(nType >=0 && nType < 6); //输出指针
BYTE *pOut = pOutBuf;
//数据、差值的位数
USHORT nBits = 0;
//差值或者数据
int iDiff0,iDiff1;
//最终输出数据字节数
nOutBytes = 0;
//临时输出数据长度,每个WriteBits写入的字节数
UINT nOut = 0; //指定使用的Huffman表
BYTE *bitDC;
USHORT *valDC;
BYTE *bitAC;
USHORT *valAC;
//上次保留下来的DC值的指针
short *pLastDC; //根据不同的类型给出不同的Huffman编码表
//pLastDC代表上一个8*8矩阵中DC的值,并保留下在本矩阵中DC值
if(nType < 4)
{
bitDC = m_bitYDC;
valDC = m_valYDC;
bitAC = m_bitYAC;
valAC = m_valYAC;
pLastDC = &m_dcY;
}
else
{
bitDC = m_bitUVDC;
valDC = m_valUVDC;
bitAC = m_bitUVAC;
valAC = m_valUVAC;
pLastDC = (nType == 4)?&m_dcU:&m_dcV;
} //////////////////////////////////////////////////////////////////////////
// 对DC采用APCM编码,差分编码
//开始DC Huffman编码
iDiff0 = iDiff1 = pInBuf[0] - *pLastDC;
*pLastDC = pInBuf[0]; //如果是负数,则求绝对值和反码
if(iDiff0 < 0)
{
//求绝对值
iDiff0 = -iDiff0;
//取绝对值的反码
iDiff1 = ~iDiff0;
}
//求得码长
while(iDiff0)
{
nBits++;
iDiff0 >>= 1;
} //写入DC Huffman 识别码(标志码)
/*
TRACE("DC标志码 : Value : 0x%X Bits : %u \n",valDC[nBits],bitDC[nBits]);
TRACE("DC : Value : 0x%X Bits : %u \n",iDiff1,nBits);
*/
WriteBits(valDC[nBits],bitDC[nBits],pOut,nOut);
pOut += nOut;
//写入DC差值二进制码
WriteBits(iDiff1,nBits,pOut,nOut);
pOut += nOut; //DC Hufman编码结束 //////////////////////////////////////////////////////////////////////////
// 对AC采用RLE编码,游程编码
//开始AC Huffman编码
BYTE nZeroAc = 0;
BYTE n = 0;
for(UINT i = 1;i < 64;i++)
{
iDiff0 = iDiff1 = pInBuf[m_ZagZig[i]];
if(iDiff0 == 0)
{
//统计连续零的个数
nZeroAc++;
}
else
{
while(nZeroAc > 15)
{
//如果连续的零超过15个则写入一个F0标志,代表此处有16个零
WriteBits(valAC[0xF0],bitAC[0xF0],pOut,nOut);
//WriteBits(0x7F9,11,pOut,nOut);
pOut += nOut; nZeroAc -= 16;
}
//求绝对值和反码
if(iDiff0 < 0)
{
iDiff0 = -iDiff0;
//取反码
iDiff1 = ~iDiff0;
}
//求得码长,码长至少为1,不可能为零
nBits = 1;
while(iDiff0 >>= 1)
{
nBits++;
}
/*
TRACE("0的个数 : 0x%X \n",nZeroAc);
TRACE("AC标志码 : Value : 0x%X Bits : %u \n",valAC[nBits],bitAC[nBits]);
TRACE("AC : Value : 0x%X Bits : %u \n",iDiff1,nBits);
*/
//编码格式为:(零的个数+AC值编码位数)(正好一个字节,Huffman编码)+AC值(Huffman编码)
//1. 把0的个数和AC值编码位数合并成一个字节
n = (nZeroAc << 4) + nBits;
WriteBits(valAC[n],bitAC[n],pOut,nOut);
pOut += nOut; //2. 写入AC数据
WriteBits(iDiff1,nBits,pOut,nOut);
pOut += nOut; nZeroAc = 0;
}
}
if(nZeroAc > 0)
{
//说明后面全是零
WriteBits(valAC[0],bitAC[0],pOut,nOut);
//WriteBits(10,4,pOut,nOut);
pOut += nOut;
}
//AC 编码结束
nOutBytes = pOut - pOutBuf;
/*
TRACE("Huffman编码后,%u块输出大小为:%u\n",nType,nOutBytes);
for(UINT d = 0;d < nOutBytes;d++)
{
TRACE("%3d ",pOutBuf[d]);
if((d+1)%8==0 || d+1 == nOutBytes)
{
TRACE("\n");
}
}
*/
}
//输入为384的MCU
void CJpeg::CompressMCU(BYTE *pBuf, UINT& nOutSize)
{
ASSERT(pBuf != NULL);
BYTE *pIn = pBuf;
UINT nOut = 0;
nOutSize = 0; char *pInChar = new char[64];
short *pInt = new short[64];
BYTE *pOut = new BYTE[1152]; for(UINT i = 0;i < 6;i++)
{
//把输入到FDCT变换的数据缩减到-128~127
ByteToChar(pIn,pInChar); //FDCT变换
//一维变换
Fdct_1_1(pInChar,pInt); //Fdct64(pInChar,pInt); //Fdct1(pInChar,pInt); //二维变换
//Fdct2(pInChar,pInt);
//量化
Quantize(pInt,i); //Huffman编码
Huffman(pInt,pOut + nOutSize,i,nOut);
nOutSize += nOut; pIn += 64;
} delete [] pInChar;
delete [] pInt;
memcpy(pBuf,pOut,nOutSize);
delete [] pOut;/*
TRACE("MCU编码结果:\n");
for(UINT d = 0;d < nOutSize;d++)
{
TRACE("%4u ",pBuf[d]);
if((((d+1)%8 == 0) && (d !=0)) || (d+1 == nOutSize))
{
TRACE("\n");
}
}
*/
}
void CJpeg::Fdct_1_1(char *pInBuf, short *pOutBuf)
{
char *pIn = pInBuf;
short *pOut = pOutBuf; short tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
short tmp10, tmp11, tmp12, tmp13;
short z1, z2, z3, z4, z5, z11, z13;
int i;
for(i = 0; i < 8; i++)
{
tmp0 = pIn[0] + pIn[7];
tmp7 = pIn[0] - pIn[7];
tmp1 = pIn[1] + pIn[6];
tmp6 = pIn[1] - pIn[6];
tmp2 = pIn[2] + pIn[5];
tmp5 = pIn[2] - pIn[5];
tmp3 = pIn[3] + pIn[4];
tmp4 = pIn[3] - pIn[4];
tmp10 = tmp0 + tmp3;
tmp13 = tmp0 - tmp3;
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
pOut[0] = tmp10 + tmp11;
pOut[4] = tmp10 - tmp11;
z1 = (short)((tmp12 + tmp13) * 0.707106781);
pOut[2] = tmp13 + z1;
pOut[6] = tmp13 - z1;
tmp10 = tmp4 + tmp5;
tmp11 = tmp5 + tmp6;
tmp12 = tmp6 + tmp7;
z5 = (short)((tmp10 - tmp12) * 0.382683433);
z2 = (short)(0.541196100 * tmp10 + z5);
z4 = (short)(1.306562965 * tmp12 + z5);
z3 = (short)(tmp11 * 0.707106781);
z11 = tmp7 + z3;
z13 = tmp7 - z3;
pOut[5] = z13 + z2;
pOut[3] = z13 - z2;
pOut[1] = z11 + z4;
pOut[7] = z11 - z4; pIn += 8;
pOut += 8;
} pOut = pOutBuf;
for (i = 0; i < 8; i++)
{
tmp0 = pOut[0] + pOut[56];
tmp7 = pOut[0] - pOut[56];
tmp1 = pOut[8] + pOut[48];
tmp6 = pOut[8] - pOut[48];
tmp2 = pOut[16] + pOut[40];
tmp5 = pOut[16] - pOut[40];
tmp3 = pOut[24] + pOut[32];
tmp4 = pOut[24] - pOut[32];
tmp10 = tmp0 + tmp3;
tmp13 = tmp0 - tmp3;
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
pOut[0] = tmp10 + tmp11;
pOut[32] = tmp10 - tmp11;
z1 = (short)((tmp12 + tmp13) * 0.707106781);
pOut[16] = tmp13 + z1;
pOut[48] = tmp13 - z1;
tmp10 = tmp4 + tmp5;
tmp11 = tmp5 + tmp6;
tmp12 = tmp6 + tmp7;
z5 = (short)((tmp10 - tmp12) * 0.382683433);
z2 = (short)(0.541196100 * tmp10 + z5);
z4 = (short)(1.306562965 * tmp12 + z5);
z3 = (short)(tmp11 * 0.707106781);
z11 = tmp7 + z3;
z13 = tmp7 - z3;
pOut[40] = z13 + z2;
pOut[24] = z13 - z2;
pOut[8] = z11 + z4;
pOut[56] = z11 - z4; pOut++;
}
/*
TRACE("以下是经过一维FDCT变换后的数据:\n");
for(int d = 0;d<64;d++)
{
TRACE("%5d ",pOutBuf[d]);
if((d+1)%8 ==0)
{
TRACE("\n");
}
}
*/
}//量化函数
void CJpeg::Quantize(short *pBuf, UINT nType)
{
BYTE *pQuanTbl;
double f; pQuanTbl = (nType < 4)?m_QuanYEnc:m_QuanUVEnc; for(UINT i = 0;i < 64;i++)
{
//取整
f = pBuf[i]/pQuanTbl[i];
if(f >= 0)
{
f += 0.5;
}
else
{
f -= 0.5;
}
pBuf[i] = (short)f;
}
/*
TRACE("%u量化后的结果:\n",nType);
TRACE("输入地址为:%u\n",pBuf);
for(int d = 0;d < 64;d++)
{
TRACE("%3d,",pBuf[d]);
if((d+1)%8==0)
{
TRACE("\n");
}
}
*/
}//对Y8*8矩阵进行Huffman编码
//其中首先包含了对DC进行的DPCM编码和对AC的RLN编码
//接着进行Huffman编码
void CJpeg::Huffman(short *pInBuf, BYTE *pOutBuf, UINT nType, UINT &nOutBytes)
{
ASSERT(pInBuf != NULL);
ASSERT(pOutBuf != NULL);
ASSERT(nType >=0 && nType < 6); //输出指针
BYTE *pOut = pOutBuf;
//数据、差值的位数
USHORT nBits = 0;
//差值或者数据
int iDiff0,iDiff1;
//最终输出数据字节数
nOutBytes = 0;
//临时输出数据长度,每个WriteBits写入的字节数
UINT nOut = 0; //指定使用的Huffman表
BYTE *bitDC;
USHORT *valDC;
BYTE *bitAC;
USHORT *valAC;
//上次保留下来的DC值的指针
short *pLastDC; //根据不同的类型给出不同的Huffman编码表
//pLastDC代表上一个8*8矩阵中DC的值,并保留下在本矩阵中DC值
if(nType < 4)
{
bitDC = m_bitYDC;
valDC = m_valYDC;
bitAC = m_bitYAC;
valAC = m_valYAC;
pLastDC = &m_dcY;
}
else
{
bitDC = m_bitUVDC;
valDC = m_valUVDC;
bitAC = m_bitUVAC;
valAC = m_valUVAC;
pLastDC = (nType == 4)?&m_dcU:&m_dcV;
} //////////////////////////////////////////////////////////////////////////
// 对DC采用APCM编码,差分编码
//开始DC Huffman编码
iDiff0 = iDiff1 = pInBuf[0] - *pLastDC;
*pLastDC = pInBuf[0]; //如果是负数,则求绝对值和反码
if(iDiff0 < 0)
{
//求绝对值
iDiff0 = -iDiff0;
//取绝对值的反码
iDiff1 = ~iDiff0;
}
//求得码长
while(iDiff0)
{
nBits++;
iDiff0 >>= 1;
} //写入DC Huffman 识别码(标志码)
/*
TRACE("DC标志码 : Value : 0x%X Bits : %u \n",valDC[nBits],bitDC[nBits]);
TRACE("DC : Value : 0x%X Bits : %u \n",iDiff1,nBits);
*/
WriteBits(valDC[nBits],bitDC[nBits],pOut,nOut);
pOut += nOut;
//写入DC差值二进制码
WriteBits(iDiff1,nBits,pOut,nOut);
pOut += nOut; //DC Hufman编码结束 //////////////////////////////////////////////////////////////////////////
// 对AC采用RLE编码,游程编码
//开始AC Huffman编码
BYTE nZeroAc = 0;
BYTE n = 0;
for(UINT i = 1;i < 64;i++)
{
iDiff0 = iDiff1 = pInBuf[m_ZagZig[i]];
if(iDiff0 == 0)
{
//统计连续零的个数
nZeroAc++;
}
else
{
while(nZeroAc > 15)
{
//如果连续的零超过15个则写入一个F0标志,代表此处有16个零
WriteBits(valAC[0xF0],bitAC[0xF0],pOut,nOut);
//WriteBits(0x7F9,11,pOut,nOut);
pOut += nOut; nZeroAc -= 16;
}
//求绝对值和反码
if(iDiff0 < 0)
{
iDiff0 = -iDiff0;
//取反码
iDiff1 = ~iDiff0;
}
//求得码长,码长至少为1,不可能为零
nBits = 1;
while(iDiff0 >>= 1)
{
nBits++;
}
/*
TRACE("0的个数 : 0x%X \n",nZeroAc);
TRACE("AC标志码 : Value : 0x%X Bits : %u \n",valAC[nBits],bitAC[nBits]);
TRACE("AC : Value : 0x%X Bits : %u \n",iDiff1,nBits);
*/
//编码格式为:(零的个数+AC值编码位数)(正好一个字节,Huffman编码)+AC值(Huffman编码)
//1. 把0的个数和AC值编码位数合并成一个字节
n = (nZeroAc << 4) + nBits;
WriteBits(valAC[n],bitAC[n],pOut,nOut);
pOut += nOut; //2. 写入AC数据
WriteBits(iDiff1,nBits,pOut,nOut);
pOut += nOut; nZeroAc = 0;
}
}
if(nZeroAc > 0)
{
//说明后面全是零
WriteBits(valAC[0],bitAC[0],pOut,nOut);
//WriteBits(10,4,pOut,nOut);
pOut += nOut;
}
//AC 编码结束
nOutBytes = pOut - pOutBuf;
/*
TRACE("Huffman编码后,%u块输出大小为:%u\n",nType,nOutBytes);
for(UINT d = 0;d < nOutBytes;d++)
{
TRACE("%3d ",pOutBuf[d]);
if((d+1)%8==0 || d+1 == nOutBytes)
{
TRACE("\n");
}
}
*/
}