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

📄 jpeg_code.cpp

📁 实现JPEG编码功能
💻 CPP
📖 第 1 页 / 共 3 页
字号:
  {
   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 + -