⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 简单jpeg编码程序.txt

📁 这是一个很简单jpeg编码程序
💻 TXT
📖 第 1 页 / 共 3 页
字号:
  fwrite(&DHT,sizeof(DHT),1,this->pOutFile); 
  for (i = 0; i <= 161; i++)
  {
   WriteByte(STD_AC_UV_VALUES[i]);  
  } 
 }

 //写入SOS段
 void 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 WriteEOI(void)
 {
  fwrite(&EOITAG,sizeof(EOITAG),1,this->pOutFile);
 }


 // 将高8位和低8位交换
 USHORT Intel2Moto(USHORT val)
 {
  BYTE highBits = BYTE(val / 256);
  BYTE lowBits = BYTE(val % 256);

  return lowBits * 256 + highBits;
 }

 //写1字节到文件
 void WriteByte(BYTE val)
 {   
  fwrite(&val,sizeof(val),1,this->pOutFile);
 }

 // 生成标准Huffman表
 void 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 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]);          
   }
  }
 }

 //********************************************************************
 // 方法名称:ProcessData 
 //
 // 方法说明:处理图像数据FDCT-QUANT-HUFFMAN
 //
 // 参数说明:
 // lpYBuf:亮度Y信号输入缓冲
 // lpUBuf:色差U信号输入缓冲
 // lpVBuf:色差V信号输入缓冲
 //********************************************************************
 void ProcessData(BYTE* lpYBuf,BYTE* lpUBuf,BYTE* lpVBuf)
 { 
  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 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;   /* 将指针指向下一列 */
  }
 }

 //********************************************************************
 // 方法名称:WriteBits 
 //
 // 方法说明:写入二进制流
 //
 // 参数说明:
 // value:AC/DC信号的振幅
 //********************************************************************
 void WriteBits(HUFFCODE huffCode)
 {  
  WriteBitsStream(huffCode.code,huffCode.length); 
 }
 void WriteBits(SYM2 sym)
 {
  WriteBitsStream(sym.amplitude,sym.codeLen); 
 }

 //********************************************************************
 // 方法名称:WriteBitsStream 
 //
 // 方法说明:写入二进制流
 //
 // 参数说明:
 // value:需要写入的值
 // codeLen:二进制长度
 //********************************************************************
 void 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;
   }
  }
 }

 //********************************************************************
 // 方法名称:RLEComp 
 //
 // 方法说明:使用RLE算法对AC压缩,假设输入数据1,0,0,0,3,0,5 
 //     输出为(0,1)(3,3)(1,5),左位表示右位数据前0的个数
 //          左位用4bits表示,0的个数超过表示范围则输出为(15,0)
 //          其余的0数据在下一个符号中表示.
 //
 // 参数说明:
 // lpbuf:输入缓冲,8x8变换信号缓冲
 // lpOutBuf:输出缓冲,结构数组,结构信息见头文件
 // resultLen:输出缓冲长度,即编码后符号的数量
 //********************************************************************
 void 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;             //符号计数
   }
  } 
 }

 //********************************************************************
 // 方法名称:BuildSym2 
 //
 // 方法说明:将信号的振幅VLI编码,返回编码长度和信号振幅的反码
 //
 // 参数说明:
 // value:AC/DC信号的振幅
 //********************************************************************
 SYM2 BuildSym2(SHORT value)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -