📄 tonyjpegencoder.cpp
字号:
/****************************************************************************
* Author: Dr. Tony Lin *
* Email: lintong@cis.pku.edu.cn *
* Release Date: Dec. 2002 *
* *
* Name: TonyJpegLib, rewritten from IJG codes *
* Source: IJG v.6a JPEG LIB *
* Purpose: Support real jpeg file, with readable code *
* *
* Acknowlegement: Thanks for great IJG, and Chris Losinger *
* *
* Legal Issues: (almost same as IJG with followings) *
* *
* 1. We don't promise that this software works. *
* 2. You can use this software for whatever you want. *
* You don't have to pay. *
* 3. You may not pretend that you wrote this software. If you use it *
* in a program, you must acknowledge somewhere. That is, please *
* metion IJG, and Me, Dr. Tony Lin. *
* *
*****************************************************************************/
////////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "TonyJpegEncoder.h"
////////////////////////////////////////////////////////////////////////////////
//JPEG marker codes
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;
/*
* jpeg_natural_order[i] is the natural-order position of the i'th
* element of zigzag order.
*
* When reading corrupted data, the Huffman decoders could attempt
* to reference an entry beyond the end of this array (if the decoded
* zero run length reaches past the end of the block). To prevent
* wild stores without adding an inner-loop test, we put some extra
* "63"s after the real entries. This will cause the extra coefficient
* to be stored in location 63 of the block, not somewhere random.
* The worst case would be a run-length of 15, which means we need 16
* fake entries.
*/
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
};
// These are the sample quantization tables given in JPEG spec section K.1.
// The spec says that the values given produce "good" quality, and
// when divided by 2, "very good" quality.
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;
////////////////////////////////////////////////////////////////////////////////
CTonyJpegEncoder::CTonyJpegEncoder( )
{
m_nQuality = 50;
InitEncoder( );
}
CTonyJpegEncoder::CTonyJpegEncoder( int nQuality )
{
m_nQuality = nQuality;
InitEncoder( );
}
CTonyJpegEncoder::~CTonyJpegEncoder( )
{
}
////////////////////////////////////////////////////////////////////////////////
// Prepare for all the tables needed,
// eg. quantization tables, huff tables, color convert tables
// 1 <= nQuality <= 100, is used for quantization scaling
// Computing once, and reuse them again and again !!!!!!!
void CTonyJpegEncoder::InitEncoder( )
{
// prepare color convert table, from bgr to ycbcr
InitColorTable( );
// prepare two quant tables, one for Y, and another for CbCr
InitQuantTable( );
// prepare four huffman tables:
InitHuffmanTable( );
}
////////////////////////////////////////////////////////////////////////////////
// Name: CTonyJpegEncoder::InitColorTable()
// Purpose:
// Save RGB->YCC colorspace conversion for reuse, only computing once
// so dont need multiply in color conversion later
/* Notes:
*
* YCbCr is defined per CCIR 601-1, except that Cb and Cr are
* normalized to the range 0 .. 255 rather than -0.5 .. 0.5.
* The conversion equations to be implemented are therefore
*
* 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
*
* (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.)
* To avoid floating-point arithmetic, we represent the fractional constants
* as integers scaled up by 2^16 (about 4 digits precision); we have to divide
* the products by 2^16, with appropriate rounding, to get the correct answer.
*/
void CTonyJpegEncoder::InitColorTable( void )
{
int i;
int nScale = 1L << 16; //equal to power(2,16)
int CBCR_OFFSET = 128<<16;
/*
* nHalf is for (y, cb, cr) rounding, equal to (1L<<16)*0.5
* If (R,G,B)=(0,0,1), then Cb = 128.5, should round to 129
* Using these tables will produce 129 too:
* Cb = (int)((RToCb[0] + GToCb[0] + BToCb[1]) >> 16)
* = (int)(( 0 + 0 + 1L<<15 + 1L<<15 + 128 * 1L<<16 ) >> 16)
* = (int)(( 1L<<16 + 128 * 1L<<16 ) >> 16 )
* = 129
*/
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);
}
}
////////////////////////////////////////////////////////////////////////////////
// InitQuantTable will produce customized quantization table into:
// m_tblYQuant[0..63] and m_tblCbCrQuant[0..63]
void CTonyJpegEncoder::InitQuantTable( void )
{
/* For AA&N IDCT method, divisors are equal to quantization
* coefficients scaled by scalefactor[row]*scalefactor[col], where
* scalefactor[0] = 1
* scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7
* We apply a further scale factor of 8.
*/
static unsigned short aanscales[64] = {
/* precomputed values scaled up by 14 bits */
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
};
// Safety checking. Convert 0 to 1 to avoid zero divide.
m_nScale = m_nQuality;
if (m_nScale <= 0)
m_nScale = 1;
if (m_nScale > 100)
m_nScale = 100;
// Non-linear map: 1->5000, 10->500, 25->200, 50->100, 75->50, 100->0
if (m_nScale < 50)
m_nScale = 5000 / m_nScale;
else
m_nScale = 200 - m_nScale*2;
// use std to initialize
memcpy( m_dqtY, std_luminance_quant_tbl, 64 );
memcpy( m_dqtCbCr, std_chrominance_quant_tbl, 64 );
// scale dqt for writing jpeg header
ScaleTable( m_dqtY, m_nScale, 100 );
ScaleTable( m_dqtCbCr, m_nScale, 100 );
// Scale the Y and CbCr quant table, respectively
ScaleQuantTable( m_qtblY, &std_luminance_quant_tbl[0], aanscales );
ScaleQuantTable( m_qtblCbCr, &std_chrominance_quant_tbl[0], aanscales );
}
////////////////////////////////////////////////////////////////////////////////
void CTonyJpegEncoder::ScaleTable(unsigned char* tbl, int scale, int max)
{
int i, temp, half = max/2;
for (i = 0; i < 64; i++)
{
// (1) user scale up
temp = (int)(( m_nScale * tbl[i] + half ) / max );
// limit to baseline range
if (temp <= 0)
temp = 1;
if (temp > 255)
temp = 255;
// (2) scaling needed for AA&N algorithm
tbl[i] = (unsigned char)temp;
}
}
////////////////////////////////////////////////////////////////////////////////
void CTonyJpegEncoder::ScaleQuantTable(
unsigned short* tblRst, //result quant table
unsigned char* tblStd, //standard quant table
unsigned short* tblAan //scale factor for AAN dct
)
{
int i, temp, half = 1<<10;
for (i = 0; i < 64; i++)
{
// (1) user scale up
temp = (int)(( m_nScale * tblStd[i] + 50 ) / 100 );
// limit to baseline range
if (temp <= 0)
temp = 1;
if (temp > 255)
temp = 255;
// (2) scaling needed for AA&N algorithm
tblRst[i] = (unsigned short)(( temp * tblAan[i] + half )>>11 );
}
}
////////////////////////////////////////////////////////////////////////////////
// Prepare four Huffman tables:
// HUFFMAN_TABLE m_htblYDC, m_htblYAC, m_htblCbCrDC, m_htblCbCrAC;
void CTonyJpegEncoder::InitHuffmanTable( void )
{
// Y dc component
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 component
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 };
// Compute four derived Huffman tables
ComputeHuffmanTable( bitsYDC, valYDC, &m_htblYDC );
ComputeHuffmanTable( bitsYAC, valYAC, &m_htblYAC );
ComputeHuffmanTable( bitsCbCrDC, valCbCrDC, &m_htblCbCrDC );
ComputeHuffmanTable( bitsCbCrAC, valCbCrAC, &m_htblCbCrAC );
}
////////////////////////////////////////////////////////////////////////////////
// Compute the derived values for a Huffman table.
// also, add bits[] and huffval[] to Hufftable for writing jpeg file header
void CTonyJpegEncoder::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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -