📄 minijpegenc.cpp
字号:
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 CMiniJpegEncoder::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];
/* Divide the coefficient value by qval, ensuring proper rounding.
* Since C does not specify the direction of rounding for negative
* quotients, we have to force the dividend positive for portability.
*
* In most files, at least half of the output values will be zero
* (at default quantization settings, more like three-quarters...)
* so we should ensure that this case is fast. On many machines,
* a comparison is enough cheaper than a divide to make a special test
* a win. Since both inputs will be nonnegative, we need only test
* for a < b to discover whether a/b is 0.
* If your machine's division is fast enough, define FAST_DIVIDE.
*/
// Notes: Actually we use the second expression !!
/*
#ifdef FAST_DIVIDE
#define DIVIDE_BY(a,b) a /= b
#else
*/
#define DIVIDE_BY(a,b) if (a >= b) a /= b; else a = 0
//#endif
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;
}
}
////////////////////////////////////////////////////////////////////////////////
bool CMiniJpegEncoder::HuffmanEncode(
int* pCoef, // DCT coefficients
unsigned char* pOut, // Output byte stream
int iBlock, // 0,1,2,3:Y; 4:Cb; 5:Cr;
int& nBytes // Out, Byte number of Output stream
)
{
/*
* 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
};
int temp, temp2, nbits, k, r, i, nWrite;
int *block = pCoef;
int *pLastDc = &m_dcY;
HUFFMAN_TABLE *dctbl, *actbl;
nBytes = 0;
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;
}
/* Encode the DC coefficient difference per section F.1.2.1 */
temp = temp2 = block[0] - (*pLastDc);
*pLastDc = block[0];
if (temp < 0) {
temp = -temp; /* temp is abs value of input */
/* For a negative input, want temp2 = bitwise complement of abs(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 = 0;
while (temp) {
nbits ++;
temp >>= 1;
}
// Write category number
if (! EmitBits( pOut + nBytes, dctbl->code[nbits], dctbl->size[nbits], nWrite ))
return FALSE;
nBytes += nWrite;
// Write category offset
if (nbits) /* EmitBits rejects calls with size 0 */
{
if (! EmitBits( pOut + nBytes, (unsigned int) temp2, nbits, nWrite ))
return FALSE;
nBytes += nWrite;
}
////////////////////////////////////////////////////////////////////////////
/* Encode the AC coefficients per section F.1.2.2 */
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( pOut + nBytes, actbl->code[0xF0],
actbl->size[0xF0], nWrite ))
return FALSE;
nBytes += nWrite;
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( pOut + nBytes, actbl->code[i],
actbl->size[i], nWrite ))
return FALSE;
nBytes += nWrite;
// Write Category offset
if (! EmitBits( pOut + nBytes, (unsigned int) temp2,
nbits, nWrite ))
return FALSE;
nBytes += nWrite;
r = 0;
}
}
//If all the left coefs were zero, emit an end-of-block code
if (r > 0)
{
if (! EmitBits( pOut + nBytes, actbl->code[0],
actbl->size[0], nWrite ))
return FALSE;
nBytes += nWrite;
}
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////
/* Outputting bits to the file */
/* Only the right 24 bits of put_buffer are used; the valid bits are
* left-justified in this part. At most 16 bits can be passed to EmitBits
* in one call, and we never retain more than 7 bits in put_buffer
* between calls, so 24 bits are sufficient.
*/
inline bool CMiniJpegEncoder::EmitBits(
unsigned char* pOut, //Output byte stream
unsigned int code, //Huffman code
int size, //Size in bits of the Huffman code
int& nBytes //Out, bytes length
)
{
/* This routine is heavily used, so it's worth coding tightly. */
int put_buffer = (int) code;
int put_bits = m_nPutBits;
nBytes = 0;
/* 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
while (put_bits >= 8)
{
// Write one byte out !!!!
*(pOut++) = (unsigned char) ((put_buffer >> 16) & 0xFF);
nBytes ++;
/*
if (uc == 0xFF) { //need to stuff a zero byte?
*(pOut++) = (unsigned char) 0; // Write one byte out !!!!
nBytes ++;
}
*/
put_buffer <<= 8;
put_bits -= 8;
}
m_nPutVal = put_buffer; /* update state variables */
m_nPutBits = put_bits;
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////
inline void CMiniJpegEncoder::EmitLeftBits(
unsigned char* pOut, //Output byte stream
int& nBytes //Out, bytes length
)
{
unsigned char uc = (unsigned char) ((m_nPutVal >> 16) & 0xFF);
*(pOut++) = uc; // Write one byte out !!!!
nBytes = 1;
m_nPutVal = 0;
m_nPutBits = 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -