1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
5 // By downloading, copying, installing or using the software you agree to this license.
6 // If you do not agree to this license, do not download, install,
7 // copy or use the software.
10 // Intel License Agreement
11 // For Open Source Computer Vision Library
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
19 // * Redistribution's of source code must retain the above copyright notice,
20 // this list of conditions and the following disclaimer.
22 // * Redistribution's in binary form must reproduce the above copyright notice,
23 // this list of conditions and the following disclaimer in the documentation
24 // and/or other materials provided with the distribution.
26 // * The name of Intel Corporation may not be used to endorse or promote products
27 // derived from this software without specific prior written permission.
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
45 #include "grfmt_jpeg.h"
47 ////////////////////// JPEG-oriented two-level bitstream ////////////////////////
49 RMJpegBitStream::RMJpegBitStream()
53 RMJpegBitStream::~RMJpegBitStream()
58 bool RMJpegBitStream::Open( const char* filename )
63 m_is_opened = m_low_strm.Open( filename );
64 if( m_is_opened ) SetPos(0);
69 void RMJpegBitStream::Close()
76 void RMJpegBitStream::ReadBlock()
78 uchar* end = m_start + m_block_size;
79 uchar* current = m_start;
84 memmove( current - sz, m_end - sz, sz );
85 while( current < end )
87 int val = m_low_strm.GetByte();
90 *current++ = (uchar)val;
94 val = m_low_strm.GetByte();
97 else if( !(0xD0 <= val && val <= 0xD7) )
99 m_low_strm.SetPos( m_low_strm.GetPos() - 2 );
108 if( current == m_start ) throw;
111 m_end = m_start + (((current - m_start) + 3) & -4);
112 bs_bswap_block( m_start, m_end );
116 void RMJpegBitStream::Flush()
118 m_end = m_start + m_block_size;
119 m_current = m_end - 4;
123 void RMJpegBitStream::AlignOnByte()
128 int RMJpegBitStream::FindMarker()
130 int code = m_low_strm.GetWord();
131 while( (code & 0xFF00) != 0xFF00 || (code == 0xFFFF || code == 0xFF00 ))
133 code = ((code&255) << 8) | m_low_strm.GetByte();
139 /****************************** JPEG (JFIF) reader ***************************/
141 // zigzag & IDCT prescaling (AAN algorithm) tables
142 static const uchar zigzag[] =
144 0, 8, 1, 2, 9, 16, 24, 17, 10, 3, 4, 11, 18, 25, 32, 40,
145 33, 26, 19, 12, 5, 6, 13, 20, 27, 34, 41, 48, 56, 49, 42, 35,
146 28, 21, 14, 7, 15, 22, 29, 36, 43, 50, 57, 58, 51, 44, 37, 30,
147 23, 31, 38, 45, 52, 59, 60, 53, 46, 39, 47, 54, 61, 62, 55, 63,
148 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63
151 const int idct_prescale[] =
153 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
154 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270,
155 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906,
156 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315,
157 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
158 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552,
159 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446,
160 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247
164 #define fix(x, n) (int)((x)*(1 << (n)) + .5)
166 #define C1_082 fix( 1.082392200, fixb )
167 #define C1_414 fix( 1.414213562, fixb )
168 #define C1_847 fix( 1.847759065, fixb )
169 #define C2_613 fix( 2.613125930, fixb )
172 #define b_cb fix( 1.772, fixc )
173 #define g_cb -fix( 0.34414, fixc )
174 #define g_cr -fix( 0.71414, fixc )
175 #define r_cr fix( 1.402, fixc )
177 // IDCT without prescaling
178 static void aan_idct8x8( int* src, int *dst, int step )
180 int workspace[64], *work = workspace;
183 /* Pass 1: process rows */
184 for( i = 8; i > 0; i--, src += 8, work += 8 )
187 int x0 = src[5], x1 = src[3];
188 int x2 = src[1], x3 = src[7];
190 int x4 = x0 + x1; x0 -= x1;
192 x1 = x2 + x3; x2 -= x3;
193 x3 = x1 + x4; x1 -= x4;
195 x4 = (x0 + x2)*C1_847;
196 x0 = descale( x4 - x0*C2_613, fixb);
197 x2 = descale( x2*C1_082 - x4, fixb);
198 x1 = descale( x1*C1_414, fixb);
204 work[7] = x3; work[6] = x0;
205 work[5] = x1; work[4] = x2;
207 x2 = src[2]; x3 = src[6];
208 x0 = src[0]; x1 = src[4];
211 x2 = descale((x2-x3)*C1_414, fixb) - x4;
213 x3 = x0 + x1; x0 -= x1;
214 x1 = x3 + x4; x3 -= x4;
215 x4 = x0 + x2; x0 -= x2;
218 x1 -= x2; x2 = 2*x2 + x1;
219 work[7] = x1; work[0] = x2;
222 x1 = x4 + x2; x4 -= x2;
223 work[1] = x1; work[6] = x4;
225 x1 = work[5]; x2 = work[4];
226 x4 = x0 + x1; x0 -= x1;
227 x1 = x3 + x2; x3 -= x2;
229 work[2] = x4; work[5] = x0;
230 work[3] = x3; work[4] = x1;
233 /* Pass 2: process columns */
235 for( i = 8; i > 0; i--, dst+=step, work++ )
238 int x0 = work[8*5], x1 = work[8*3];
239 int x2 = work[8*1], x3 = work[8*7];
241 int x4 = x0 + x1; x0 -= x1;
242 x1 = x2 + x3; x2 -= x3;
243 x3 = x1 + x4; x1 -= x4;
245 x4 = (x0 + x2)*C1_847;
246 x0 = descale( x4 - x0*C2_613, fixb);
247 x2 = descale( x2*C1_082 - x4, fixb);
248 x1 = descale( x1*C1_414, fixb);
254 dst[7] = x3; dst[6] = x0;
255 dst[5] = x1; dst[4] = x2;
257 x2 = work[8*2]; x3 = work[8*6];
258 x0 = work[8*0]; x1 = work[8*4];
261 x2 = descale((x2-x3)*C1_414, fixb) - x4;
263 x3 = x0 + x1; x0 -= x1;
264 x1 = x3 + x4; x3 -= x4;
265 x4 = x0 + x2; x0 -= x2;
268 x1 -= x2; x2 = 2*x2 + x1;
272 dst[7] = x1; dst[0] = x2;
275 x1 = descale(x4 + x2,3);
276 x4 = descale(x4 - x2,3);
277 dst[1] = x1; dst[6] = x4;
279 x1 = dst[5]; x2 = dst[4];
281 x4 = descale(x0 + x1,3);
282 x0 = descale(x0 - x1,3);
283 x1 = descale(x3 + x2,3);
284 x3 = descale(x3 - x2,3);
286 dst[2] = x4; dst[5] = x0;
287 dst[3] = x3; dst[4] = x1;
292 static const int max_dec_htable_size = 1 << 12;
293 static const int first_table_bits = 9;
295 GrFmtJpegReader::GrFmtJpegReader()
298 m_signature ="\xFF\xD8\xFF";
299 m_description = "JFIF files (*.jpeg;*.jpg;*.jpe)";
304 for( i = 0; i < 4; i++ )
306 m_td[i] = new short[max_dec_htable_size];
307 m_ta[i] = new short[max_dec_htable_size];
312 GrFmtJpegReader::~GrFmtJpegReader()
314 for( int i = 0; i < 4; i++ )
324 int GrFmtJpegReader::GetColor()
326 return m_planes == 3;
329 void GrFmtJpegReader::Close()
334 bool GrFmtJpegReader::ReadHeader()
338 bool result = false, is_jfif = false, is_sof = false,
339 is_qt = false, is_ht = false, is_sos = false;
341 assert( strlen(m_filename) != 0 );
342 if( !m_strm.Open( m_filename )) return false;
344 memset( m_is_tq, 0, sizeof(m_is_tq));
345 memset( m_is_td, 0, sizeof(m_is_td));
346 memset( m_is_ta, 0, sizeof(m_is_ta));
351 RMByteStream& lstrm = m_strm.m_low_strm;
353 lstrm.Skip( 2 ); // skip SOI marker
357 int marker = m_strm.FindMarker() & 255;
359 // check for standalone markers
360 if( marker != 0xD8 /* SOI */ && marker != 0xD9 /* EOI */ &&
361 marker != 0x01 /* TEM */ && !( 0xD0 <= marker && marker <= 0xD7 ))
363 int pos = lstrm.GetPos();
364 int length = lstrm.GetWord();
369 lstrm.GetBytes( buffer, 5 );
370 if( strcmp(buffer, "JFIF") == 0 ) // JFIF identification
372 m_version = lstrm.GetWord();
378 m_precision = lstrm.GetByte();
379 m_height = lstrm.GetWord();
380 m_width = lstrm.GetWord();
381 m_planes = lstrm.GetByte();
383 if( m_width == 0 || m_height == 0 || // DNL not supported
384 (m_planes != 1 && m_planes != 3)) goto parsing_end;
386 memset( m_ci, -1, sizeof(m_ci));
388 for( i = 0; i < m_planes; i++ )
390 int idx = lstrm.GetByte();
392 if( idx < 1 || idx > m_planes ) // wrong index
396 cmp_info& ci = m_ci[idx-1];
398 if( ci.tq > 0 /* duplicated description */) goto parsing_end;
400 ci.h = (char)lstrm.GetByte();
401 ci.v = (char)(ci.h & 15);
403 ci.tq = (char)lstrm.GetByte();
404 if( !((ci.h == 1 || ci.h == 2 || ci.h == 4) &&
405 (ci.v == 1 || ci.v == 2 || ci.v == 4) &&
407 // chroma mcu-parts should have equal sizes and
408 // be non greater then luma sizes
409 !( i != 2 || (ci.h == m_ci[1].h && ci.v == m_ci[1].v &&
410 ci.h <= m_ci[0].h && ci.v <= m_ci[0].v)))
414 m_type = marker - 0xC0;
418 if( !load_quant_tables( length )) goto parsing_end;
423 if( !load_huffman_tables( length )) goto parsing_end;
433 m_MCUs = lstrm.GetWord();
436 lstrm.SetPos( pos + length );
445 result = is_jfif && is_sof && is_qt && is_ht && is_sos;
448 m_width = m_height = -1;
456 bool GrFmtJpegReader::load_quant_tables( int length )
461 RMByteStream& lstrm = m_strm.m_low_strm;
466 int tq = lstrm.GetByte();
470 tq_size = (64<<size) + 1;
471 if( tq > 3 || size > 1 || length < tq_size ) return false;
474 lstrm.GetBytes( buffer, tq_size - 1 );
476 if( size == 0 ) // 8 bit quant factors
478 for( i = 0; i < 64; i++ )
481 m_tq[tq][idx] = buffer[i] * idct_prescale[idx];
484 else // 16 bit quant factors
486 for( i = 0; i < 64; i++ )
489 m_tq[tq][idx] = ((unsigned short*)buffer)[i] *
500 bool GrFmtJpegReader::load_huffman_tables( int length )
502 const int max_bits = 16;
507 RMByteStream& lstrm = m_strm.m_low_strm;
512 int t = lstrm.GetByte();
516 if( t > 3 || hclass > 1 || length < 17 ) return false;
519 lstrm.GetBytes( buffer, max_bits );
520 for( i = 0, ht_size = 0; i < max_bits; i++ ) ht_size += buffer[i];
522 if( length < ht_size ) return false;
525 lstrm.GetBytes( buffer + max_bits, ht_size );
527 if( !::bs_create_decode_huffman_table(
528 ::bs_create_source_huffman_table(
529 buffer, buffer2, max_bits, first_table_bits ),
530 hclass == 0 ? m_td[t] : m_ta[t],
531 max_dec_htable_size )) return false;
541 bool GrFmtJpegReader::ReadData( uchar* data, int step, int color )
543 if( m_offset < 0 || !m_strm.IsOpened())
546 if( m_precision == 8 )
548 for( int i = 0; i < 4; i++ )
551 for( int j = 0; j < 64; j++ )
560 RMByteStream& lstrm = m_strm.m_low_strm;
561 lstrm.SetPos( m_offset );
565 int marker = m_strm.FindMarker() & 255;
567 if( marker == 0xD8 /* SOI */ || marker == 0xD9 /* EOI */ )
570 // check for standalone markers
571 if( marker != 0x01 /* TEM */ && !( 0xD0 <= marker && marker <= 0xD7 ))
573 int pos = lstrm.GetPos();
574 int length = lstrm.GetWord();
579 if( !load_huffman_tables( length )) goto decoding_end;
585 int idx[3] = { -1, -1, -1 };
586 int i, ns = lstrm.GetByte();
587 int sum = 0, a; // spectral selection & approximation
589 if( ns != m_planes ) goto decoding_end;
590 for( i = 0; i < ns; i++ )
592 int td, ta, c = lstrm.GetByte() - 1;
593 if( c < 0 || m_planes <= c )
598 if( idx[c] != -1 ) goto decoding_end;
600 td = lstrm.GetByte();
603 if( !(ta <= 3 && m_is_ta[ta] &&
604 td <= 3 && m_is_td[td] &&
605 m_is_tq[m_ci[c].tq]) )
608 m_ci[c].td = (char)td;
609 m_ci[c].ta = (char)ta;
611 sum += m_ci[c].h*m_ci[c].v;
614 if( sum > 10 ) goto decoding_end;
616 m_ss = lstrm.GetByte();
617 m_se = lstrm.GetByte();
623 ProcessScan( idx, ns, data, step, color );
624 goto decoding_end; // only single scan case is supported now
627 //m_offset = pos - 2;
631 m_MCUs = lstrm.GetWord();
635 if( marker != 0xDA ) lstrm.SetPos( pos + length );
647 void GrFmtJpegReader::ResetDecoder()
649 m_ci[0].dc_pred = m_ci[1].dc_pred = m_ci[2].dc_pred = 0;
652 void GrFmtJpegReader::ProcessScan( int* idx, int ns, uchar* data, int step, int color )
654 int i, s = 0, mcu, x1 = 0, y1 = 0;
657 int pos[3], h[3], v[3];
658 int x_shift = 0, y_shift = 0;
659 int nch = color ? 3 : 1;
661 assert( ns == m_planes && m_ss == 0 && m_se == 63 &&
662 m_al == 0 && m_ah == 0 ); // sequental & single scan
664 assert( idx[0] == 0 && (ns ==1 || (idx[1] == 1 && idx[2] == 2)));
666 for( i = 0; i < ns; i++ )
677 x_shift = h[0]/(h[1]*2);
678 y_shift = v[0]/(v[1]*2);
684 for( mcu = 0;; mcu++ )
690 if( mcu == m_MCUs && m_MCUs != 0 )
693 m_strm.AlignOnByte();
698 for( i = 0; i < ns; i++ )
701 cmp = blocks[pos[c]];
702 for( y = 0; y < v[c]; y += 8, cmp += h[c]*8 )
703 for( x = 0; x < h[c]; x += 8 )
706 if( i < (color ? 3 : 1))
708 aan_idct8x8( temp, cmp + x, h[c] );
716 if( y1 + y2 > m_height ) y2 = m_height - y1;
717 if( x1 + x2 > m_width ) x2 = m_width - x1;
720 data1 = data + x1*nch;
723 for( y = 0; y < y2; y++, data1 += step, cmp += h[0] )
727 for( x = 0; x < x2; x++ )
729 int val = descale( cmp[x] + 128*4, 2 );
730 data1[x*3] = data1[x*3 + 1] = data1[x*3 + 2] = saturate( val );
735 for( x = 0; x < x2; x++ )
737 int val = descale( cmp[x] + 128*4, 2 );
738 data1[x] = saturate( val );
744 for( y = 0; y < y2; y++, data1 += step, cmp += h[0] )
748 int shift = h[1]*(y >> y_shift);
749 int* cmpCb = blocks[pos[1]] + shift;
750 int* cmpCr = blocks[pos[2]] + shift;
751 for( x = 0; x < x2; x++ )
753 int Y = (cmp[x] + 128*4) << fixc;
754 int Cb = cmpCb[x >> x_shift];
755 int Cr = cmpCr[x >> x_shift];
756 int t = (Y + Cb*b_cb) >> (fixc + 2);
757 data1[x*3] = saturate(t);
758 t = (Y + Cb*g_cb + Cr*g_cr) >> (fixc + 2);
759 data1[x*3 + 1] = saturate(t);
760 t = (Y + Cr*r_cr) >> (fixc + 2);
761 data1[x*3 + 2] = saturate(t);
766 for( x = 0; x < x2; x++ )
768 int val = descale( cmp[x] + 128*4, 2 );
769 data1[x] = saturate(val);
781 if( y1 >= m_height ) break;
787 void GrFmtJpegReader::GetBlock( int* block, int c )
789 memset( block, 0, 64*sizeof(block[0]) );
791 assert( 0 <= c && c < 3 );
792 const short* td = m_td[m_ci[c].td];
793 const short* ta = m_ta[m_ci[c].ta];
794 const int* tq = m_tq[m_ci[c].tq];
796 // Get DC coefficient
797 int i = 0, cat = m_strm.GetHuff( td );
798 int mask = bs_bits_masks[cat];
799 int val = m_strm.Get( cat );
801 val -= (val*2 <= mask ? mask : 0);
802 m_ci[c].dc_pred = val += m_ci[c].dc_pred;
804 block[0] = (val * tq[0]) >> 16;
809 cat = m_strm.GetHuff( ta );
810 if( cat == 0 ) break; // end of block
814 mask = bs_bits_masks[cat];
815 val = m_strm.Get( cat );
817 val -= (val*2 <= mask ? mask : 0);
818 block[cat] = (val * tq[cat]) >> 16;