grfmt_jpeg.cpp.svn-base
来自「非结构化路识别」· SVN-BASE 代码 · 共 1,652 行 · 第 1/4 页
SVN-BASE
1,652 行
max_dec_htable_size )) return false;
if( hclass == 0 )
m_is_td[t] = true;
else
m_is_ta[t] = true;
}
return true;
}
bool GrFmtJpegReader::ReadData( uchar* data, int step, int color )
{
if( m_offset < 0 || !m_strm.IsOpened())
return false;
if( setjmp( m_strm.JmpBuf()) == 0 )
{
RMByteStream& lstrm = m_strm.m_low_strm;
lstrm.SetPos( m_offset );
for(;;)
{
int marker = m_strm.FindMarker() & 255;
if( marker == 0xD8 /* SOI */ || marker == 0xD9 /* EOI */ )
goto decoding_end;
// check for standalone markers
if( marker != 0x01 /* TEM */ && !( 0xD0 <= marker && marker <= 0xD7 ))
{
int pos = lstrm.GetPos();
int length = lstrm.GetWord();
switch( marker )
{
case 0xC4: // DHT
if( !LoadHuffmanTables( length )) goto decoding_end;
break;
case 0xDA: // SOS
// read scan header
{
int idx[3] = { -1, -1, -1 };
int i, ns = lstrm.GetByte();
int sum = 0, a; // spectral selection & approximation
if( ns != m_planes ) goto decoding_end;
for( i = 0; i < ns; i++ )
{
int td, ta, c = lstrm.GetByte() - 1;
if( c < 0 || m_planes <= c )
{
c = i; // hack
}
if( idx[c] != -1 ) goto decoding_end;
idx[i] = c;
td = lstrm.GetByte();
ta = td & 15;
td >>= 4;
if( !(ta <= 3 && m_is_ta[ta] &&
td <= 3 && m_is_td[td] &&
m_is_tq[m_ci[c].tq]) )
goto decoding_end;
m_ci[c].td = (char)td;
m_ci[c].ta = (char)ta;
sum += m_ci[c].h*m_ci[c].v;
}
if( sum > 10 ) goto decoding_end;
m_ss = lstrm.GetByte();
m_se = lstrm.GetByte();
a = lstrm.GetByte();
m_al = a & 15;
m_ah = a >> 4;
ProcessScan( idx, ns, data, step, color );
goto decoding_end; // only single scan case is supported now
}
//m_offset = pos - 2;
//break;
case 0xDD: // DRI
m_MCUs = lstrm.GetWord();
break;
}
if( marker != 0xDA ) lstrm.SetPos( pos + length );
}
}
decoding_end: ;
}
return true;
}
void GrFmtJpegReader::ResetDecoder()
{
m_ci[0].dc_pred = m_ci[1].dc_pred = m_ci[2].dc_pred = 0;
}
void GrFmtJpegReader::ProcessScan( int* idx, int ns, uchar* data, int step, int color )
{
int i, s = 0, mcu, x1 = 0, y1 = 0;
int temp[64];
int blocks[10][64];
int pos[3], h[3], v[3];
int x_shift = 0, y_shift = 0;
int nch = color ? 3 : 1;
assert( ns == m_planes && m_ss == 0 && m_se == 63 &&
m_al == 0 && m_ah == 0 ); // sequental & single scan
assert( idx[0] == 0 && (ns ==1 || (idx[1] == 1 && idx[2] == 2)));
for( i = 0; i < ns; i++ )
{
int c = idx[i];
h[c] = m_ci[c].h*8;
v[c] = m_ci[c].v*8;
pos[c] = s >> 6;
s += h[c]*v[c];
}
if( ns == 3 )
{
x_shift = h[0]/(h[1]*2);
y_shift = v[0]/(v[1]*2);
}
m_strm.Flush();
ResetDecoder();
for( mcu = 0;; mcu++ )
{
int x2, y2, x, y;
int* cmp;
uchar* data1;
if( mcu == m_MCUs && m_MCUs != 0 )
{
ResetDecoder();
m_strm.AlignOnByte();
mcu = 0;
}
// Get mcu
for( i = 0; i < ns; i++ )
{
int c = idx[i];
cmp = blocks[pos[c]];
for( y = 0; y < v[c]; y += 8, cmp += h[c]*8 )
for( x = 0; x < h[c]; x += 8 )
{
GetBlock( temp, c );
if( i < (color ? 3 : 1))
{
aan_idct8x8( temp, cmp + x, h[c] );
}
}
}
y2 = v[0];
x2 = h[0];
if( y1 + y2 > m_height ) y2 = m_height - y1;
if( x1 + x2 > m_width ) x2 = m_width - x1;
cmp = blocks[0];
data1 = data + x1*nch;
if( ns == 1 )
for( y = 0; y < y2; y++, data1 += step, cmp += h[0] )
{
if( color )
{
for( x = 0; x < x2; x++ )
{
int val = descale( cmp[x] + 128*4, 2 );
data1[x*3] = data1[x*3 + 1] = data1[x*3 + 2] = saturate( val );
}
}
else
{
for( x = 0; x < x2; x++ )
{
int val = descale( cmp[x] + 128*4, 2 );
data1[x] = saturate( val );
}
}
}
else
{
for( y = 0; y < y2; y++, data1 += step, cmp += h[0] )
{
if( color )
{
int shift = h[1]*(y >> y_shift);
int* cmpCb = blocks[pos[1]] + shift;
int* cmpCr = blocks[pos[2]] + shift;
for( x = 0; x < x2; x++ )
{
int Y = (cmp[x] + 128*4) << fixc;
int Cb = cmpCb[x >> x_shift];
int Cr = cmpCr[x >> x_shift];
int t = (Y + Cb*b_cb) >> (fixc + 2);
data1[x*3] = saturate(t);
t = (Y + Cb*g_cb + Cr*g_cr) >> (fixc + 2);
data1[x*3 + 1] = saturate(t);
t = (Y + Cr*r_cr) >> (fixc + 2);
data1[x*3 + 2] = saturate(t);
}
}
else
{
for( x = 0; x < x2; x++ )
{
int val = descale( cmp[x] + 128*4, 2 );
data1[x] = saturate(val);
}
}
}
}
x1 += h[0];
if( x1 >= m_width )
{
x1 = 0;
y1 += v[0];
data += v[0]*step;
if( y1 >= m_height ) break;
}
}
}
void GrFmtJpegReader::GetBlock( int* block, int c )
{
memset( block, 0, 64*sizeof(block[0]) );
assert( 0 <= c && c < 3 );
const short* td = m_td[m_ci[c].td];
const short* ta = m_ta[m_ci[c].ta];
const int* tq = m_tq[m_ci[c].tq];
// Get DC coefficient
int i = 0, cat = m_strm.GetHuff( td );
int mask = bs_bit_mask[cat];
int val = m_strm.Get( cat );
val -= (val*2 <= mask ? mask : 0);
m_ci[c].dc_pred = val += m_ci[c].dc_pred;
block[0] = descale(val * tq[0],16);
// Get AC coeffs
for(;;)
{
cat = m_strm.GetHuff( ta );
if( cat == 0 ) break; // end of block
i += (cat >> 4) + 1;
cat &= 15;
mask = bs_bit_mask[cat];
val = m_strm.Get( cat );
cat = zigzag[i];
val -= (val*2 <= mask ? mask : 0);
block[cat] = descale(val * tq[cat], 16);
assert( i <= 63 );
if( i >= 63 ) break;
}
}
////////////////////// WJpegStream ///////////////////////
WJpegBitStream::WJpegBitStream()
{
}
WJpegBitStream::~WJpegBitStream()
{
Close();
m_is_opened = false;
}
bool WJpegBitStream::Open( const char* filename )
{
Close();
Allocate();
m_is_opened = m_low_strm.Open( filename );
if( m_is_opened )
{
m_block_pos = 0;
ResetBuffer();
}
return m_is_opened;
}
void WJpegBitStream::Close()
{
if( m_is_opened )
{
Flush();
m_low_strm.Close();
m_is_opened = false;
}
}
void WJpegBitStream::Flush()
{
Put( -1, m_bit_idx & 31 );
*((ulong*&)m_current)++ = m_val;
WriteBlock();
ResetBuffer();
}
void WJpegBitStream::WriteBlock()
{
uchar* ptr = m_start;
if( !bsIsBigEndian() )
bsBSwapBlock( m_start, m_current );
while( ptr < m_current )
{
int val = *ptr++;
m_low_strm.PutByte( val );
if( val == 0xff )
{
m_low_strm.PutByte( 0 );
}
}
m_current = m_start;
}
/////////////////////// GrFmtJpegWriter ///////////////////
GrFmtJpegWriter::GrFmtJpegWriter( const char* filename ) : GrFmtWriter( filename )
{
}
GrFmtJpegWriter::~GrFmtJpegWriter()
{
}
// Standard JPEG quantization tables
static const uchar jpegTableK1_T[] =
{
16, 12, 14, 14, 18, 24, 49, 72,
11, 12, 13, 17, 22, 35, 64, 92,
10, 14, 16, 22, 37, 55, 78, 95,
16, 19, 24, 29, 56, 64, 87, 98,
24, 26, 40, 51, 68, 81, 103, 112,
40, 58, 57, 87, 109, 104, 121, 100,
51, 60, 69, 80, 103, 113, 120, 103,
61, 55, 56, 62, 77, 92, 101, 99
};
static const uchar jpegTableK2_T[] =
{
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
};
// Standard Huffman tables
// ... for luma DCs.
static const uchar jpegTableK3[] =
{
0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
};
// ... for chroma DCs.
static const uchar jpegTableK4[] =
{
0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
};
// ... for luma ACs.
static const uchar jpegTableK5[] =
{
0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 125,
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,
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?