图像转换(jpg to bmo)(bmp to jpg)

//jpeg转bmp的原理很简单,用ipciture读入jpg图像,然后在成bmp的,由于在vc 6.0里面可以自动存储的格式只有两种:bmp和ico,由此的来

void JpegToBmp(const char *resourcepath,const char *destnatepath)
{
    IPicture *m_picture;
   
    CFile file(resourcepath,CFile::modeRead);
    DWORD m_filelen=file.GetLength();
    HGLOBAL hglobal=GlobalAlloc(GMEM_MOVEABLE,m_filelen);
    LPVOID pdata=NULL;
    pdata=GlobalLock(hglobal);
    file.ReadHuge(pdata,m_filelen);
    IStream *m_stream;
    GlobalUnlock(hglobal);
    file.Close();
   
    CreateStreamOnHGlobal(hglobal,TRUE,&m_stream);
    OleLoadPicture(m_stream,m_filelen,TRUE,IID_IPicture,(LPVOID*)&m_picture); 
     
      LONG   size;  
      m_picture->SaveAsFile(m_stream,TRUE,&size);  
      char   pathbuf[1024];  
      CFile   iconfile;  
      iconfile.Open(destnatepath,CFile::modeCreate|CFile::modeWrite);  
      LARGE_INTEGER li;  
      li.HighPart = 0;  
      li.LowPart = 0;  
      ULARGE_INTEGER ulnewpos;  
      m_stream->Seek(li,STREAM_SEEK_SET,&ulnewpos);  
      ULONG  uReadCount = 1;  
      while(uReadCount>0)  
      {  
            m_stream->Read(pathbuf,sizeof(pathbuf),&uReadCount);  
            if(uReadCount>0)  
                                iconfile.Write(pathbuf,uReadCount);  
      }
   
    GlobalFree(hglobal);
    m_stream->Release();
    m_stream=NULL;
    m_picture->Release();            
}

 

bmp转jpg的麻烦一点儿,因为jpg需要复杂的解压,从网上download了一个,可用主要是通过两个类实现:

view plain print ?
  1. // CompressEncode.h: interface for the CCompressEncode class.  
  2. //  
  3. //////////////////////////////////////////////////////////////////////  
  4. #if !defined(AFX_COMPRESSENCODE_H__0EF37988_FDDE_4229_9EF1_CA5B1E51BEFF__INCLUDED_)  
  5. #define AFX_COMPRESSENCODE_H__0EF37988_FDDE_4229_9EF1_CA5B1E51BEFF__INCLUDED_  
  6. #if _MSC_VER > 1000  
  7. #pragma once  
  8. #endif // _MSC_VER > 1000  
  9. typedef struct tag_HUFFMAN_TABLE {   
  10.         unsigned int    code[256];  // code for each symbol    
  11.         char            size[256];  // length of code for each symbol    
  12.         //If no code has been allocated for a symbol S, size[S] is 0    
  13.    
  14.         /* These two fields directly represent the contents of a JPEG DHT marker */   
  15.         unsigned char bits[17];     /* bits[k] = # of symbols with codes of */   
  16.         /* length k bits; bits[0] is unused */   
  17.         unsigned char huffval[256];     /* The symbols, in order of incr code length */   
  18.                                 /* This field is used only during compression.  It's initialized FALSE when  
  19.                                 * the table is created, and set TRUE when it's been output to the file.  
  20.                                 * You could suppress output of a table by setting this to TRUE.  
  21.                                 * (See jpeg_suppress_tables for an example.)*/   
  22. }HUFFMAN_TABLE;   
  23. class CCompressEncode    
  24. {  
  25. public:  
  26.     CCompressEncode();  
  27.     virtual ~CCompressEncode();  
  28.     CCompressEncode( int nQuality );   
  29.     bool CompressImage(    
  30.         unsigned char *pInBuf,  //source data, bgr format, 3 bytes per pixel   
  31.         unsigned char *pOutBuf, //destination buffer, in jpg format   
  32.         int nWidthPix,          //image width in pixels   
  33.         int nHeight,            //height   
  34.         int& nOutputBytes       //return number of bytes being written   
  35.         );   
  36.    
  37.     ////////////////////////////////////////////////////////////////////////////   
  38.     //  Following data members should be computed in initialization   
  39.    
  40.     unsigned short m_nQuality, m_nScale;   
  41.    
  42.     //RGB转化YCbCr颜色对应表   
  43.     int m_RToY[256],    m_GToY[256],    m_BToY[256];   
  44.     int m_RToCb[256],   m_GToCb[256],   m_BToCb[256];   
  45.     int m_RToCr[256],   m_GToCr[256],   m_BToCr[256];   
  46.    
  47.     //  To speed up, we precompute two DCT quant tables   
  48.     unsigned short m_qtblY[64], m_qtblCbCr[64];   
  49.    
  50.     //用来写入JPG文件头   
  51.     unsigned char m_dqtY[64], m_dqtCbCr[64];   
  52.    
  53.     HUFFMAN_TABLE m_htblYDC, m_htblYAC, m_htblCbCrDC, m_htblCbCrAC;   
  54.    
  55.     ////////////////////////////////////////////////////////////////////////////   
  56.        
  57.     ////////////////////////////////////////////////////////////////////////////   
  58.     //  Following are should be initialized for compressing every image   
  59.    
  60.     unsigned short m_nWidth, m_nHeight;   
  61.    
  62.     //  Three dc records, used for dc differentize for Y/Cb/Cr   
  63.     int m_dcY, m_dcCb, m_dcCr;   
  64.    
  65.     //  The size (in bits) and value (in 4 byte buffer) to be written out   
  66.     int m_nPutBits, m_nPutVal;   
  67.    
  68.     unsigned char *m_pOutBuf;   
  69.    
  70.     ////////////////////////////////////////////////////////////////////////////   
  71.    
  72. private:   
  73.    
  74.     void InitEncoder( void );   
  75.        
  76.     void InitColorTable( void );   
  77.    
  78.     void InitQuantTable( void );   
  79.    
  80.     void ScaleQuantTable(   
  81.         unsigned short* tblRst,    
  82.         unsigned char* tblStd,         
  83.         unsigned short* tblAan     
  84.         );   
  85.    
  86.     void ScaleTable(unsigned char* tbl, int scale, int max);   
  87.    
  88.    
  89.     void InitHuffmanTable( void );   
  90.    
  91.     void ComputeHuffmanTable(   
  92.         unsigned char * pBits,    
  93.         unsigned char * pVal,   
  94.         HUFFMAN_TABLE * pTbl       
  95.         );   
  96.    
  97.     bool CompressOneTile(   
  98.         unsigned char * pBgr    //source data, in BGR format       
  99.     );   
  100.    
  101.     void BGRToYCbCr(       
  102.         unsigned char * pBgr,   //tile source data, in BGR format, 768 bytes   
  103.         unsigned char * pY,     //out, Illuminance, 256 bytes   
  104.         unsigned char * pCb,    //out, Cb, 256 bytes   
  105.         unsigned char * pCr     //out, Cr, 256 bytes   
  106.         );   
  107.        
  108.     void BGRToYCbCrEx(     
  109.         unsigned char * pBgr,   //in, tile data, in BGR format, 768 bytes   
  110.         int * pBlock            //out, Y: 256; Cb: 64; Cr: 64    
  111.         );   
  112.        
  113.     void ForwardDct(    
  114.         int* data,  //source data, length is 64    
  115.         int* coef   //output dct coefficients   
  116.         );   
  117.        
  118.     void Quantize(    
  119.         int* coef,  //coef is both in and out   
  120.         int iBlock  //block id; Y: 0,1,2,3; Cb: 4; Cr: 5   
  121.         );   
  122.    
  123.     bool HuffmanEncode(    
  124.         int* pCoef,             //  DCT coefficients   
  125.         int iBlock              //  0,1,2,3:Y; 4:Cb; 5:Cr;   
  126.         );   
  127.    
  128.     bool EmitBits(   
  129.         unsigned int code,      //Huffman code   
  130.         int size                //Size in bits of the Huffman code   
  131.         );   
  132.    
  133.     void EmitLeftBits(void);   
  134.    
  135.     void WriteJpegHeader(void);    
  136.     void write_sos(void);   
  137.     void write_sof(int code);   
  138.     void write_app0(void);   
  139.     void write_soi(void);   
  140.     void write_dht(int IsCbCr, int IsAc);   
  141.     void write_dqt(int index);   
  142.            
  143. };  
  144. #endif // !defined(AFX_COMPRESSENCODE_H__0EF37988_FDDE_4229_9EF1_CA5B1E51BEFF__INCLUDED_)   
// CompressEncode.h: interface for the CCompressEncode class. // ////////////////////////////////////////////////////////////////////// #if !defined(AFX_COMPRESSENCODE_H__0EF37988_FDDE_4229_9EF1_CA5B1E51BEFF__INCLUDED_) #define AFX_COMPRESSENCODE_H__0EF37988_FDDE_4229_9EF1_CA5B1E51BEFF__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 typedef struct tag_HUFFMAN_TABLE { unsigned int code[256]; // code for each symbol char size[256]; // length of code for each symbol //If no code has been allocated for a symbol S, size[S] is 0 /* These two fields directly represent the contents of a JPEG DHT marker */ unsigned char bits[17]; /* bits[k] = # of symbols with codes of */ /* length k bits; bits[0] is unused */ unsigned char huffval[256]; /* The symbols, in order of incr code length */ /* This field is used only during compression. It's initialized FALSE when * the table is created, and set TRUE when it's been output to the file. * You could suppress output of a table by setting this to TRUE. * (See jpeg_suppress_tables for an example.)*/ }HUFFMAN_TABLE; class CCompressEncode { public: CCompressEncode(); virtual ~CCompressEncode(); CCompressEncode( int nQuality ); bool CompressImage( unsigned char *pInBuf, //source data, bgr format, 3 bytes per pixel unsigned char *pOutBuf, //destination buffer, in jpg format int nWidthPix, //image width in pixels int nHeight, //height int& nOutputBytes //return number of bytes being written ); //////////////////////////////////////////////////////////////////////////// // Following data members should be computed in initialization unsigned short m_nQuality, m_nScale; //RGB转化YCbCr颜色对应表 int m_RToY[256], m_GToY[256], m_BToY[256]; int m_RToCb[256], m_GToCb[256], m_BToCb[256]; int m_RToCr[256], m_GToCr[256], m_BToCr[256]; // To speed up, we precompute two DCT quant tables unsigned short m_qtblY[64], m_qtblCbCr[64]; //用来写入JPG文件头 unsigned char m_dqtY[64], m_dqtCbCr[64]; HUFFMAN_TABLE m_htblYDC, m_htblYAC, m_htblCbCrDC, m_htblCbCrAC; //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// // Following are should be initialized for compressing every image unsigned short m_nWidth, m_nHeight; // Three dc records, used for dc differentize for Y/Cb/Cr int m_dcY, m_dcCb, m_dcCr; // The size (in bits) and value (in 4 byte buffer) to be written out int m_nPutBits, m_nPutVal; unsigned char *m_pOutBuf; //////////////////////////////////////////////////////////////////////////// private: void InitEncoder( void ); void InitColorTable( void ); void InitQuantTable( void ); void ScaleQuantTable( unsigned short* tblRst, unsigned char* tblStd, unsigned short* tblAan ); void ScaleTable(unsigned char* tbl, int scale, int max); void InitHuffmanTable( void ); void ComputeHuffmanTable( unsigned char * pBits, unsigned char * pVal, HUFFMAN_TABLE * pTbl ); bool CompressOneTile( unsigned char * pBgr //source data, in BGR format ); void BGRToYCbCr( unsigned char * pBgr, //tile source data, in BGR format, 768 bytes unsigned char * pY, //out, Illuminance, 256 bytes unsigned char * pCb, //out, Cb, 256 bytes unsigned char * pCr //out, Cr, 256 bytes ); void BGRToYCbCrEx( unsigned char * pBgr, //in, tile data, in BGR format, 768 bytes int * pBlock //out, Y: 256; Cb: 64; Cr: 64 ); void ForwardDct( int* data, //source data, length is 64 int* coef //output dct coefficients ); void Quantize( int* coef, //coef is both in and out int iBlock //block id; Y: 0,1,2,3; Cb: 4; Cr: 5 ); bool HuffmanEncode( int* pCoef, // DCT coefficients int iBlock // 0,1,2,3:Y; 4:Cb; 5:Cr; ); bool EmitBits( unsigned int code, //Huffman code int size //Size in bits of the Huffman code ); void EmitLeftBits(void); void WriteJpegHeader(void); void write_sos(void); void write_sof(int code); void write_app0(void); void write_soi(void); void write_dht(int IsCbCr, int IsAc); void write_dqt(int index); }; #endif // !defined(AFX_COMPRESSENCODE_H__0EF37988_FDDE_4229_9EF1_CA5B1E51BEFF__INCLUDED_) 
view plain print ?
  1. #ifndef __PICTUREOPERATE_H__   
  2. #define __PICTUREOPERATE_H__   
  3.    
  4. class PictureOperate   
  5. {   
  6. public:   
  7.     PictureOperate();   
  8.     ~PictureOperate();   
  9.    
  10.     //加载位图   
  11.     BOOL Load( const char * );   
  12.        
  13.    
  14.     //进行编码压缩并且保存文件   
  15.     void picCompressEncode(CString filename, BOOL color, int quality);   
  16.        
  17.        
  18.     UINT m_width, m_height, m_rowbytes;   
  19.    
  20. private:   
  21.     DWORD m_dwDibSize;   
  22.     unsigned char *m_pDib, *m_pDibBits;    
  23.     BITMAPINFOHEADER *m_pBIH;   
  24.        
  25.     CPalette m_Palette;   
  26.     RGBQUAD *m_pPalette;   
  27.     int m_nPaletteEntries;   
  28. };   
  29. #endif  
#ifndef __PICTUREOPERATE_H__ #define __PICTUREOPERATE_H__ class PictureOperate { public: PictureOperate(); ~PictureOperate(); //加载位图 BOOL Load( const char * ); //进行编码压缩并且保存文件 void picCompressEncode(CString filename, BOOL color, int quality); UINT m_width, m_height, m_rowbytes; private: DWORD m_dwDibSize; unsigned char *m_pDib, *m_pDibBits; BITMAPINFOHEADER *m_pBIH; CPalette m_Palette; RGBQUAD *m_pPalette; int m_nPaletteEntries; }; #endif 
view plain print ?
  1. #include "stdafx.h"     
  2. #include "PicOperate.h"      
  3. #include "CompressEncode.h"     
  4. ///////////////////////////////////////////////////////////////////////////////     
  5. //构造函数     
  6. PictureOperate::PictureOperate()     
  7. {     
  8.     m_pDib = NULL;     
  9. }     
  10. //析构函数     
  11. PictureOperate::~PictureOperate()     
  12. {     
  13.     if( m_pDib != NULL )     
  14.         delete [] m_pDib;     
  15. }     
  16. //加载位图     
  17. BOOL PictureOperate::Load( const char *pszFilename )     
  18. {     
  19.      
  20.     CFile cf;     
  21.      
  22.     // Attempt to open the Dib file for reading.     
  23.     if( !cf.Open( pszFilename, CFile::modeRead ) )     
  24.         return( FALSE );     
  25.      
  26.     // Get the size of the file and store     
  27.     // in a local variable. Subtract the     
  28.     // size of the BITMAPFILEHEADER structure     
  29.     // since we won't keep that in memory.     
  30.     DWORD dwDibSize;     
  31.     dwDibSize =     
  32.         cf.GetLength() - sizeof( BITMAPFILEHEADER );     
  33.      
  34.     // Attempt to allocate the Dib memory.     
  35.     unsigned char *pDib;     
  36.     pDib = new unsigned char [dwDibSize];     
  37.     if( pDib == NULL )     
  38.         return( FALSE );     
  39.      
  40.     BITMAPFILEHEADER BFH;     
  41.      
  42.     // Read in the Dib header and data.     
  43.     try{     
  44.      
  45.         // Did we read in the entire BITMAPFILEHEADER?     
  46.         if( cf.Read( &BFH, sizeof( BITMAPFILEHEADER ) )     
  47.             != sizeof( BITMAPFILEHEADER ) ||     
  48.      
  49.             // Is the type 'MB'?     
  50.             BFH.bfType != 'MB' ||     
  51.      
  52.             // Did we read in the remaining data?     
  53.             cf.Read( pDib, dwDibSize ) != dwDibSize ){     
  54.      
  55.             // Delete the memory if we had any     
  56.             // errors and return FALSE.     
  57.             delete [] pDib;     
  58.             return( FALSE );     
  59.             }     
  60.         }     
  61.      
  62.     // If we catch an exception, delete the     
  63.     // exception, the temporary Dib memory,     
  64.     // and return FALSE.     
  65.     catch( CFileException *e ){     
  66.         e->Delete();     
  67.         delete [] pDib;     
  68.         return( FALSE );     
  69.         }     
  70.          
  71.     // If we got to this point, the Dib has been     
  72.     // loaded. If a Dib was already loaded into     
  73.     // this class, we must now delete it.     
  74.     if( m_pDib != NULL )     
  75.         delete m_pDib;     
  76.      
  77.     // Store the local Dib data pointer and     
  78.     // Dib size variables in the class member     
  79.     // variables.     
  80.     m_pDib = pDib;     
  81.     m_dwDibSize = dwDibSize;     
  82.      
  83.     // Pointer our BITMAPINFOHEADER and RGBQUAD     
  84.     // variables to the correct place in the Dib data.     
  85.     m_pBIH = (BITMAPINFOHEADER *) m_pDib;     
  86.     m_pPalette =     
  87.         (RGBQUAD *) &m_pDib[sizeof(BITMAPINFOHEADER)];     
  88.      
  89.     //  get image width and height     
  90.     m_width = m_pBIH->biWidth;     
  91.     m_height = m_pBIH->biHeight;     
  92.      
  93.     // Calculate the number of palette entries.     
  94.     m_nPaletteEntries = 1 << m_pBIH->biBitCount;     
  95.     if( m_pBIH->biBitCount > 8 )     
  96.         m_nPaletteEntries = 0;     
  97.     else if( m_pBIH->biClrUsed != 0 )     
  98.         m_nPaletteEntries = m_pBIH->biClrUsed;     
  99.      
  100.     // Point m_pDibBits to the actual Dib bits data.     
  101.     m_pDibBits =     
  102.         &m_pDib[sizeof(BITMAPINFOHEADER)+     
  103.             m_nPaletteEntries*sizeof(RGBQUAD)];     
  104.      
  105.     // If we have a valid palette, delete it.     
  106.     if( m_Palette.GetSafeHandle() != NULL )     
  107.         m_Palette.DeleteObject();     
  108.      
  109.     // If there are palette entries, we'll need     
  110.     // to create a LOGPALETTE then create the     
  111.     // CPalette palette.     
  112.     if( m_nPaletteEntries != 0 ){     
  113.      
  114.         // Allocate the LOGPALETTE structure.     
  115.         LOGPALETTE *pLogPal = (LOGPALETTE *) new char     
  116.                 [sizeof(LOGPALETTE)+     
  117.                 m_nPaletteEntries*sizeof(PALETTEENTRY)];     
  118.      
  119.         if( pLogPal != NULL ){     
  120.      
  121.             // Set the LOGPALETTE to version 0x300     
  122.             // and store the number of palette     
  123.             // entries.     
  124.             pLogPal->palVersion = 0x300;     
  125.             pLogPal->palNumEntries = m_nPaletteEntries;     
  126.      
  127.             // Store the RGB values into each     
  128.             // PALETTEENTRY element.     
  129.             forint i=0; i<m_nPaletteEntries; i++){  
  130.                 pLogPal->palPalEntry[i].peRed =     
  131.                     m_pPalette[i].rgbRed;     
  132.                 pLogPal->palPalEntry[i].peGreen =     
  133.                     m_pPalette[i].rgbGreen;     
  134.                 pLogPal->palPalEntry[i].peBlue =     
  135.                     m_pPalette[i].rgbBlue;     
  136.                 }     
  137.      
  138.             // Create the CPalette object and     
  139.             // delete the LOGPALETTE memory.     
  140.             m_Palette.CreatePalette( pLogPal );     
  141.             delete [] pLogPal;     
  142.             }     
  143.         }     
  144.          
  145.     return( TRUE );     
  146.      
  147. }     
  148.      
  149.      
  150.      
  151. ///////////////////////////////////////////////////////////////////////////////     
  152. //对位图进行基于DCT的压缩编码,并且保存为JPG文件     
  153. void PictureOperate::picCompressEncode(CString filename, BOOL color, int quality)     
  154. {     
  155.      
  156.     //压缩后的字节数     
  157.     int nOutputBytes = 0;     
  158.      
  159.     unsigned char *pJpg;     
  160.     pJpg = new unsigned char [m_dwDibSize];     
  161.          
  162.     LARGE_INTEGER iLarge;     
  163.     QueryPerformanceFrequency( &iLarge );        
  164.     double dbFreq = (double) iLarge.QuadPart;     
  165.          
  166.     //获得起始时间     
  167.     QueryPerformanceCounter( &iLarge );      
  168.     double dbBegin = (double) iLarge.QuadPart;     
  169.      
  170.     /////////////////////////////////////////////////////     
  171.      
  172.          
  173.     //quality为压缩质量     
  174.     CCompressEncode encoder( quality );     
  175.      
  176.     encoder.CompressImage( m_pDibBits, pJpg,      
  177.         m_pBIH->biWidth, m_pBIH->biHeight, nOutputBytes );     
  178.      
  179.     //////////////////////////////////////////////////////     
  180.      
  181.     //获得压缩结束后时间     
  182.     QueryPerformanceCounter( &iLarge );      
  183.     double dbEnd = (double) iLarge.QuadPart;     
  184.      
  185.     int nms = (int) (( dbEnd - dbBegin ) * 1000.0 / dbFreq );        
  186.              
  187.     float ratio = (float) m_dwDibSize / nOutputBytes;     
  188.     CString str;     
  189.     //输出压缩后信息     
  190.     str.Format( "压缩后字节数 = %d, 压缩比 = %f, 耗时 = %d ",      
  191.                     nOutputBytes, ratio, nms );     
  192.     AfxMessageBox( str );     
  193.          
  194.     //保存JPG文件     
  195.     CFile cf;     
  196.     if( !cf.Open( filename, CFile::modeCreate | CFile::modeWrite ) )     
  197.     {     
  198.         AfxMessageBox("Can not create jpg file!");     
  199.         return;     
  200.     }     
  201.      
  202.     cf.Write( pJpg, nOutputBytes );     
  203.      
  204.     delete []pJpg;     
  205. }   
#include "stdafx.h" #include "PicOperate.h" #include "CompressEncode.h" /////////////////////////////////////////////////////////////////////////////// //构造函数 PictureOperate::PictureOperate() { m_pDib = NULL; } //析构函数 PictureOperate::~PictureOperate() { if( m_pDib != NULL ) delete [] m_pDib; } //加载位图 BOOL PictureOperate::Load( const char *pszFilename ) { CFile cf; // Attempt to open the Dib file for reading. if( !cf.Open( pszFilename, CFile::modeRead ) ) return( FALSE ); // Get the size of the file and store // in a local variable. Subtract the // size of the BITMAPFILEHEADER structure // since we won't keep that in memory. DWORD dwDibSize; dwDibSize = cf.GetLength() - sizeof( BITMAPFILEHEADER ); // Attempt to allocate the Dib memory. unsigned char *pDib; pDib = new unsigned char [dwDibSize]; if( pDib == NULL ) return( FALSE ); BITMAPFILEHEADER BFH; // Read in the Dib header and data. try{ // Did we read in the entire BITMAPFILEHEADER? if( cf.Read( &BFH, sizeof( BITMAPFILEHEADER ) ) != sizeof( BITMAPFILEHEADER ) || // Is the type 'MB'? BFH.bfType != 'MB' || // Did we read in the remaining data? cf.Read( pDib, dwDibSize ) != dwDibSize ){ // Delete the memory if we had any // errors and return FALSE. delete [] pDib; return( FALSE ); } } // If we catch an exception, delete the // exception, the temporary Dib memory, // and return FALSE. catch( CFileException *e ){ e->Delete(); delete [] pDib; return( FALSE ); } // If we got to this point, the Dib has been // loaded. If a Dib was already loaded into // this class, we must now delete it. if( m_pDib != NULL ) delete m_pDib; // Store the local Dib data pointer and // Dib size variables in the class member // variables. m_pDib = pDib; m_dwDibSize = dwDibSize; // Pointer our BITMAPINFOHEADER and RGBQUAD // variables to the correct place in the Dib data. m_pBIH = (BITMAPINFOHEADER *) m_pDib; m_pPalette = (RGBQUAD *) &m_pDib[sizeof(BITMAPINFOHEADER)]; // get image width and height m_width = m_pBIH->biWidth; m_height = m_pBIH->biHeight; // Calculate the number of palette entries. m_nPaletteEntries = 1 << m_pBIH->biBitCount; if( m_pBIH->biBitCount > 8 ) m_nPaletteEntries = 0; else if( m_pBIH->biClrUsed != 0 ) m_nPaletteEntries = m_pBIH->biClrUsed; // Point m_pDibBits to the actual Dib bits data. m_pDibBits = &m_pDib[sizeof(BITMAPINFOHEADER)+ m_nPaletteEntries*sizeof(RGBQUAD)]; // If we have a valid palette, delete it. if( m_Palette.GetSafeHandle() != NULL ) m_Palette.DeleteObject(); // If there are palette entries, we'll need // to create a LOGPALETTE then create the // CPalette palette. if( m_nPaletteEntries != 0 ){ // Allocate the LOGPALETTE structure. LOGPALETTE *pLogPal = (LOGPALETTE *) new char [sizeof(LOGPALETTE)+ m_nPaletteEntries*sizeof(PALETTEENTRY)]; if( pLogPal != NULL ){ // Set the LOGPALETTE to version 0x300 // and store the number of palette // entries. pLogPal->palVersion = 0x300; pLogPal->palNumEntries = m_nPaletteEntries; // Store the RGB values into each // PALETTEENTRY element. for( int i=0; i<m_nPaletteEntries; i++){ pLogPal->palPalEntry[i].peRed = m_pPalette[i].rgbRed; pLogPal->palPalEntry[i].peGreen = m_pPalette[i].rgbGreen; pLogPal->palPalEntry[i].peBlue = m_pPalette[i].rgbBlue; } // Create the CPalette object and // delete the LOGPALETTE memory. m_Palette.CreatePalette( pLogPal ); delete [] pLogPal; } } return( TRUE ); } /////////////////////////////////////////////////////////////////////////////// //对位图进行基于DCT的压缩编码,并且保存为JPG文件 void PictureOperate::picCompressEncode(CString filename, BOOL color, int quality) { //压缩后的字节数 int nOutputBytes = 0; unsigned char *pJpg; pJpg = new unsigned char [m_dwDibSize]; LARGE_INTEGER iLarge; QueryPerformanceFrequency( &iLarge ); double dbFreq = (double) iLarge.QuadPart; //获得起始时间 QueryPerformanceCounter( &iLarge ); double dbBegin = (double) iLarge.QuadPart; ///////////////////////////////////////////////////// //quality为压缩质量 CCompressEncode encoder( quality ); encoder.CompressImage( m_pDibBits, pJpg, m_pBIH->biWidth, m_pBIH->biHeight, nOutputBytes ); ////////////////////////////////////////////////////// //获得压缩结束后时间 QueryPerformanceCounter( &iLarge ); double dbEnd = (double) iLarge.QuadPart; int nms = (int) (( dbEnd - dbBegin ) * 1000.0 / dbFreq ); float ratio = (float) m_dwDibSize / nOutputBytes; CString str; //输出压缩后信息 str.Format( "压缩后字节数 = %d, 压缩比 = %f, 耗时 = %d ", nOutputBytes, ratio, nms ); AfxMessageBox( str ); //保存JPG文件 CFile cf; if( !cf.Open( filename, CFile::modeCreate | CFile::modeWrite ) ) { AfxMessageBox("Can not create jpg file!"); return; } cf.Write( pJpg, nOutputBytes ); delete []pJpg; } 
view plain print ?
  1. // CompressEncode.cpp: implementation of the CCompressEncode class.  
  2. //  
  3. //////////////////////////////////////////////////////////////////////  
  4. #include "stdafx.h"  
  5. #include "bmptojpg.h"  
  6. #include "CompressEncode.h"  
  7. #ifdef _DEBUG  
  8. #undef THIS_FILE  
  9. static char THIS_FILE[]=__FILE__;  
  10. #define new DEBUG_NEW  
  11. #endif  
  12. //////////////////////////////////////////////////////////////////////  
  13. // Construction/Destruction  
  14. //////////////////////////////////////////////////////////////////////  
  15. ////////////////////////////////////////////////////////////////////////////////   
  16. //JPEG标志码   
  17. typedef enum {         
  18.   M_SOF0  = 0xc0,   
  19.   M_SOF1  = 0xc1,   
  20.   M_SOF2  = 0xc2,   
  21.   M_SOF3  = 0xc3,   
  22.      
  23.   M_SOF5  = 0xc5,   
  24.   M_SOF6  = 0xc6,   
  25.   M_SOF7  = 0xc7,   
  26.      
  27.   M_JPG   = 0xc8,   
  28.   M_SOF9  = 0xc9,   
  29.   M_SOF10 = 0xca,   
  30.   M_SOF11 = 0xcb,   
  31.      
  32.   M_SOF13 = 0xcd,   
  33.   M_SOF14 = 0xce,   
  34.   M_SOF15 = 0xcf,   
  35.      
  36.   M_DHT   = 0xc4,   
  37.      
  38.   M_DAC   = 0xcc,   
  39.      
  40.   M_RST0  = 0xd0,   
  41.   M_RST1  = 0xd1,   
  42.   M_RST2  = 0xd2,   
  43.   M_RST3  = 0xd3,   
  44.   M_RST4  = 0xd4,   
  45.   M_RST5  = 0xd5,   
  46.   M_RST6  = 0xd6,   
  47.   M_RST7  = 0xd7,   
  48.      
  49.   M_SOI   = 0xd8,   
  50.   M_EOI   = 0xd9,   
  51.   M_SOS   = 0xda,   
  52.   M_DQT   = 0xdb,   
  53.   M_DNL   = 0xdc,   
  54.   M_DRI   = 0xdd,   
  55.   M_DHP   = 0xde,   
  56.   M_EXP   = 0xdf,   
  57.      
  58.   M_APP0  = 0xe0,   
  59.   M_APP1  = 0xe1,   
  60.   M_APP2  = 0xe2,   
  61.   M_APP3  = 0xe3,   
  62.   M_APP4  = 0xe4,   
  63.   M_APP5  = 0xe5,   
  64.   M_APP6  = 0xe6,   
  65.   M_APP7  = 0xe7,   
  66.   M_APP8  = 0xe8,   
  67.   M_APP9  = 0xe9,   
  68.   M_APP10 = 0xea,   
  69.   M_APP11 = 0xeb,   
  70.   M_APP12 = 0xec,   
  71.   M_APP13 = 0xed,   
  72.   M_APP14 = 0xee,   
  73.   M_APP15 = 0xef,   
  74.      
  75.   M_JPG0  = 0xf0,   
  76.   M_JPG13 = 0xfd,   
  77.   M_COM   = 0xfe,   
  78.      
  79.   M_TEM   = 0x01,   
  80.      
  81.   M_ERROR = 0x100   
  82. } JPEG_MARKER;   
  83.    
  84. //Z字型扫描数组      
  85.     static const int jpeg_natural_order[64+16] = {   
  86.             0,  1,  8, 16,  9,  2,  3, 10,   
  87.             17, 24, 32, 25, 18, 11,  4,  5,   
  88.             12, 19, 26, 33, 40, 48, 41, 34,   
  89.             27, 20, 13,  6,  7, 14, 21, 28,   
  90.             35, 42, 49, 56, 57, 50, 43, 36,   
  91.             29, 22, 15, 23, 30, 37, 44, 51,   
  92.             58, 59, 52, 45, 38, 31, 39, 46,   
  93.             53, 60, 61, 54, 47, 55, 62, 63,   
  94.             63, 63, 63, 63, 63, 63, 63, 63,//extra entries for safety   
  95.             63, 63, 63, 63, 63, 63, 63, 63   
  96.     };   
  97.    
  98.    
  99.        
  100.        
  101.     unsigned char std_luminance_quant_tbl[64] =    
  102.     {   
  103.             16,  11,  10,  16,  24,  40,  51,  61,   
  104.             12,  12,  14,  19,  26,  58,  60,  55,   
  105.             14,  13,  16,  24,  40,  57,  69,  56,   
  106.             14,  17,  22,  29,  51,  87,  80,  62,   
  107.             18,  22,  37,  56,  68, 109, 103,  77,   
  108.             24,  35,  55,  64,  81, 104, 113,  92,   
  109.             49,  64,  78,  87, 103, 121, 120, 101,   
  110.             72,  92,  95,  98, 112, 100, 103,  99   
  111.     };   
  112.     unsigned char std_chrominance_quant_tbl[64] =    
  113.     {   
  114.             17,  18,  24,  47,  99,  99,  99,  99,   
  115.             18,  21,  26,  66,  99,  99,  99,  99,   
  116.             24,  26,  56,  99,  99,  99,  99,  99,   
  117.             47,  66,  99,  99,  99,  99,  99,  99,   
  118.             99,  99,  99,  99,  99,  99,  99,  99,   
  119.             99,  99,  99,  99,  99,  99,  99,  99,   
  120.             99,  99,  99,  99,  99,  99,  99,  99,   
  121.             99,  99,  99,  99,  99,  99,  99,  99   
  122.     };   
  123.    
  124.    
  125.    
  126.    
  127.    
  128. ////////////////////////////////////////////////////////////////////////////////   
  129.    
  130. #define emit_byte(val)  *m_pOutBuf++=(unsigned char)(val);     
  131.       
  132. #define emit_2bytes(val)            *m_pOutBuf=(unsigned char)(((val)>>8)&0xFF);  *(m_pOutBuf+1)=(unsigned char)((val)&0xFF);  m_pOutBuf+=2;     
  133.       
  134. #define emit_marker(val)            *m_pOutBuf=0xFF;   *(m_pOutBuf+1)=(unsigned char)(val);   m_pOutBuf+=2;     
  135.        
  136. //////////////////////////////////////////////////////////////////////  
  137. CCompressEncode::CCompressEncode()  
  138. {  
  139.     m_nQuality = 50;   
  140.     InitEncoder( );    
  141. }  
  142. CCompressEncode::CCompressEncode(int nQuality)  
  143. {  
  144.     m_nQuality = nQuality;   
  145.     InitEncoder( );    
  146. }  
  147. CCompressEncode::~CCompressEncode()  
  148. {  
  149. }  
  150. //////////////////////////////////////////////////////////////////////////  
  151. //初始化颜色转化表、量化表、Huffman表   
  152. void CCompressEncode::InitEncoder( )   
  153. {   
  154.        
  155.     InitColorTable( );   
  156.    
  157.    
  158.     InitQuantTable( );   
  159.    
  160.        
  161.     InitHuffmanTable( );   
  162. }   
  163.    
  164.    
  165. ////////////////////////////////////////////////////////////////////////////////   
  166.    
  167. //从RGB转换成YCbCr   
  168. /*  
  169.    
  170.  *  Y  =  0.29900 * R + 0.58700 * G + 0.11400 * B  
  171.  *  Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B  + 128  
  172.  *  Cr =  0.50000 * R - 0.41869 * G - 0.08131 * B  + 128  
  173.    
  174.  */   
  175. void CCompressEncode::InitColorTable( void )   
  176. {   
  177.     int i;   
  178.     int nScale  = 1L << 16;          
  179.     int CBCR_OFFSET = 128<<16;   
  180.        
  181.     int nHalf = nScale >> 1;     
  182.    
  183.     for( i=0; i<256; i++ )   
  184.     {   
  185.         m_RToY[ i ] = (int)( 0.29900 * nScale + 0.5 ) * i;   
  186.         m_GToY[ i ] = (int)( 0.58700 * nScale + 0.5 ) * i;   
  187.         m_BToY[ i ] = (int)( 0.11400 * nScale + 0.5 ) * i + nHalf;   
  188.    
  189.         m_RToCb[ i ] = (int)( 0.16874 * nScale + 0.5 ) * (-i);   
  190.         m_GToCb[ i ] = (int)( 0.33126 * nScale + 0.5 ) * (-i);   
  191.         m_BToCb[ i ] = (int)( 0.50000 * nScale + 0.5 ) * i +    
  192.                                         CBCR_OFFSET + nHalf - 1;   
  193.    
  194.         m_RToCr[ i ] = m_BToCb[ i ];   
  195.         m_GToCr[ i ] = (int)( 0.41869 * nScale + 0.5 ) * (-i);   
  196.         m_BToCr[ i ] = (int)( 0.08131 * nScale + 0.5 ) * (-i);   
  197.     }   
  198. }   
  199.    
  200.    
  201. ////////////////////////////////////////////////////////////////////////////////   
  202. //初始化量化表   
  203. //m_tblYQuant[0..63] 和m_tblCbCrQuant[0..63]   
  204.    
  205. void CCompressEncode::InitQuantTable( void )   
  206. {   
  207.        
  208.     static unsigned short aanscales[64] = {   
  209.                
  210.             16384, 22725, 21407, 19266, 16384, 12873,  8867,  4520,   
  211.             22725, 31521, 29692, 26722, 22725, 17855, 12299,  6270,   
  212.             21407, 29692, 27969, 25172, 21407, 16819, 11585,  5906,   
  213.             19266, 26722, 25172, 22654, 19266, 15137, 10426,  5315,   
  214.             16384, 22725, 21407, 19266, 16384, 12873,  8867,  4520,   
  215.             12873, 17855, 16819, 15137, 12873, 10114,  6967,  3552,   
  216.              8867, 12299, 11585, 10426,  8867,  6967,  4799,  2446,   
  217.              4520,  6270,  5906,  5315,  4520,  3552,  2446,  1247   
  218.     };   
  219.        
  220.        
  221.     m_nScale = m_nQuality;   
  222.    
  223.     if (m_nScale <= 0)    
  224.         m_nScale = 1;   
  225.     if (m_nScale > 100)    
  226.         m_nScale = 100;   
  227.        
  228.        
  229.     if (m_nScale < 50)   
  230.         m_nScale = 5000 / m_nScale;   
  231.     else   
  232.         m_nScale = 200 - m_nScale*2;   
  233.    
  234.        
  235.     memcpy( m_dqtY,     std_luminance_quant_tbl,    64 );   
  236.     memcpy( m_dqtCbCr,  std_chrominance_quant_tbl,  64 );   
  237.    
  238.        
  239.     ScaleTable( m_dqtY,     m_nScale, 100 );   
  240.     ScaleTable( m_dqtCbCr,  m_nScale, 100 );           
  241.    
  242.    
  243.     ScaleQuantTable( m_qtblY,    &std_luminance_quant_tbl[0],   aanscales );   
  244.     ScaleQuantTable( m_qtblCbCr, &std_chrominance_quant_tbl[0], aanscales );   
  245. }   
  246.    
  247. ////////////////////////////////////////////////////////////////////////////////   
  248. void CCompressEncode::ScaleTable(unsigned char* tbl, int scale, int max)   
  249. {   
  250.     int i, temp, half = max/2;   
  251.    
  252.     for (i = 0; i < 64; i++)    
  253.     {   
  254.            
  255.         temp = (int)(( m_nScale * tbl[i] + half ) / max );   
  256.    
  257.            
  258.         if (temp <= 0)   
  259.             temp = 1;   
  260.         if (temp > 255)   
  261.             temp = 255;   
  262.    
  263.            
  264.         tbl[i] = (unsigned char)temp;   
  265.     }   
  266. }   
  267.    
  268.    
  269. ////////////////////////////////////////////////////////////////////////////////   
  270.    
  271. void CCompressEncode::ScaleQuantTable(   
  272.             unsigned short* tblRst,        
  273.             unsigned char* tblStd,         
  274.             unsigned short* tblAan         
  275.             )   
  276. {   
  277.     int i, temp, half = 1<<10;   
  278.     for (i = 0; i < 64; i++)    
  279.     {   
  280.            
  281.         temp = (int)(( m_nScale * tblStd[i] + 50 ) / 100 );   
  282.    
  283.            
  284.         if (temp <= 0)    
  285.             temp = 1;   
  286.         if (temp > 255)   
  287.             temp = 255;        
  288.    
  289.            
  290.         tblRst[i] = (unsigned short)(( temp * tblAan[i] + half )>>11 );   
  291.     }   
  292. }   
  293.    
  294.    
  295. ////////////////////////////////////////////////////////////////////////////////   
  296. //初始化Huffman表:   
  297. //      HUFFMAN_TABLE m_htblYDC, m_htblYAC, m_htblCbCrDC, m_htblCbCrAC;   
  298.    
  299. void CCompressEncode::InitHuffmanTable( void )   
  300. {   
  301.     //  Y dc系数   
  302.     static unsigned char bitsYDC[17] =   
  303.     { 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };   
  304.     static unsigned char valYDC[] =   
  305.     { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };   
  306.        
  307.    
  308.     //  CbCr dc   
  309.     static unsigned char bitsCbCrDC[17] =   
  310.     { 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };   
  311.     static unsigned char valCbCrDC[] =   
  312.     { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };   
  313.        
  314.    
  315.     //  Y ac系数   
  316.     static unsigned char bitsYAC[17] =   
  317.     { 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d };   
  318.     static unsigned char valYAC[] =   
  319.     { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,   
  320.     0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,   
  321.     0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,   
  322.     0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,   
  323.     0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,   
  324.     0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,   
  325.     0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,   
  326.     0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,   
  327.     0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,   
  328.     0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,   
  329.     0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,   
  330.     0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,   
  331.     0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,   
  332.     0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,   
  333.     0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,   
  334.     0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,   
  335.     0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,   
  336.     0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,   
  337.     0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,   
  338.     0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,   
  339.     0xf9, 0xfa };   
  340.        
  341.    
  342.     //  CbCr ac   
  343.     static unsigned char bitsCbCrAC[17] =   
  344.     { 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 };   
  345.     static unsigned char valCbCrAC[] =   
  346.     { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,   
  347.     0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,   
  348.     0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,   
  349.     0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,   
  350.     0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,   
  351.     0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,   
  352.     0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,   
  353.     0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,   
  354.     0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,   
  355.     0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,   
  356.     0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,   
  357.     0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,   
  358.     0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,   
  359.     0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,   
  360.     0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,   
  361.     0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,   
  362.     0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,   
  363.     0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,   
  364.     0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,   
  365.     0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,   
  366.     0xf9, 0xfa };   
  367.    
  368.     //  计算生成Huffman表   
  369.     ComputeHuffmanTable( bitsYDC, valYDC, &m_htblYDC );   
  370.     ComputeHuffmanTable( bitsYAC, valYAC, &m_htblYAC );   
  371.    
  372.     ComputeHuffmanTable( bitsCbCrDC, valCbCrDC, &m_htblCbCrDC );   
  373.     ComputeHuffmanTable( bitsCbCrAC, valCbCrAC, &m_htblCbCrAC );   
  374. }   
  375.    
  376. ////////////////////////////////////////////////////////////////////////////////   
  377.    
  378. //  计算生成Huffman表   
  379. void CCompressEncode::ComputeHuffmanTable(   
  380.         unsigned char * pBits,    
  381.         unsigned char * pVal,   
  382.         HUFFMAN_TABLE * pTbl    )   
  383. {   
  384.     int p, i, l, lastp, si;   
  385.     char huffsize[257];   
  386.     unsigned int huffcode[257];   
  387.     unsigned int code;   
  388.    
  389.     // First we copy bits and huffval   
  390.     memcpy( pTbl->bits,      pBits,  sizeof(pTbl->bits) );   
  391.     memcpy( pTbl->huffval,  pVal,    sizeof(pTbl->huffval) );   
  392.        
  393.     /* Figure C.1: make table of Huffman code length for each symbol */   
  394.     /* Note that this is in code-length order. */   
  395.        
  396.     p = 0;   
  397.     for (l = 1; l <= 16; l++) {   
  398.         for (i = 1; i <= (int) pBits[l]; i++)   
  399.             huffsize[p++] = (char) l;   
  400.     }   
  401.     huffsize[p] = 0;   
  402.     lastp = p;   
  403.        
  404.     /* Figure C.2: generate the codes themselves */   
  405.     /* Note that this is in code-length order. */   
  406.        
  407.     code = 0;   
  408.     si = huffsize[0];   
  409.     p = 0;   
  410.     while (huffsize[p]) {   
  411.         while (((int) huffsize[p]) == si) {   
  412.             huffcode[p++] = code;   
  413.             code++;   
  414.         }   
  415.         code <<= 1;   
  416.         si++;   
  417.     }   
  418.        
  419.     /* Figure C.3: generate encoding tables */   
  420.     /* These are code and size indexed by symbol value */   
  421.        
  422.     /* Set any codeless symbols to have code length 0;  
  423.     * this allows EmitBits to detect any attempt to emit such symbols.  
  424.     */   
  425.     memset( pTbl->size, 0, sizeof( pTbl->size ) );   
  426.        
  427.     for (p = 0; p < lastp; p++) {   
  428.         pTbl->code[ pVal[p] ] = huffcode[p];   
  429.         pTbl->size[ pVal[p] ] = huffsize[p];   
  430.     }   
  431. }   
  432.    
  433. ///////////////////////////////////////////////////////////////////////////////   
  434.    
  435. //写入JPG头,soi, app0, Y_dqt, CbCr_dqt, sof, 4 * dht, sos.   
  436. void CCompressEncode::WriteJpegHeader(void)   
  437. {   
  438.     write_soi();   
  439.    
  440.     write_app0();   
  441.    
  442.     write_dqt(0);//Y   
  443.    
  444.     write_dqt(1);//cbcr   
  445.    
  446.     write_sof(M_SOF0);   
  447.    
  448.     write_dht(0, 0);//m_htblYDC   
  449.     write_dht(0, 1);//m_htblYAC   
  450.     write_dht(1, 0);//m_htblCbCrDC   
  451.     write_dht(1, 1);//m_htblCbCrAC   
  452.    
  453.     write_sos();   
  454. }   
  455.    
  456. ///////////////////////////////////////////////////////////////////////////////   
  457.    
  458. void CCompressEncode::write_soi()   
  459. {   
  460.     emit_marker(M_SOI);   
  461. }   
  462.    
  463. void CCompressEncode::write_app0()   
  464. {   
  465.      
  466.      
  467.   emit_marker(M_APP0);   
  468.      
  469.   emit_2bytes(2 + 4 + 1 + 2 + 1 + 2 + 2 + 1 + 1); /* length */   
  470.    
  471.   emit_byte(0x4A);  /* Identifier: ASCII "JFIF" */   
  472.   emit_byte(0x46);   
  473.   emit_byte(0x49);   
  474.   emit_byte(0x46);   
  475.   emit_byte(0);   
  476.    
  477.      
  478.   emit_byte(1);     /* Major version */   
  479.   emit_byte(1);     /* Minor version */   
  480.   emit_byte(1); /* Pixel size information */   
  481.   emit_2bytes(300);   
  482.   emit_2bytes(300);   
  483.   emit_byte(0);     /* No thumbnail image */   
  484.   emit_byte(0);   
  485. }   
  486.    
  487. void CCompressEncode::write_dqt(int index)//0:Y;1:CbCr   
  488. {   
  489.     unsigned char* dqt;   
  490.     if( index == 0 )   
  491.         dqt = &m_dqtY[0];//changed from std with quality   
  492.     else   
  493.         dqt = &m_dqtCbCr[0];   
  494.    
  495.     //only allow prec = 0;   
  496.    
  497.     emit_marker(M_DQT);   
  498.     emit_2bytes(67);//length   
  499.     emit_byte(index);   
  500.    
  501.     int i;   
  502.     unsigned char qval;   
  503.     for (i = 0; i < 64; i++)    
  504.     {   
  505.         qval = (unsigned char) (dqt[jpeg_natural_order[i]]);   
  506.         emit_byte(qval);   
  507.     }   
  508. }   
  509.    
  510.    
  511. //currently support M_SOF0 baseline implementation   
  512. void CCompressEncode::write_sof(int code)   
  513. {   
  514.     emit_marker(code);   
  515.     emit_2bytes(17); //length   
  516.    
  517.     emit_byte(8);//cinfo->data_precision);   
  518.     emit_2bytes(m_nHeight);   
  519.     emit_2bytes(m_nWidth);   
  520.     emit_byte(3);//cinfo->num_components);   
  521.    
  522.     //for Y   
  523.     emit_byte(1);//compptr->component_id);   
  524.     emit_byte(34);//(compptr->h_samp_factor << 4) + compptr->v_samp_factor);   
  525.     emit_byte(0);//quant_tbl_no   
  526.    
  527.     //for Cb   
  528.     emit_byte(2);//compptr->component_id);   
  529.     emit_byte(17);//(compptr->h_samp_factor << 4) + compptr->v_samp_factor);   
  530.     emit_byte(1);//quant_tbl_no   
  531.    
  532.     //for Cr   
  533.     emit_byte(3);//compptr->component_id);   
  534.     emit_byte(17);//(compptr->h_samp_factor << 4) + compptr->v_samp_factor);   
  535.     emit_byte(1);//quant_tbl_no   
  536. }   
  537.    
  538. void CCompressEncode::write_dht(int IsCbCr, int IsAc)   
  539. {   
  540.     HUFFMAN_TABLE *htbl;   
  541.     int index;   
  542.     if( IsCbCr )   
  543.     {   
  544.         if( IsAc )   
  545.         {   
  546.             htbl = &m_htblCbCrAC;   
  547.             index = 17;   
  548.         }   
  549.         else   
  550.         {   
  551.             htbl = &m_htblCbCrDC;   
  552.             index = 1;   
  553.         }   
  554.     }   
  555.     else   
  556.     {   
  557.         if( IsAc )   
  558.         {   
  559.             htbl = &m_htblYAC;   
  560.             index = 16;   
  561.         }   
  562.         else   
  563.         {   
  564.             htbl = &m_htblYDC;   
  565.             index = 0;   
  566.         }   
  567.     }   
  568.    
  569.     emit_marker(M_DHT);   
  570.    
  571.     int i, length = 0;   
  572.     for (i = 1; i <= 16; i++)   
  573.         length += htbl->bits[i];   
  574.        
  575.     emit_2bytes(length + 2 + 1 + 16);   
  576.        
  577.     emit_byte(index);   
  578.    
  579.     for (i = 1; i <= 16; i++)   
  580.         emit_byte(htbl->bits[i]);   
  581.        
  582.     for (i = 0; i < length; i++)//varible-length   
  583.         emit_byte(htbl->huffval[i]);       
  584. }   
  585.    
  586. void CCompressEncode::write_sos()   
  587. {   
  588.     emit_marker(M_SOS);   
  589.    
  590.     int length = 2 * 3 + 2 + 1 + 3;   
  591.     emit_2bytes(length);   
  592.    
  593.     emit_byte(3);//cinfo->comps_in_scan   
  594.    
  595.     //Y   
  596.     emit_byte(1);//index   
  597.     emit_byte(0);//dc and ac tbl use 0-th tbl   
  598.    
  599.     //Cb   
  600.     emit_byte(2);//index   
  601.     emit_byte(0x11);//dc and ac tbl use 1-th tbl   
  602.    
  603.     //Cr   
  604.     emit_byte(3);//index   
  605.     emit_byte(0x11);//dc and ac tbl use 1-th tbl   
  606.    
  607.     emit_byte(0);//Ss   
  608.     emit_byte(0x3F);//Se   
  609.     emit_byte(0);//  Ah/Al   
  610. }   
  611. ////////////////////////////////////////////////////////////////////////////////   
  612.    
  613.    
  614.    
  615.    
  616. ////////////////////////////////////////////////////////////////////////////////   
  617. //对图像进行压缩编码的主函数   
  618. bool CCompressEncode::CompressImage(       
  619.      unsigned char *pInBuf, //源数据   
  620.      unsigned char *pOutBuf,//目标数据   
  621.      int nWidthPix,         //图像宽   
  622.      int nHeight,           //图像高   
  623.      int& nOutputBytes      //转化后字节数   
  624.      )   
  625. {   
  626.     //  错误处理   
  627.     if(( pInBuf == 0 )||( pOutBuf == 0 ))   
  628.         return false;   
  629.    
  630.     m_nWidth = nWidthPix;   
  631.     m_nHeight = nHeight;   
  632.     m_pOutBuf = pOutBuf;   
  633.    
  634.     //写入JPG头   
  635.     WriteJpegHeader();   
  636.    
  637.        
  638.     int nHeadBytes = m_pOutBuf - pOutBuf;   
  639.    
  640.        
  641.     int nRowBytes = ( m_nWidth * 3 + 3 ) / 4 * 4;          
  642.    
  643.     //异常   
  644.     if(( nWidthPix <= 0 )||( nRowBytes <= 0 )||( nHeight <= 0 ))   
  645.         return false;   
  646.    
  647.        
  648.     int xPixel, yPixel, xTile, yTile, cxTile, cyTile, cxBlock, cyBlock;   
  649.     int x, y, nTrueRows, nTrueCols, nTileBytes;   
  650.     unsigned char byTile[768], *pTileRow, *pLastPixel, *pHolePixel;   
  651.            
  652.     //  水平和垂直MCU的数量    
  653.     //  MCU(Minimum Coded Unit), 16*16 象素   
  654.     cxTile = (nWidthPix + 15)>> 4;       
  655.     cyTile = (nHeight + 15) >> 4;   
  656.    
  657.     //  水平和垂直块的数量 8*8 象素   
  658.     cxBlock = cxTile << 1;   
  659.     cyBlock = cyTile << 1;   
  660.    
  661.    
  662.     //初始化   
  663.     nTileBytes = 0;   
  664.    
  665.    
  666.     m_dcY = m_dcCb = m_dcCr = 0;   
  667.    
  668.    
  669.     m_nPutBits = 0;   
  670.     m_nPutVal = 0;   
  671.    
  672.     //循环对每个MCU进行处理   
  673.        
  674.     for( yTile = 0; yTile < cyTile; yTile++ )   
  675.     {   
  676.         for( xTile = 0; xTile < cxTile; xTile++ )   
  677.         {   
  678.             //获得此MCU初始相似   
  679.             xPixel = xTile << 4;   
  680.             yPixel = yTile << 4;   
  681.    
  682.             //  获得列和栏数   
  683.             nTrueRows = 16;   
  684.             nTrueCols = 16;            
  685.             if( yPixel + nTrueRows > nHeight )   
  686.                 nTrueRows = nHeight - yPixel;   
  687.             if( xPixel + nTrueCols > nWidthPix )   
  688.                 nTrueCols = nWidthPix - xPixel;   
  689.    
  690.                
  691.             pTileRow = pInBuf + (m_nHeight - yPixel) * nRowBytes + xPixel * 3;   
  692.    
  693.             //获得数据   
  694.             for( y = 0; y < 16; y ++ )   
  695.             {   
  696.                 if( y < nTrueRows )   
  697.                 {      
  698.                        
  699.                     pTileRow -= nRowBytes;                     
  700.                     memcpy( byTile + y * 16 * 3, pTileRow, nTrueCols * 3 );   
  701.                        
  702.                        
  703.                     if( nTrueCols < 16 )   
  704.                     {   
  705.                         pLastPixel = pTileRow + (nTrueCols - 1) * 3;   
  706.                         pHolePixel = byTile + y * 16 * 3 + nTrueCols * 3;   
  707.                         for( x = nTrueCols; x < 16; x ++ )   
  708.                         {   
  709.                             memcpy( pHolePixel, pLastPixel, 3 );   
  710.                             pHolePixel += 3;   
  711.                         }   
  712.                     }   
  713.                 }   
  714.                 else   
  715.                 {   
  716.                        
  717.                     memcpy( byTile + y * 16 * 3,    
  718.                             byTile + (nTrueRows - 1) * 16 * 3,   
  719.                             16 * 3 );   
  720.                 }   
  721.             }   
  722.            
  723.             //调用函数对此MCU进行压缩编码   
  724.             if( ! CompressOneTile(  byTile ))   
  725.                 return false;              
  726.         }   
  727.     }   
  728.        
  729.     //处理剩余部分   
  730.     if( m_nPutBits > 0 )   
  731.     {   
  732.         EmitLeftBits( );   
  733.     }   
  734.    
  735.     //写入结束标志   
  736.     emit_marker(M_EOI);   
  737.     nOutputBytes = m_pOutBuf - pOutBuf;   
  738.     return true;   
  739. }   
  740.    
  741. ////////////////////////////////////////////////////////////////////////////////   
  742. //  对一个16*16象素的块进行基于DCT的压缩编码   
  743.    
  744. bool CCompressEncode::CompressOneTile(     
  745.     unsigned char * pBgr       
  746.     )   
  747. {   
  748.     //  三个颜色部分    
  749.     int pYCbCr[384];   
  750.    
  751.     //  DCT变换输出   
  752.     int coef[64];      
  753.    
  754.     //  颜色转换   
  755.     BGRToYCbCrEx( pBgr, pYCbCr );   
  756.    
  757.     //  分别对Y/Cb/Cr几个部分进行压缩编码 Y: 4 blocks; Cb: 1 block; Cr: 1 block   
  758.     int i;   
  759.     for( i=0; i<6; i++ )   
  760.     {   
  761.         ForwardDct( pYCbCr + i*64, coef );   
  762.            
  763.         Quantize( coef, i );       
  764.            
  765.         HuffmanEncode( coef, i );      
  766.     }   
  767.    
  768.     return true;   
  769. }   
  770.    
  771.    
  772. ////////////////////////////////////////////////////////////////////////////////   
  773. //  颜色转换   
  774. void CCompressEncode::BGRToYCbCr(      
  775.         unsigned char * pBgr,   //tile source data, in BGR format, 768 bytes   
  776.         unsigned char * pY,     //out, Illuminance, 256 bytes   
  777.         unsigned char * pCb,    //out, Cb, 256 bytes   
  778.         unsigned char * pCr     //out, Cr, 256 bytes   
  779.         )   
  780. {   
  781.     int i;   
  782.     unsigned char r, g, b, *pByte = pBgr, *py = pY, *pcb = pCb, *pcr = pCr;   
  783.    
  784.     for( i=0; i<256; i++ )   
  785.     {   
  786.         b = *(pByte ++);   
  787.         g = *(pByte ++);   
  788.         r = *(pByte ++);   
  789.    
  790.         *(py++)  = (unsigned char)((m_RToY[r]  + m_GToY[g]  + m_BToY[b] )>>16);   
  791.         *(pcb++) = (unsigned char)((m_RToCb[r] + m_GToCb[g] + m_BToCb[b])>>16);   
  792.         *(pcr++) = (unsigned char)((m_RToCr[r] + m_GToCr[g] + m_BToCr[b])>>16);   
  793.     }   
  794. }   
  795.    
  796. ////////////////////////////////////////////////////////////////////////////////   
  797.    
  798. void CCompressEncode::BGRToYCbCrEx(    
  799.         unsigned char * pBgr,   //in, tile data, in BGR format, 768 bytes   
  800.         int * pBlock    //out, Y: 256; Cb: 64; Cr: 64    
  801.         )   
  802. {   
  803.     int x, y, *py[4], *pcb, *pcr;   
  804.     unsigned char r, g, b, *pByte;   
  805.    
  806.     pByte = pBgr;   
  807.     for( x = 0; x < 4; x++ )   
  808.         py[ x ] = pBlock + 64 * x;   
  809.     pcb   = pBlock + 256;   
  810.     pcr   = pBlock + 320;   
  811.        
  812.     for( y=0; y<16; y++ )   
  813.     {   
  814.         for( x=0; x<16; x++ )   
  815.         {   
  816.             b = *(pByte ++);   
  817.             g = *(pByte ++);   
  818.             r = *(pByte ++);   
  819.                
  820.             //  block number is ((y/8) * 2 + x/8): 0, 1, 2, 3   
  821.             *( py[((y>>3)<<1) + (x>>3)] ++ ) =    
  822.                 ((m_RToY[ r ]  + m_GToY[ g ]  + m_BToY[ b ] )>>16) -128;     
  823.                
  824.             //  Equal to: (( x%2 == 0 )&&( y%2 == 0 ))   
  825.             if( (!(y & 1L)) && (!(x & 1L)) )   
  826.             {   
  827.                 *(pcb++) =    
  828.                     ((m_RToCb[ r ] + m_GToCb[ g ] + m_BToCb[ b ])>>16) -128;   
  829.                 *(pcr++) =    
  830.                     ((m_RToCr[ r ] + m_GToCr[ g ] + m_BToCr[ b ])>>16) -128;   
  831.             }   
  832.         }   
  833.     }   
  834. }   
  835.    
  836. ////////////////////////////////////////////////////////////////////////////////   
  837.    
  838. //离散余弦正变换   
  839. void CCompressEncode::ForwardDct(    
  840.         int* data,  //source data, length is 64    
  841.         int* coef   //output dct coefficients   
  842.         )   
  843. {   
  844.    
  845. ////////////////////////////////////////////////////////////////////////////   
  846. //为了方便计算定义几个宏   
  847. #define FIX_0_382683433  ((int)98)      /* FIX(0.382683433) */   
  848. #define FIX_0_541196100  ((int)139)     /* FIX(0.541196100) */   
  849. #define FIX_0_707106781  ((int)181)     /* FIX(0.707106781) */   
  850. #define FIX_1_306562965  ((int)334)     /* FIX(1.306562965) */   
  851.        
  852.    
  853. #define MULTIPLY(var,cons)  (int)(((cons) * (var)) >> 8 )   
  854.    
  855. ////////////////////////////////////////////////////////////////////////////   
  856.    
  857.     static const int DCTSIZE = 8;   
  858.     int x, y;   
  859.     int *dataptr;   
  860.     int tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;   
  861.     int tmp10, tmp11, tmp12, tmp13;   
  862.     int z1, z2, z3, z4, z5, z11, z13, *coefptr;   
  863.        
  864.     /* Pass 1: process rows. */   
  865.        
  866.     dataptr = data;     //input   
  867.     coefptr = coef;     //output       
  868.     for( y = 0; y < 8; y++ )    
  869.     {   
  870.         tmp0 = dataptr[0] + dataptr[7];   
  871.         tmp7 = dataptr[0] - dataptr[7];   
  872.         tmp1 = dataptr[1] + dataptr[6];   
  873.         tmp6 = dataptr[1] - dataptr[6];   
  874.         tmp2 = dataptr[2] + dataptr[5];   
  875.         tmp5 = dataptr[2] - dataptr[5];   
  876.         tmp3 = dataptr[3] + dataptr[4];   
  877.         tmp4 = dataptr[3] - dataptr[4];   
  878.            
  879.         /* Even part */   
  880.            
  881.         tmp10 = tmp0 + tmp3;    /* phase 2 */   
  882.         tmp13 = tmp0 - tmp3;   
  883.         tmp11 = tmp1 + tmp2;   
  884.         tmp12 = tmp1 - tmp2;   
  885.            
  886.         coefptr[0] = tmp10 + tmp11; /* phase 3 */   
  887.         coefptr[4] = tmp10 - tmp11;   
  888.            
  889.         z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */   
  890.         coefptr[2] = tmp13 + z1;    /* phase 5 */   
  891.         coefptr[6] = tmp13 - z1;   
  892.            
  893.         /* Odd part */   
  894.            
  895.         tmp10 = tmp4 + tmp5;    /* phase 2 */   
  896.         tmp11 = tmp5 + tmp6;   
  897.         tmp12 = tmp6 + tmp7;   
  898.            
  899.         /* The rotator is modified from fig 4-8 to avoid extra negations. */   
  900.         z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433);  /* c6 */   
  901.         z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5;     /* c2-c6 */   
  902.         z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5;     /* c2+c6 */   
  903.         z3 = MULTIPLY(tmp11, FIX_0_707106781);          /* c4 */   
  904.            
  905.         z11 = tmp7 + z3;        /* phase 5 */   
  906.         z13 = tmp7 - z3;   
  907.            
  908.         coefptr[5] = z13 + z2;  /* phase 6 */   
  909.         coefptr[3] = z13 - z2;   
  910.         coefptr[1] = z11 + z4;   
  911.         coefptr[7] = z11 - z4;   
  912.            
  913.         dataptr += 8;       /* advance pointer to next row */   
  914.         coefptr += 8;   
  915.     }   
  916.        
  917.     /* Pass 2: process columns. */     
  918.    
  919.     coefptr = coef;     //both input and output   
  920.     for ( x = 0; x < 8; x++ )    
  921.     {   
  922.         tmp0 = coefptr[DCTSIZE*0] + coefptr[DCTSIZE*7];   
  923.         tmp7 = coefptr[DCTSIZE*0] - coefptr[DCTSIZE*7];   
  924.         tmp1 = coefptr[DCTSIZE*1] + coefptr[DCTSIZE*6];   
  925.         tmp6 = coefptr[DCTSIZE*1] - coefptr[DCTSIZE*6];   
  926.         tmp2 = coefptr[DCTSIZE*2] + coefptr[DCTSIZE*5];   
  927.         tmp5 = coefptr[DCTSIZE*2] - coefptr[DCTSIZE*5];   
  928.         tmp3 = coefptr[DCTSIZE*3] + coefptr[DCTSIZE*4];   
  929.         tmp4 = coefptr[DCTSIZE*3] - coefptr[DCTSIZE*4];   
  930.            
  931.         /* Even part */   
  932.            
  933.         tmp10 = tmp0 + tmp3;    /* phase 2 */   
  934.         tmp13 = tmp0 - tmp3;   
  935.         tmp11 = tmp1 + tmp2;   
  936.         tmp12 = tmp1 - tmp2;   
  937.            
  938.         coefptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */   
  939.         coefptr[DCTSIZE*4] = tmp10 - tmp11;   
  940.            
  941.         z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */   
  942.         coefptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */   
  943.         coefptr[DCTSIZE*6] = tmp13 - z1;   
  944.            
  945.         /* Odd part */   
  946.            
  947.         tmp10 = tmp4 + tmp5;    /* phase 2 */   
  948.         tmp11 = tmp5 + tmp6;   
  949.         tmp12 = tmp6 + tmp7;   
  950.            
  951.         /* The rotator is modified from fig 4-8 to avoid extra negations. */   
  952.         z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */   
  953.         z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */   
  954.         z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */   
  955.         z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */   
  956.            
  957.         z11 = tmp7 + z3;        /* phase 5 */   
  958.         z13 = tmp7 - z3;   
  959.            
  960.         coefptr[DCTSIZE*5] = z13 + z2; /* phase 6 */   
  961.         coefptr[DCTSIZE*3] = z13 - z2;   
  962.         coefptr[DCTSIZE*1] = z11 + z4;   
  963.         coefptr[DCTSIZE*7] = z11 - z4;   
  964.            
  965.         coefptr++;          /* advance pointer to next column */   
  966.     }   
  967. }   
  968.    
  969.    
  970. ////////////////////////////////////////////////////////////////////////////////   
  971.    
  972. //进行量化   
  973. void CCompressEncode::Quantize(    
  974.         int* coef,  //coef is both in and out   
  975.         int iBlock  //block id; Y: 0,1,2,3; Cb: 4; Cr: 5   
  976.         )   
  977. {   
  978.     int temp;   
  979.     unsigned short qval, *pQuant;   
  980.    
  981.     if( iBlock < 4 )   
  982.         pQuant = m_qtblY;   
  983.     else   
  984.         pQuant = m_qtblCbCr;   
  985.    
  986.     for (int i = 0; i < 64; i++)    
  987.     {   
  988.         qval = pQuant[i];   
  989.         temp = coef[i];   
  990.            
  991.            
  992. #define DIVIDE_BY(a,b)  if (a >= b) a /= b; else a = 0   
  993.            
  994.            
  995.         if ( temp < 0)    
  996.         {   
  997.             temp = -temp;   
  998.             temp += qval>>1;  /* for rounding */   
  999.             DIVIDE_BY(temp, qval);   
  1000.             temp = -temp;   
  1001.         }    
  1002.         else    
  1003.         {   
  1004.             temp += qval>>1;  /* for rounding */   
  1005.             DIVIDE_BY(temp, qval);   
  1006.         }   
  1007.            
  1008.         coef[i] = temp;        
  1009.     }   
  1010. }   
  1011.    
  1012.    
  1013.    
  1014. ////////////////////////////////////////////////////////////////////////////////   
  1015.    
  1016. //Huffman编码   
  1017. bool CCompressEncode::HuffmanEncode(    
  1018.         int* pCoef,             //  DCT coefficients   
  1019.         int iBlock              //  0,1,2,3:Y; 4:Cb; 5:Cr;   
  1020.         )   
  1021. {      
  1022.     //对AC系数进行Z字型扫描   
  1023.     static const int jpeg_natural_order[64+16] = {   
  1024.              0,  1,  8, 16,  9,  2,  3, 10,   
  1025.             17, 24, 32, 25, 18, 11,  4,  5,   
  1026.             12, 19, 26, 33, 40, 48, 41, 34,   
  1027.             27, 20, 13,  6,  7, 14, 21, 28,   
  1028.             35, 42, 49, 56, 57, 50, 43, 36,   
  1029.             29, 22, 15, 23, 30, 37, 44, 51,   
  1030.             58, 59, 52, 45, 38, 31, 39, 46,   
  1031.             53, 60, 61, 54, 47, 55, 62, 63,   
  1032.             63, 63, 63, 63, 63, 63, 63, 63,//extra entries for safety   
  1033.             63, 63, 63, 63, 63, 63, 63, 63   
  1034.     };   
  1035.        
  1036.     int temp, temp2, nbits, k, r, i;   
  1037.     int *block = pCoef;   
  1038.     int *pLastDc = &m_dcY;   
  1039.     HUFFMAN_TABLE *dctbl, *actbl;   
  1040.    
  1041.     if( iBlock < 4 )   
  1042.     {   
  1043.         dctbl = & m_htblYDC;   
  1044.         actbl = & m_htblYAC;   
  1045. //      pLastDc = &m_dcY;      
  1046.     }   
  1047.     else   
  1048.     {   
  1049.         dctbl = & m_htblCbCrDC;   
  1050.         actbl = & m_htblCbCrAC;   
  1051.    
  1052.         if( iBlock == 4 )   
  1053.             pLastDc = &m_dcCb;   
  1054.         else   
  1055.             pLastDc = &m_dcCr;   
  1056.     }   
  1057.        
  1058.     //对DC系数进行编码   
  1059.        
  1060.     temp = temp2 = block[0] - (*pLastDc);   
  1061.     *pLastDc = block[0];   
  1062.        
  1063.     if (temp < 0) {   
  1064.         temp = -temp;       /* temp is abs value of input */   
  1065.            
  1066.         temp2 --;   
  1067.     }   
  1068.        
  1069.     /* Find the number of bits needed for the magnitude of the coefficient */   
  1070.     nbits = 0;   
  1071.     while (temp) {   
  1072.         nbits ++;   
  1073.         temp >>= 1;   
  1074.     }   
  1075.        
  1076.     //  Write category number   
  1077.     if (! EmitBits( dctbl->code[nbits], dctbl->size[nbits] ))   
  1078.         return FALSE;   
  1079.    
  1080.     //  Write category offset   
  1081.     if (nbits)          /* EmitBits rejects calls with size 0 */   
  1082.     {   
  1083.         if (! EmitBits( (unsigned int) temp2, nbits ))   
  1084.             return FALSE;   
  1085.     }   
  1086.        
  1087.     ////////////////////////////////////////////////////////////////////////////   
  1088.     //对AC系数进行编码   
  1089.        
  1090.     r = 0;          /* r = run length of zeros */   
  1091.        
  1092.     for (k = 1; k < 64; k++)    
  1093.     {   
  1094.         if ((temp = block[jpeg_natural_order[k]]) == 0)    
  1095.         {   
  1096.             r++;   
  1097.         }    
  1098.         else    
  1099.         {   
  1100.             /* if run length > 15, must emit special run-length-16 codes (0xF0) */   
  1101.             while (r > 15) {   
  1102.                 if (! EmitBits( actbl->code[0xF0], actbl->size[0xF0] ))   
  1103.                     return FALSE;   
  1104.                 r -= 16;   
  1105.             }   
  1106.                
  1107.             temp2 = temp;   
  1108.             if (temp < 0) {   
  1109.                 temp = -temp;       /* temp is abs value of input */   
  1110.                 /* This code assumes we are on a two's complement machine */   
  1111.                 temp2--;   
  1112.             }   
  1113.                
  1114.             /* Find the number of bits needed for the magnitude of the coefficient */   
  1115.             nbits = 1;      /* there must be at least one 1 bit */   
  1116.             while ((temp >>= 1))   
  1117.                 nbits++;   
  1118.                
  1119.             /* Emit Huffman symbol for run length / number of bits */   
  1120.             i = (r << 4) + nbits;   
  1121.             if (! EmitBits( actbl->code[i], actbl->size[i] ))   
  1122.                 return FALSE;   
  1123.                            
  1124.             //  Write Category offset   
  1125.             if (! EmitBits( (unsigned int) temp2, nbits ))   
  1126.                 return FALSE;   
  1127.                            
  1128.             r = 0;   
  1129.         }   
  1130.     }   
  1131.        
  1132.        
  1133.     if (r > 0)   
  1134.     {   
  1135.         if (! EmitBits( actbl->code[0], actbl->size[0] ))   
  1136.             return FALSE;   
  1137.     }          
  1138.        
  1139.     return TRUE;   
  1140. }   
  1141.    
  1142.    
  1143. ////////////////////////////////////////////////////////////////////////////////   
  1144.    
  1145.    
  1146. inline bool CCompressEncode::EmitBits(   
  1147.         unsigned int code,      //Huffman code   
  1148.         int size                //Size in bits of the Huffman code   
  1149.         )   
  1150. {   
  1151.     /* This routine is heavily used, so it's worth coding tightly. */   
  1152.     int put_buffer = (int) code;   
  1153.     int put_bits = m_nPutBits;   
  1154.        
  1155.     /* if size is 0, caller used an invalid Huffman table entry */   
  1156.     if (size == 0)   
  1157.         return false;   
  1158.        
  1159.     put_buffer &= (((int)1)<<size) - 1; /* mask off any extra bits in code */   
  1160.        
  1161.     put_bits += size;                   /* new number of bits in buffer */   
  1162.        
  1163.     put_buffer <<= 24 - put_bits;     /* align incoming bits */   
  1164.        
  1165.     put_buffer |= m_nPutVal;            /* and merge with old buffer contents */   
  1166.        
  1167.     //  If there are more than 8 bits, write it out   
  1168.     unsigned char uc;   
  1169.     while (put_bits >= 8)    
  1170.     {   
  1171.         //  Write one byte out !!!!   
  1172.         uc = (unsigned char) ((put_buffer >> 16) & 0xFF);   
  1173.         emit_byte(uc);   
  1174.        
  1175.         if (uc == 0xFF) {       //need to stuff a zero byte?   
  1176.             emit_byte(0);   //  Write one byte out !!!!   
  1177.         }   
  1178.    
  1179.         put_buffer <<= 8;   
  1180.         put_bits -= 8;   
  1181.     }   
  1182.        
  1183.     m_nPutVal   = put_buffer; /* update state variables */   
  1184.     m_nPutBits  = put_bits;   
  1185.        
  1186.     return TRUE;   
  1187. }   
  1188.    
  1189. ////////////////////////////////////////////////////////////////////////////////   
  1190.    
  1191. inline void CCompressEncode::EmitLeftBits(void)   
  1192. {   
  1193.     if (! EmitBits(0x7F, 7)) /* fill 7 bits with ones */   
  1194.         return;   
  1195.        
  1196.     m_nPutVal  = 0;   
  1197.     m_nPutBits = 0;   
  1198. }   
  1199.    
  1200.    
  1201. ////////////////////////////////////////////////////////////////////////////////   
// CompressEncode.cpp: implementation of the CCompressEncode class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "bmptojpg.h" #include "CompressEncode.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //JPEG标志码 typedef enum { M_SOF0 = 0xc0, M_SOF1 = 0xc1, M_SOF2 = 0xc2, M_SOF3 = 0xc3, M_SOF5 = 0xc5, M_SOF6 = 0xc6, M_SOF7 = 0xc7, M_JPG = 0xc8, M_SOF9 = 0xc9, M_SOF10 = 0xca, M_SOF11 = 0xcb, M_SOF13 = 0xcd, M_SOF14 = 0xce, M_SOF15 = 0xcf, M_DHT = 0xc4, M_DAC = 0xcc, M_RST0 = 0xd0, M_RST1 = 0xd1, M_RST2 = 0xd2, M_RST3 = 0xd3, M_RST4 = 0xd4, M_RST5 = 0xd5, M_RST6 = 0xd6, M_RST7 = 0xd7, M_SOI = 0xd8, M_EOI = 0xd9, M_SOS = 0xda, M_DQT = 0xdb, M_DNL = 0xdc, M_DRI = 0xdd, M_DHP = 0xde, M_EXP = 0xdf, M_APP0 = 0xe0, M_APP1 = 0xe1, M_APP2 = 0xe2, M_APP3 = 0xe3, M_APP4 = 0xe4, M_APP5 = 0xe5, M_APP6 = 0xe6, M_APP7 = 0xe7, M_APP8 = 0xe8, M_APP9 = 0xe9, M_APP10 = 0xea, M_APP11 = 0xeb, M_APP12 = 0xec, M_APP13 = 0xed, M_APP14 = 0xee, M_APP15 = 0xef, M_JPG0 = 0xf0, M_JPG13 = 0xfd, M_COM = 0xfe, M_TEM = 0x01, M_ERROR = 0x100 } JPEG_MARKER; //Z字型扫描数组 static const int jpeg_natural_order[64+16] = { 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63, 63, 63, 63, 63, 63, 63, 63, 63,//extra entries for safety 63, 63, 63, 63, 63, 63, 63, 63 }; unsigned char std_luminance_quant_tbl[64] = { 16, 11, 10, 16, 24, 40, 51, 61, 12, 12, 14, 19, 26, 58, 60, 55, 14, 13, 16, 24, 40, 57, 69, 56, 14, 17, 22, 29, 51, 87, 80, 62, 18, 22, 37, 56, 68, 109, 103, 77, 24, 35, 55, 64, 81, 104, 113, 92, 49, 64, 78, 87, 103, 121, 120, 101, 72, 92, 95, 98, 112, 100, 103, 99 }; unsigned char std_chrominance_quant_tbl[64] = { 17, 18, 24, 47, 99, 99, 99, 99, 18, 21, 26, 66, 99, 99, 99, 99, 24, 26, 56, 99, 99, 99, 99, 99, 47, 66, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99 }; //////////////////////////////////////////////////////////////////////////////// #define emit_byte(val) *m_pOutBuf++=(unsigned char)(val); #define emit_2bytes(val) *m_pOutBuf=(unsigned char)(((val)>>8)&0xFF); *(m_pOutBuf+1)=(unsigned char)((val)&0xFF); m_pOutBuf+=2; #define emit_marker(val) *m_pOutBuf=0xFF; *(m_pOutBuf+1)=(unsigned char)(val); m_pOutBuf+=2; ////////////////////////////////////////////////////////////////////// CCompressEncode::CCompressEncode() { m_nQuality = 50; InitEncoder( ); } CCompressEncode::CCompressEncode(int nQuality) { m_nQuality = nQuality; InitEncoder( ); } CCompressEncode::~CCompressEncode() { } ////////////////////////////////////////////////////////////////////////// //初始化颜色转化表、量化表、Huffman表 void CCompressEncode::InitEncoder( ) { InitColorTable( ); InitQuantTable( ); InitHuffmanTable( ); } //////////////////////////////////////////////////////////////////////////////// //从RGB转换成YCbCr /* * Y = 0.29900 * R + 0.58700 * G + 0.11400 * B * Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + 128 * Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B + 128 */ void CCompressEncode::InitColorTable( void ) { int i; int nScale = 1L << 16; int CBCR_OFFSET = 128<<16; int nHalf = nScale >> 1; for( i=0; i<256; i++ ) { m_RToY[ i ] = (int)( 0.29900 * nScale + 0.5 ) * i; m_GToY[ i ] = (int)( 0.58700 * nScale + 0.5 ) * i; m_BToY[ i ] = (int)( 0.11400 * nScale + 0.5 ) * i + nHalf; m_RToCb[ i ] = (int)( 0.16874 * nScale + 0.5 ) * (-i); m_GToCb[ i ] = (int)( 0.33126 * nScale + 0.5 ) * (-i); m_BToCb[ i ] = (int)( 0.50000 * nScale + 0.5 ) * i + CBCR_OFFSET + nHalf - 1; m_RToCr[ i ] = m_BToCb[ i ]; m_GToCr[ i ] = (int)( 0.41869 * nScale + 0.5 ) * (-i); m_BToCr[ i ] = (int)( 0.08131 * nScale + 0.5 ) * (-i); } } //////////////////////////////////////////////////////////////////////////////// //初始化量化表 //m_tblYQuant[0..63] 和m_tblCbCrQuant[0..63] void CCompressEncode::InitQuantTable( void ) { static unsigned short aanscales[64] = { 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 }; m_nScale = m_nQuality; if (m_nScale <= 0) m_nScale = 1; if (m_nScale > 100) m_nScale = 100; if (m_nScale < 50) m_nScale = 5000 / m_nScale; else m_nScale = 200 - m_nScale*2; memcpy( m_dqtY, std_luminance_quant_tbl, 64 ); memcpy( m_dqtCbCr, std_chrominance_quant_tbl, 64 ); ScaleTable( m_dqtY, m_nScale, 100 ); ScaleTable( m_dqtCbCr, m_nScale, 100 ); ScaleQuantTable( m_qtblY, &std_luminance_quant_tbl[0], aanscales ); ScaleQuantTable( m_qtblCbCr, &std_chrominance_quant_tbl[0], aanscales ); } //////////////////////////////////////////////////////////////////////////////// void CCompressEncode::ScaleTable(unsigned char* tbl, int scale, int max) { int i, temp, half = max/2; for (i = 0; i < 64; i++) { temp = (int)(( m_nScale * tbl[i] + half ) / max ); if (temp <= 0) temp = 1; if (temp > 255) temp = 255; tbl[i] = (unsigned char)temp; } } //////////////////////////////////////////////////////////////////////////////// void CCompressEncode::ScaleQuantTable( unsigned short* tblRst, unsigned char* tblStd, unsigned short* tblAan ) { int i, temp, half = 1<<10; for (i = 0; i < 64; i++) { temp = (int)(( m_nScale * tblStd[i] + 50 ) / 100 ); if (temp <= 0) temp = 1; if (temp > 255) temp = 255; tblRst[i] = (unsigned short)(( temp * tblAan[i] + half )>>11 ); } } //////////////////////////////////////////////////////////////////////////////// //初始化Huffman表: // HUFFMAN_TABLE m_htblYDC, m_htblYAC, m_htblCbCrDC, m_htblCbCrAC; void CCompressEncode::InitHuffmanTable( void ) { // Y dc系数 static unsigned char bitsYDC[17] = { 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }; static unsigned char valYDC[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; // CbCr dc static unsigned char bitsCbCrDC[17] = { 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }; static unsigned char valCbCrDC[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; // Y ac系数 static unsigned char bitsYAC[17] = { 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d }; static unsigned char valYAC[] = { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa }; // CbCr ac static unsigned char bitsCbCrAC[17] = { 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 }; static unsigned char valCbCrAC[] = { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa }; // 计算生成Huffman表 ComputeHuffmanTable( bitsYDC, valYDC, &m_htblYDC ); ComputeHuffmanTable( bitsYAC, valYAC, &m_htblYAC ); ComputeHuffmanTable( bitsCbCrDC, valCbCrDC, &m_htblCbCrDC ); ComputeHuffmanTable( bitsCbCrAC, valCbCrAC, &m_htblCbCrAC ); } //////////////////////////////////////////////////////////////////////////////// // 计算生成Huffman表 void CCompressEncode::ComputeHuffmanTable( unsigned char * pBits, unsigned char * pVal, HUFFMAN_TABLE * pTbl ) { int p, i, l, lastp, si; char huffsize[257]; unsigned int huffcode[257]; unsigned int code; // First we copy bits and huffval memcpy( pTbl->bits, pBits, sizeof(pTbl->bits) ); memcpy( pTbl->huffval, pVal, sizeof(pTbl->huffval) ); /* Figure C.1: make table of Huffman code length for each symbol */ /* Note that this is in code-length order. */ p = 0; for (l = 1; l <= 16; l++) { for (i = 1; i <= (int) pBits[l]; i++) huffsize[p++] = (char) l; } huffsize[p] = 0; lastp = p; /* Figure C.2: generate the codes themselves */ /* Note that this is in code-length order. */ code = 0; si = huffsize[0]; p = 0; while (huffsize[p]) { while (((int) huffsize[p]) == si) { huffcode[p++] = code; code++; } code <<= 1; si++; } /* Figure C.3: generate encoding tables */ /* These are code and size indexed by symbol value */ /* Set any codeless symbols to have code length 0; * this allows EmitBits to detect any attempt to emit such symbols. */ memset( pTbl->size, 0, sizeof( pTbl->size ) ); for (p = 0; p < lastp; p++) { pTbl->code[ pVal[p] ] = huffcode[p]; pTbl->size[ pVal[p] ] = huffsize[p]; } } /////////////////////////////////////////////////////////////////////////////// //写入JPG头,soi, app0, Y_dqt, CbCr_dqt, sof, 4 * dht, sos. void CCompressEncode::WriteJpegHeader(void) { write_soi(); write_app0(); write_dqt(0);//Y write_dqt(1);//cbcr write_sof(M_SOF0); write_dht(0, 0);//m_htblYDC write_dht(0, 1);//m_htblYAC write_dht(1, 0);//m_htblCbCrDC write_dht(1, 1);//m_htblCbCrAC write_sos(); } /////////////////////////////////////////////////////////////////////////////// void CCompressEncode::write_soi() { emit_marker(M_SOI); } void CCompressEncode::write_app0() { emit_marker(M_APP0); emit_2bytes(2 + 4 + 1 + 2 + 1 + 2 + 2 + 1 + 1); /* length */ emit_byte(0x4A); /* Identifier: ASCII "JFIF" */ emit_byte(0x46); emit_byte(0x49); emit_byte(0x46); emit_byte(0); emit_byte(1); /* Major version */ emit_byte(1); /* Minor version */ emit_byte(1); /* Pixel size information */ emit_2bytes(300); emit_2bytes(300); emit_byte(0); /* No thumbnail image */ emit_byte(0); } void CCompressEncode::write_dqt(int index)//0:Y;1:CbCr { unsigned char* dqt; if( index == 0 ) dqt = &m_dqtY[0];//changed from std with quality else dqt = &m_dqtCbCr[0]; //only allow prec = 0; emit_marker(M_DQT); emit_2bytes(67);//length emit_byte(index); int i; unsigned char qval; for (i = 0; i < 64; i++) { qval = (unsigned char) (dqt[jpeg_natural_order[i]]); emit_byte(qval); } } //currently support M_SOF0 baseline implementation void CCompressEncode::write_sof(int code) { emit_marker(code); emit_2bytes(17); //length emit_byte(8);//cinfo->data_precision); emit_2bytes(m_nHeight); emit_2bytes(m_nWidth); emit_byte(3);//cinfo->num_components); //for Y emit_byte(1);//compptr->component_id); emit_byte(34);//(compptr->h_samp_factor << 4) + compptr->v_samp_factor); emit_byte(0);//quant_tbl_no //for Cb emit_byte(2);//compptr->component_id); emit_byte(17);//(compptr->h_samp_factor << 4) + compptr->v_samp_factor); emit_byte(1);//quant_tbl_no //for Cr emit_byte(3);//compptr->component_id); emit_byte(17);//(compptr->h_samp_factor << 4) + compptr->v_samp_factor); emit_byte(1);//quant_tbl_no } void CCompressEncode::write_dht(int IsCbCr, int IsAc) { HUFFMAN_TABLE *htbl; int index; if( IsCbCr ) { if( IsAc ) { htbl = &m_htblCbCrAC; index = 17; } else { htbl = &m_htblCbCrDC; index = 1; } } else { if( IsAc ) { htbl = &m_htblYAC; index = 16; } else { htbl = &m_htblYDC; index = 0; } } emit_marker(M_DHT); int i, length = 0; for (i = 1; i <= 16; i++) length += htbl->bits[i]; emit_2bytes(length + 2 + 1 + 16); emit_byte(index); for (i = 1; i <= 16; i++) emit_byte(htbl->bits[i]); for (i = 0; i < length; i++)//varible-length emit_byte(htbl->huffval[i]); } void CCompressEncode::write_sos() { emit_marker(M_SOS); int length = 2 * 3 + 2 + 1 + 3; emit_2bytes(length); emit_byte(3);//cinfo->comps_in_scan //Y emit_byte(1);//index emit_byte(0);//dc and ac tbl use 0-th tbl //Cb emit_byte(2);//index emit_byte(0x11);//dc and ac tbl use 1-th tbl //Cr emit_byte(3);//index emit_byte(0x11);//dc and ac tbl use 1-th tbl emit_byte(0);//Ss emit_byte(0x3F);//Se emit_byte(0);// Ah/Al } //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //对图像进行压缩编码的主函数 bool CCompressEncode::CompressImage( unsigned char *pInBuf, //源数据 unsigned char *pOutBuf,//目标数据 int nWidthPix, //图像宽 int nHeight, //图像高 int& nOutputBytes //转化后字节数 ) { // 错误处理 if(( pInBuf == 0 )||( pOutBuf == 0 )) return false; m_nWidth = nWidthPix; m_nHeight = nHeight; m_pOutBuf = pOutBuf; //写入JPG头 WriteJpegHeader(); int nHeadBytes = m_pOutBuf - pOutBuf; int nRowBytes = ( m_nWidth * 3 + 3 ) / 4 * 4; //异常 if(( nWidthPix <= 0 )||( nRowBytes <= 0 )||( nHeight <= 0 )) return false; int xPixel, yPixel, xTile, yTile, cxTile, cyTile, cxBlock, cyBlock; int x, y, nTrueRows, nTrueCols, nTileBytes; unsigned char byTile[768], *pTileRow, *pLastPixel, *pHolePixel; // 水平和垂直MCU的数量 // MCU(Minimum Coded Unit), 16*16 象素 cxTile = (nWidthPix + 15)>> 4; cyTile = (nHeight + 15) >> 4; // 水平和垂直块的数量 8*8 象素 cxBlock = cxTile << 1; cyBlock = cyTile << 1; //初始化 nTileBytes = 0; m_dcY = m_dcCb = m_dcCr = 0; m_nPutBits = 0; m_nPutVal = 0; //循环对每个MCU进行处理 for( yTile = 0; yTile < cyTile; yTile++ ) { for( xTile = 0; xTile < cxTile; xTile++ ) { //获得此MCU初始相似 xPixel = xTile << 4; yPixel = yTile << 4; // 获得列和栏数 nTrueRows = 16; nTrueCols = 16; if( yPixel + nTrueRows > nHeight ) nTrueRows = nHeight - yPixel; if( xPixel + nTrueCols > nWidthPix ) nTrueCols = nWidthPix - xPixel; pTileRow = pInBuf + (m_nHeight - yPixel) * nRowBytes + xPixel * 3; //获得数据 for( y = 0; y < 16; y ++ ) { if( y < nTrueRows ) { pTileRow -= nRowBytes; memcpy( byTile + y * 16 * 3, pTileRow, nTrueCols * 3 ); if( nTrueCols < 16 ) { pLastPixel = pTileRow + (nTrueCols - 1) * 3; pHolePixel = byTile + y * 16 * 3 + nTrueCols * 3; for( x = nTrueCols; x < 16; x ++ ) { memcpy( pHolePixel, pLastPixel, 3 ); pHolePixel += 3; } } } else { memcpy( byTile + y * 16 * 3, byTile + (nTrueRows - 1) * 16 * 3, 16 * 3 ); } } //调用函数对此MCU进行压缩编码 if( ! CompressOneTile( byTile )) return false; } } //处理剩余部分 if( m_nPutBits > 0 ) { EmitLeftBits( ); } //写入结束标志 emit_marker(M_EOI); nOutputBytes = m_pOutBuf - pOutBuf; return true; } //////////////////////////////////////////////////////////////////////////////// // 对一个16*16象素的块进行基于DCT的压缩编码 bool CCompressEncode::CompressOneTile( unsigned char * pBgr ) { // 三个颜色部分 int pYCbCr[384]; // DCT变换输出 int coef[64]; // 颜色转换 BGRToYCbCrEx( pBgr, pYCbCr ); // 分别对Y/Cb/Cr几个部分进行压缩编码 Y: 4 blocks; Cb: 1 block; Cr: 1 block int i; for( i=0; i<6; i++ ) { ForwardDct( pYCbCr + i*64, coef ); Quantize( coef, i ); HuffmanEncode( coef, i ); } return true; } //////////////////////////////////////////////////////////////////////////////// // 颜色转换 void CCompressEncode::BGRToYCbCr( unsigned char * pBgr, //tile source data, in BGR format, 768 bytes unsigned char * pY, //out, Illuminance, 256 bytes unsigned char * pCb, //out, Cb, 256 bytes unsigned char * pCr //out, Cr, 256 bytes ) { int i; unsigned char r, g, b, *pByte = pBgr, *py = pY, *pcb = pCb, *pcr = pCr; for( i=0; i<256; i++ ) { b = *(pByte ++); g = *(pByte ++); r = *(pByte ++); *(py++) = (unsigned char)((m_RToY[r] + m_GToY[g] + m_BToY[b] )>>16); *(pcb++) = (unsigned char)((m_RToCb[r] + m_GToCb[g] + m_BToCb[b])>>16); *(pcr++) = (unsigned char)((m_RToCr[r] + m_GToCr[g] + m_BToCr[b])>>16); } } //////////////////////////////////////////////////////////////////////////////// void CCompressEncode::BGRToYCbCrEx( unsigned char * pBgr, //in, tile data, in BGR format, 768 bytes int * pBlock //out, Y: 256; Cb: 64; Cr: 64 ) { int x, y, *py[4], *pcb, *pcr; unsigned char r, g, b, *pByte; pByte = pBgr; for( x = 0; x < 4; x++ ) py[ x ] = pBlock + 64 * x; pcb = pBlock + 256; pcr = pBlock + 320; for( y=0; y<16; y++ ) { for( x=0; x<16; x++ ) { b = *(pByte ++); g = *(pByte ++); r = *(pByte ++); // block number is ((y/8) * 2 + x/8): 0, 1, 2, 3 *( py[((y>>3)<<1) + (x>>3)] ++ ) = ((m_RToY[ r ] + m_GToY[ g ] + m_BToY[ b ] )>>16) -128; // Equal to: (( x%2 == 0 )&&( y%2 == 0 )) if( (!(y & 1L)) && (!(x & 1L)) ) { *(pcb++) = ((m_RToCb[ r ] + m_GToCb[ g ] + m_BToCb[ b ])>>16) -128; *(pcr++) = ((m_RToCr[ r ] + m_GToCr[ g ] + m_BToCr[ b ])>>16) -128; } } } } //////////////////////////////////////////////////////////////////////////////// //离散余弦正变换 void CCompressEncode::ForwardDct( int* data, //source data, length is 64 int* coef //output dct coefficients ) { //////////////////////////////////////////////////////////////////////////// //为了方便计算定义几个宏 #define FIX_0_382683433 ((int)98) /* FIX(0.382683433) */ #define FIX_0_541196100 ((int)139) /* FIX(0.541196100) */ #define FIX_0_707106781 ((int)181) /* FIX(0.707106781) */ #define FIX_1_306562965 ((int)334) /* FIX(1.306562965) */ #define MULTIPLY(var,cons) (int)(((cons) * (var)) >> 8 ) //////////////////////////////////////////////////////////////////////////// static const int DCTSIZE = 8; int x, y; int *dataptr; int tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; int tmp10, tmp11, tmp12, tmp13; int z1, z2, z3, z4, z5, z11, z13, *coefptr; /* Pass 1: process rows. */ dataptr = data; //input coefptr = coef; //output for( y = 0; y < 8; y++ ) { 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]; /* Even part */ tmp10 = tmp0 + tmp3; /* phase 2 */ tmp13 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp12 = tmp1 - tmp2; coefptr[0] = tmp10 + tmp11; /* phase 3 */ coefptr[4] = tmp10 - tmp11; z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */ coefptr[2] = tmp13 + z1; /* phase 5 */ coefptr[6] = tmp13 - z1; /* Odd part */ tmp10 = tmp4 + tmp5; /* phase 2 */ tmp11 = tmp5 + tmp6; tmp12 = tmp6 + tmp7; /* The rotator is modified from fig 4-8 to avoid extra negations. */ z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */ z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */ z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */ z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */ z11 = tmp7 + z3; /* phase 5 */ z13 = tmp7 - z3; coefptr[5] = z13 + z2; /* phase 6 */ coefptr[3] = z13 - z2; coefptr[1] = z11 + z4; coefptr[7] = z11 - z4; dataptr += 8; /* advance pointer to next row */ coefptr += 8; } /* Pass 2: process columns. */ coefptr = coef; //both input and output for ( x = 0; x < 8; x++ ) { tmp0 = coefptr[DCTSIZE*0] + coefptr[DCTSIZE*7]; tmp7 = coefptr[DCTSIZE*0] - coefptr[DCTSIZE*7]; tmp1 = coefptr[DCTSIZE*1] + coefptr[DCTSIZE*6]; tmp6 = coefptr[DCTSIZE*1] - coefptr[DCTSIZE*6]; tmp2 = coefptr[DCTSIZE*2] + coefptr[DCTSIZE*5]; tmp5 = coefptr[DCTSIZE*2] - coefptr[DCTSIZE*5]; tmp3 = coefptr[DCTSIZE*3] + coefptr[DCTSIZE*4]; tmp4 = coefptr[DCTSIZE*3] - coefptr[DCTSIZE*4]; /* Even part */ tmp10 = tmp0 + tmp3; /* phase 2 */ tmp13 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp12 = tmp1 - tmp2; coefptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */ coefptr[DCTSIZE*4] = tmp10 - tmp11; z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */ coefptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */ coefptr[DCTSIZE*6] = tmp13 - z1; /* Odd part */ tmp10 = tmp4 + tmp5; /* phase 2 */ tmp11 = tmp5 + tmp6; tmp12 = tmp6 + tmp7; /* The rotator is modified from fig 4-8 to avoid extra negations. */ z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */ z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */ z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */ z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */ z11 = tmp7 + z3; /* phase 5 */ z13 = tmp7 - z3; coefptr[DCTSIZE*5] = z13 + z2; /* phase 6 */ coefptr[DCTSIZE*3] = z13 - z2; coefptr[DCTSIZE*1] = z11 + z4; coefptr[DCTSIZE*7] = z11 - z4; coefptr++; /* advance pointer to next column */ } } //////////////////////////////////////////////////////////////////////////////// //进行量化 void CCompressEncode::Quantize( int* coef, //coef is both in and out int iBlock //block id; Y: 0,1,2,3; Cb: 4; Cr: 5 ) { int temp; unsigned short qval, *pQuant; if( iBlock < 4 ) pQuant = m_qtblY; else pQuant = m_qtblCbCr; for (int i = 0; i < 64; i++) { qval = pQuant[i]; temp = coef[i]; #define DIVIDE_BY(a,b) if (a >= b) a /= b; else a = 0 if ( temp < 0) { temp = -temp; temp += qval>>1; /* for rounding */ DIVIDE_BY(temp, qval); temp = -temp; } else { temp += qval>>1; /* for rounding */ DIVIDE_BY(temp, qval); } coef[i] = temp; } } //////////////////////////////////////////////////////////////////////////////// //Huffman编码 bool CCompressEncode::HuffmanEncode( int* pCoef, // DCT coefficients int iBlock // 0,1,2,3:Y; 4:Cb; 5:Cr; ) { //对AC系数进行Z字型扫描 static const int jpeg_natural_order[64+16] = { 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63, 63, 63, 63, 63, 63, 63, 63, 63,//extra entries for safety 63, 63, 63, 63, 63, 63, 63, 63 }; int temp, temp2, nbits, k, r, i; int *block = pCoef; int *pLastDc = &m_dcY; HUFFMAN_TABLE *dctbl, *actbl; if( iBlock < 4 ) { dctbl = & m_htblYDC; actbl = & m_htblYAC; // pLastDc = &m_dcY; } else { dctbl = & m_htblCbCrDC; actbl = & m_htblCbCrAC; if( iBlock == 4 ) pLastDc = &m_dcCb; else pLastDc = &m_dcCr; } //对DC系数进行编码 temp = temp2 = block[0] - (*pLastDc); *pLastDc = block[0]; if (temp < 0) { temp = -temp; /* temp is abs value of input */ temp2 --; } /* Find the number of bits needed for the magnitude of the coefficient */ nbits = 0; while (temp) { nbits ++; temp >>= 1; } // Write category number if (! EmitBits( dctbl->code[nbits], dctbl->size[nbits] )) return FALSE; // Write category offset if (nbits) /* EmitBits rejects calls with size 0 */ { if (! EmitBits( (unsigned int) temp2, nbits )) return FALSE; } //////////////////////////////////////////////////////////////////////////// //对AC系数进行编码 r = 0; /* r = run length of zeros */ for (k = 1; k < 64; k++) { if ((temp = block[jpeg_natural_order[k]]) == 0) { r++; } else { /* if run length > 15, must emit special run-length-16 codes (0xF0) */ while (r > 15) { if (! EmitBits( actbl->code[0xF0], actbl->size[0xF0] )) return FALSE; r -= 16; } temp2 = temp; if (temp < 0) { temp = -temp; /* temp is abs value of input */ /* This code assumes we are on a two's complement machine */ temp2--; } /* Find the number of bits needed for the magnitude of the coefficient */ nbits = 1; /* there must be at least one 1 bit */ while ((temp >>= 1)) nbits++; /* Emit Huffman symbol for run length / number of bits */ i = (r << 4) + nbits; if (! EmitBits( actbl->code[i], actbl->size[i] )) return FALSE; // Write Category offset if (! EmitBits( (unsigned int) temp2, nbits )) return FALSE; r = 0; } } if (r > 0) { if (! EmitBits( actbl->code[0], actbl->size[0] )) return FALSE; } return TRUE; } //////////////////////////////////////////////////////////////////////////////// inline bool CCompressEncode::EmitBits( unsigned int code, //Huffman code int size //Size in bits of the Huffman code ) { /* This routine is heavily used, so it's worth coding tightly. */ int put_buffer = (int) code; int put_bits = m_nPutBits; /* if size is 0, caller used an invalid Huffman table entry */ if (size == 0) return false; put_buffer &= (((int)1)<<size) - 1; /* mask off any extra bits in code */ put_bits += size; /* new number of bits in buffer */ put_buffer <<= 24 - put_bits; /* align incoming bits */ put_buffer |= m_nPutVal; /* and merge with old buffer contents */ // If there are more than 8 bits, write it out unsigned char uc; while (put_bits >= 8) { // Write one byte out !!!! uc = (unsigned char) ((put_buffer >> 16) & 0xFF); emit_byte(uc); if (uc == 0xFF) { //need to stuff a zero byte? emit_byte(0); // Write one byte out !!!! } put_buffer <<= 8; put_bits -= 8; } m_nPutVal = put_buffer; /* update state variables */ m_nPutBits = put_bits; return TRUE; } //////////////////////////////////////////////////////////////////////////////// inline void CCompressEncode::EmitLeftBits(void) { if (! EmitBits(0x7F, 7)) /* fill 7 bits with ones */ return; m_nPutVal = 0; m_nPutBits = 0; } ////////////////////////////////////////////////////////////////////////////////

 

CompressEncode.h

CompressEncode.cpp

PicOperate.h

PicOperate.cpp

使用规则:

    char *bmppath="1.bmp";
    CString jpgpath="2.jpg";
    int qui=30;
    m_op.Load( bmppath);
    m_op.picCompressEncode(jpgpath,TRUE,qui);

哈哈

http://blog.csdn.net/s06cuiyanchao/article/details/5194354

你可能感兴趣的:(Stream,table,null,delete,buffer,byte)