//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了一个,可用主要是通过两个类实现:
-
-
-
- #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];
- char size[256];
-
-
-
- unsigned char bits[17];
-
- unsigned char huffval[256];
-
-
-
-
- }HUFFMAN_TABLE;
- class CCompressEncode
- {
- public:
- CCompressEncode();
- virtual ~CCompressEncode();
- CCompressEncode( int nQuality );
- bool CompressImage(
- unsigned char *pInBuf,
- unsigned char *pOutBuf,
- int nWidthPix,
- int nHeight,
- int& nOutputBytes
- );
-
-
-
-
- unsigned short m_nQuality, m_nScale;
-
-
- 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];
-
-
- unsigned short m_qtblY[64], m_qtblCbCr[64];
-
-
- unsigned char m_dqtY[64], m_dqtCbCr[64];
-
- HUFFMAN_TABLE m_htblYDC, m_htblYAC, m_htblCbCrDC, m_htblCbCrAC;
-
-
-
-
-
-
- unsigned short m_nWidth, m_nHeight;
-
-
- int m_dcY, m_dcCb, m_dcCr;
-
-
- 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
- );
-
- void BGRToYCbCr(
- unsigned char * pBgr,
- unsigned char * pY,
- unsigned char * pCb,
- unsigned char * pCr
- );
-
- void BGRToYCbCrEx(
- unsigned char * pBgr,
- int * pBlock
- );
-
- void ForwardDct(
- int* data,
- int* coef
- );
-
- void Quantize(
- int* coef,
- int iBlock
- );
-
- bool HuffmanEncode(
- int* pCoef,
- int iBlock
- );
-
- bool EmitBits(
- unsigned int code,
- int size
- );
-
- 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_)
// 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_)
- #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
#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
- #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;
-
-
- if( !cf.Open( pszFilename, CFile::modeRead ) )
- return( FALSE );
-
-
-
-
-
- DWORD dwDibSize;
- dwDibSize =
- cf.GetLength() - sizeof( BITMAPFILEHEADER );
-
-
- unsigned char *pDib;
- pDib = new unsigned char [dwDibSize];
- if( pDib == NULL )
- return( FALSE );
-
- BITMAPFILEHEADER BFH;
-
-
- try{
-
-
- if( cf.Read( &BFH, sizeof( BITMAPFILEHEADER ) )
- != sizeof( BITMAPFILEHEADER ) ||
-
-
- BFH.bfType != 'MB' ||
-
-
- cf.Read( pDib, dwDibSize ) != dwDibSize ){
-
-
-
- delete [] pDib;
- return( FALSE );
- }
- }
-
-
-
-
- catch( CFileException *e ){
- e->Delete();
- delete [] pDib;
- return( FALSE );
- }
-
-
-
-
- if( m_pDib != NULL )
- delete m_pDib;
-
-
-
-
- m_pDib = pDib;
- m_dwDibSize = dwDibSize;
-
-
-
- m_pBIH = (BITMAPINFOHEADER *) m_pDib;
- m_pPalette =
- (RGBQUAD *) &m_pDib[sizeof(BITMAPINFOHEADER)];
-
-
- m_width = m_pBIH->biWidth;
- m_height = m_pBIH->biHeight;
-
-
- 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;
-
-
- m_pDibBits =
- &m_pDib[sizeof(BITMAPINFOHEADER)+
- m_nPaletteEntries*sizeof(RGBQUAD)];
-
-
- if( m_Palette.GetSafeHandle() != NULL )
- m_Palette.DeleteObject();
-
-
-
-
- if( m_nPaletteEntries != 0 ){
-
-
- LOGPALETTE *pLogPal = (LOGPALETTE *) new char
- [sizeof(LOGPALETTE)+
- m_nPaletteEntries*sizeof(PALETTEENTRY)];
-
- if( pLogPal != NULL ){
-
-
-
-
- pLogPal->palVersion = 0x300;
- pLogPal->palNumEntries = m_nPaletteEntries;
-
-
-
- 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;
- }
-
-
-
- m_Palette.CreatePalette( pLogPal );
- delete [] pLogPal;
- }
- }
-
- return( TRUE );
-
- }
-
-
-
-
-
- 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;
-
-
-
-
-
- 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 );
-
-
- CFile cf;
- if( !cf.Open( filename, CFile::modeCreate | CFile::modeWrite ) )
- {
- AfxMessageBox("Can not create jpg file!");
- return;
- }
-
- cf.Write( pJpg, nOutputBytes );
-
- delete []pJpg;
- }
#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; }
-
-
-
- #include "stdafx.h"
- #include "bmptojpg.h"
- #include "CompressEncode.h"
- #ifdef _DEBUG
- #undef THIS_FILE
- static char THIS_FILE[]=__FILE__;
- #define new DEBUG_NEW
- #endif
-
-
-
-
-
- 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;
-
-
- 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,
- 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()
- {
- }
-
-
- void CCompressEncode::InitEncoder( )
- {
-
- InitColorTable( );
-
-
- InitQuantTable( );
-
-
- InitHuffmanTable( );
- }
-
-
-
-
-
-
-
-
-
-
-
-
- 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);
- }
- }
-
-
-
-
-
-
- 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 );
- }
- }
-
-
-
-
-
-
- void CCompressEncode::InitHuffmanTable( void )
- {
-
- 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 };
-
-
-
- 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 };
-
-
-
- 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 };
-
-
-
- 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 };
-
-
- ComputeHuffmanTable( bitsYDC, valYDC, &m_htblYDC );
- ComputeHuffmanTable( bitsYAC, valYAC, &m_htblYAC );
-
- ComputeHuffmanTable( bitsCbCrDC, valCbCrDC, &m_htblCbCrDC );
- ComputeHuffmanTable( bitsCbCrAC, valCbCrAC, &m_htblCbCrAC );
- }
-
-
-
-
- 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;
-
-
- memcpy( pTbl->bits, pBits, sizeof(pTbl->bits) );
- memcpy( pTbl->huffval, pVal, sizeof(pTbl->huffval) );
-
-
-
-
- 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;
-
-
-
-
- code = 0;
- si = huffsize[0];
- p = 0;
- while (huffsize[p]) {
- while (((int) huffsize[p]) == si) {
- huffcode[p++] = code;
- code++;
- }
- code <<= 1;
- si++;
- }
-
-
-
-
-
-
-
- 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];
- }
- }
-
-
-
-
- void CCompressEncode::WriteJpegHeader(void)
- {
- write_soi();
-
- write_app0();
-
- write_dqt(0);
-
- write_dqt(1);
-
- write_sof(M_SOF0);
-
- write_dht(0, 0);
- write_dht(0, 1);
- write_dht(1, 0);
- write_dht(1, 1);
-
- 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);
-
- emit_byte(0x4A);
- emit_byte(0x46);
- emit_byte(0x49);
- emit_byte(0x46);
- emit_byte(0);
-
-
- emit_byte(1);
- emit_byte(1);
- emit_byte(1);
- emit_2bytes(300);
- emit_2bytes(300);
- emit_byte(0);
- emit_byte(0);
- }
-
- void CCompressEncode::write_dqt(int index)
- {
- unsigned char* dqt;
- if( index == 0 )
- dqt = &m_dqtY[0];
- else
- dqt = &m_dqtCbCr[0];
-
-
-
- emit_marker(M_DQT);
- emit_2bytes(67);
- 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);
- }
- }
-
-
-
- void CCompressEncode::write_sof(int code)
- {
- emit_marker(code);
- emit_2bytes(17);
-
- emit_byte(8);
- emit_2bytes(m_nHeight);
- emit_2bytes(m_nWidth);
- emit_byte(3);
-
-
- emit_byte(1);
- emit_byte(34);
- emit_byte(0);
-
-
- emit_byte(2);
- emit_byte(17);
- emit_byte(1);
-
-
- emit_byte(3);
- emit_byte(17);
- emit_byte(1);
- }
-
- 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++)
- 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);
-
-
- emit_byte(1);
- emit_byte(0);
-
-
- emit_byte(2);
- emit_byte(0x11);
-
-
- emit_byte(3);
- emit_byte(0x11);
-
- emit_byte(0);
- emit_byte(0x3F);
- emit_byte(0);
- }
-
-
-
-
-
-
-
- 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;
-
-
- 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;
-
-
-
- cxTile = (nWidthPix + 15)>> 4;
- cyTile = (nHeight + 15) >> 4;
-
-
- cxBlock = cxTile << 1;
- cyBlock = cyTile << 1;
-
-
-
- nTileBytes = 0;
-
-
- m_dcY = m_dcCb = m_dcCr = 0;
-
-
- m_nPutBits = 0;
- m_nPutVal = 0;
-
-
-
- for( yTile = 0; yTile < cyTile; yTile++ )
- {
- for( xTile = 0; xTile < cxTile; xTile++ )
- {
-
- 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 );
- }
- }
-
-
- if( ! CompressOneTile( byTile ))
- return false;
- }
- }
-
-
- if( m_nPutBits > 0 )
- {
- EmitLeftBits( );
- }
-
-
- emit_marker(M_EOI);
- nOutputBytes = m_pOutBuf - pOutBuf;
- return true;
- }
-
-
-
-
- bool CCompressEncode::CompressOneTile(
- unsigned char * pBgr
- )
- {
-
- int pYCbCr[384];
-
-
- int coef[64];
-
-
- BGRToYCbCrEx( pBgr, pYCbCr );
-
-
- 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,
- unsigned char * pY,
- unsigned char * pCb,
- unsigned char * pCr
- )
- {
- 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,
- int * pBlock
- )
- {
- 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 ++);
-
-
- *( py[((y>>3)<<1) + (x>>3)] ++ ) =
- ((m_RToY[ r ] + m_GToY[ g ] + m_BToY[ b ] )>>16) -128;
-
-
- 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,
- int* coef
- )
- {
-
-
-
- #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;
-
-
-
- dataptr = data;
- coefptr = coef;
- 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];
-
-
-
- tmp10 = tmp0 + tmp3;
- tmp13 = tmp0 - tmp3;
- tmp11 = tmp1 + tmp2;
- tmp12 = tmp1 - tmp2;
-
- coefptr[0] = tmp10 + tmp11;
- coefptr[4] = tmp10 - tmp11;
-
- z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781);
- coefptr[2] = tmp13 + z1;
- coefptr[6] = tmp13 - z1;
-
-
-
- tmp10 = tmp4 + tmp5;
- tmp11 = tmp5 + tmp6;
- tmp12 = tmp6 + tmp7;
-
-
- z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433);
- z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5;
- z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5;
- z3 = MULTIPLY(tmp11, FIX_0_707106781);
-
- z11 = tmp7 + z3;
- z13 = tmp7 - z3;
-
- coefptr[5] = z13 + z2;
- coefptr[3] = z13 - z2;
- coefptr[1] = z11 + z4;
- coefptr[7] = z11 - z4;
-
- dataptr += 8;
- coefptr += 8;
- }
-
-
-
- coefptr = coef;
- 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];
-
-
-
- tmp10 = tmp0 + tmp3;
- tmp13 = tmp0 - tmp3;
- tmp11 = tmp1 + tmp2;
- tmp12 = tmp1 - tmp2;
-
- coefptr[DCTSIZE*0] = tmp10 + tmp11;
- coefptr[DCTSIZE*4] = tmp10 - tmp11;
-
- z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781);
- coefptr[DCTSIZE*2] = tmp13 + z1;
- coefptr[DCTSIZE*6] = tmp13 - z1;
-
-
-
- tmp10 = tmp4 + tmp5;
- tmp11 = tmp5 + tmp6;
- tmp12 = tmp6 + tmp7;
-
-
- z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433);
- z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5;
- z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5;
- z3 = MULTIPLY(tmp11, FIX_0_707106781);
-
- z11 = tmp7 + z3;
- z13 = tmp7 - z3;
-
- coefptr[DCTSIZE*5] = z13 + z2;
- coefptr[DCTSIZE*3] = z13 - z2;
- coefptr[DCTSIZE*1] = z11 + z4;
- coefptr[DCTSIZE*7] = z11 - z4;
-
- coefptr++;
- }
- }
-
-
-
-
-
- void CCompressEncode::Quantize(
- int* coef,
- int iBlock
- )
- {
- 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;
- DIVIDE_BY(temp, qval);
- temp = -temp;
- }
- else
- {
- temp += qval>>1;
- DIVIDE_BY(temp, qval);
- }
-
- coef[i] = temp;
- }
- }
-
-
-
-
-
-
- bool CCompressEncode::HuffmanEncode(
- int* pCoef,
- int iBlock
- )
- {
-
- 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,
- 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;
-
- }
- else
- {
- dctbl = & m_htblCbCrDC;
- actbl = & m_htblCbCrAC;
-
- if( iBlock == 4 )
- pLastDc = &m_dcCb;
- else
- pLastDc = &m_dcCr;
- }
-
-
-
- temp = temp2 = block[0] - (*pLastDc);
- *pLastDc = block[0];
-
- if (temp < 0) {
- temp = -temp;
-
- temp2 --;
- }
-
-
- nbits = 0;
- while (temp) {
- nbits ++;
- temp >>= 1;
- }
-
-
- if (! EmitBits( dctbl->code[nbits], dctbl->size[nbits] ))
- return FALSE;
-
-
- if (nbits)
- {
- if (! EmitBits( (unsigned int) temp2, nbits ))
- return FALSE;
- }
-
-
-
-
- r = 0;
-
- for (k = 1; k < 64; k++)
- {
- if ((temp = block[jpeg_natural_order[k]]) == 0)
- {
- r++;
- }
- else
- {
-
- while (r > 15) {
- if (! EmitBits( actbl->code[0xF0], actbl->size[0xF0] ))
- return FALSE;
- r -= 16;
- }
-
- temp2 = temp;
- if (temp < 0) {
- temp = -temp;
-
- temp2--;
- }
-
-
- nbits = 1;
- while ((temp >>= 1))
- nbits++;
-
-
- i = (r << 4) + nbits;
- if (! EmitBits( actbl->code[i], actbl->size[i] ))
- return FALSE;
-
-
- 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,
- int size
- )
- {
-
- int put_buffer = (int) code;
- int put_bits = m_nPutBits;
-
-
- if (size == 0)
- return false;
-
- put_buffer &= (((int)1)<<size) - 1;
-
- put_bits += size;
-
- put_buffer <<= 24 - put_bits;
-
- put_buffer |= m_nPutVal;
-
-
- unsigned char uc;
- while (put_bits >= 8)
- {
-
- uc = (unsigned char) ((put_buffer >> 16) & 0xFF);
- emit_byte(uc);
-
- if (uc == 0xFF) {
- emit_byte(0);
- }
-
- put_buffer <<= 8;
- put_bits -= 8;
- }
-
- m_nPutVal = put_buffer;
- m_nPutBits = put_bits;
-
- return TRUE;
- }
-
-
-
- inline void CCompressEncode::EmitLeftBits(void)
- {
- if (! EmitBits(0x7F, 7))
- return;
-
- m_nPutVal = 0;
- m_nPutBits = 0;
- }
-
-
-
// 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);
哈哈