c19fa827e5982a2174a0f6341efcb9d55a37bf7b
[opencv] / src / highgui / grfmt_jpeg.cpp
1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
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.
8 //
9 //
10 //                        Intel License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
15 //
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
18 //
19 //   * Redistribution's of source code must retain the above copyright notice,
20 //     this list of conditions and the following disclaimer.
21 //
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.
25 //
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.
28 //
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.
39 //
40 //M*/
41
42 #include "_highgui.h"
43 #include "grfmt_jpeg.h"
44
45 #ifdef HAVE_JPEG
46
47 #include <stdio.h>
48 #include <setjmp.h>
49
50 #ifdef WIN32
51
52 #define XMD_H // prevent redefinition of INT32
53 #undef FAR  // prevent FAR redefinition
54
55 #endif
56
57 #if defined WIN32 && defined __GNUC__
58 typedef unsigned char boolean;
59 #endif
60
61 extern "C" {
62 #include "jpeglib.h"
63 }
64
65 namespace cv
66 {
67
68 struct JpegErrorMgr
69 {
70     struct jpeg_error_mgr pub;
71     jmp_buf setjmp_buffer;
72 };
73
74 struct JpegSource
75 {
76     struct jpeg_source_mgr pub;
77     int skip;
78 };
79
80 struct JpegState
81 {
82     jpeg_decompress_struct cinfo; // IJG JPEG codec structure
83     JpegErrorMgr jerr; // error processing manager state
84     JpegSource source; // memory buffer source
85 };
86
87 /////////////////////// Error processing /////////////////////
88
89 METHODDEF(void)
90 stub(j_decompress_ptr)
91 {
92 }
93
94 METHODDEF(boolean)
95 fill_input_buffer(j_decompress_ptr)
96 {
97     return FALSE;
98 }
99
100 // emulating memory input stream
101
102 METHODDEF(void)
103 skip_input_data(j_decompress_ptr cinfo, long num_bytes)
104 {
105     JpegSource* source = (JpegSource*) cinfo->src;
106
107     if( num_bytes > (long)source->pub.bytes_in_buffer )
108     {
109         // We need to skip more data than we have in the buffer.
110         // This will force the JPEG library to suspend decoding.
111         source->skip = num_bytes - source->pub.bytes_in_buffer;
112         source->pub.next_input_byte += source->pub.bytes_in_buffer;
113         source->pub.bytes_in_buffer = 0;
114     }
115     else
116     {
117         // Skip portion of the buffer
118         source->pub.bytes_in_buffer -= num_bytes;
119         source->pub.next_input_byte += num_bytes;
120         source->skip = 0;
121     }
122 }
123
124
125 GLOBAL(void)
126 jpeg_buffer_src(j_decompress_ptr cinfo, JpegSource* source)
127 {
128     cinfo->src = &source->pub;
129
130     // Prepare for suspending reader
131     source->pub.init_source = stub;
132     source->pub.fill_input_buffer = fill_input_buffer;
133     source->pub.skip_input_data = skip_input_data;
134     source->pub.resync_to_restart = jpeg_resync_to_restart;
135     source->pub.term_source = stub;
136     source->pub.bytes_in_buffer = 0; // forces fill_input_buffer on first read
137
138     source->skip = 0;
139 }
140
141
142 METHODDEF(void)
143 error_exit( j_common_ptr cinfo )
144 {
145     JpegErrorMgr* err_mgr = (JpegErrorMgr*)(cinfo->err);
146
147     /* Return control to the setjmp point */
148     longjmp( err_mgr->setjmp_buffer, 1 );
149 }
150
151
152 /////////////////////// JpegDecoder ///////////////////
153
154
155 JpegDecoder::JpegDecoder()
156 {
157     m_signature = "\xFF\xD8\xFF";
158     m_state = 0;
159     m_f = 0;
160     m_buf_supported = true;
161 }
162
163
164 JpegDecoder::~JpegDecoder()
165 {
166     close();
167 }
168
169
170 void  JpegDecoder::close()
171 {
172     if( m_state )
173     {
174         JpegState* state = (JpegState*)m_state;
175         jpeg_destroy_decompress( &state->cinfo );
176         delete state;
177         m_state = 0;
178     }
179
180     if( m_f )
181     {
182         fclose( m_f );
183         m_f = 0;
184     }
185
186     m_width = m_height = 0;
187     m_type = -1;
188 }
189
190 ImageDecoder JpegDecoder::newDecoder() const
191 {
192     return new JpegDecoder;
193 }
194
195 bool  JpegDecoder::readHeader()
196 {
197     bool result = false;
198     close();
199
200     JpegState* state = new JpegState;
201     m_state = state;
202     state->cinfo.err = jpeg_std_error(&state->jerr.pub);
203     state->jerr.pub.error_exit = error_exit;
204
205     if( setjmp( state->jerr.setjmp_buffer ) == 0 )
206     {
207         jpeg_create_decompress( &state->cinfo );
208
209         if( !m_buf.empty() )
210         {
211             jpeg_buffer_src(&state->cinfo, &state->source);
212             state->source.pub.next_input_byte = m_buf.data;
213             state->source.pub.bytes_in_buffer = m_buf.cols*m_buf.rows*m_buf.elemSize();
214         }
215         else
216         {
217             m_f = fopen( m_filename.c_str(), "rb" );
218             if( m_f )
219                 jpeg_stdio_src( &state->cinfo, m_f );
220         }
221         jpeg_read_header( &state->cinfo, TRUE );
222
223         m_width = state->cinfo.image_width;
224         m_height = state->cinfo.image_height;
225         m_type = state->cinfo.num_components > 1 ? CV_8UC3 : CV_8UC1;
226         result = true;
227     }
228
229     if( !result )
230         close();
231
232     return result;
233 }
234
235 /***************************************************************************
236  * following code is for supporting MJPEG image files
237  * based on a message of Laurent Pinchart on the video4linux mailing list
238  ***************************************************************************/
239
240 /* JPEG DHT Segment for YCrCb omitted from MJPEG data */
241 static
242 unsigned char my_jpeg_odml_dht[0x1a4] = {
243     0xff, 0xc4, 0x01, 0xa2,
244
245     0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,
246     0x00, 0x00, 0x00, 0x00, 0x00,
247     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
248
249     0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
250     0x00, 0x00, 0x00, 0x00, 0x00,
251     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
252
253     0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04,
254     0x04, 0x00, 0x00, 0x01, 0x7d,
255     0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06,
256     0x13, 0x51, 0x61, 0x07,
257     0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1,
258     0x15, 0x52, 0xd1, 0xf0,
259     0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a,
260     0x25, 0x26, 0x27, 0x28,
261     0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45,
262     0x46, 0x47, 0x48, 0x49,
263     0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65,
264     0x66, 0x67, 0x68, 0x69,
265     0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85,
266     0x86, 0x87, 0x88, 0x89,
267     0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3,
268     0xa4, 0xa5, 0xa6, 0xa7,
269     0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba,
270     0xc2, 0xc3, 0xc4, 0xc5,
271     0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
272     0xd9, 0xda, 0xe1, 0xe2,
273     0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4,
274     0xf5, 0xf6, 0xf7, 0xf8,
275     0xf9, 0xfa,
276
277     0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04,
278     0x04, 0x00, 0x01, 0x02, 0x77,
279     0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41,
280     0x51, 0x07, 0x61, 0x71,
281     0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09,
282     0x23, 0x33, 0x52, 0xf0,
283     0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17,
284     0x18, 0x19, 0x1a, 0x26,
285     0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44,
286     0x45, 0x46, 0x47, 0x48,
287     0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64,
288     0x65, 0x66, 0x67, 0x68,
289     0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83,
290     0x84, 0x85, 0x86, 0x87,
291     0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a,
292     0xa2, 0xa3, 0xa4, 0xa5,
293     0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8,
294     0xb9, 0xba, 0xc2, 0xc3,
295     0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
296     0xd7, 0xd8, 0xd9, 0xda,
297     0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4,
298     0xf5, 0xf6, 0xf7, 0xf8,
299     0xf9, 0xfa
300 };
301
302 /*
303  * Parse the DHT table.
304  * This code comes from jpeg6b (jdmarker.c).
305  */
306 static
307 int my_jpeg_load_dht (struct jpeg_decompress_struct *info, unsigned char *dht,
308               JHUFF_TBL *ac_tables[], JHUFF_TBL *dc_tables[])
309 {
310     unsigned int length = (dht[2] << 8) + dht[3] - 2;
311     unsigned int pos = 4;
312     unsigned int count, i;
313     int index;
314
315     JHUFF_TBL **hufftbl;
316     unsigned char bits[17];
317     unsigned char huffval[256];
318
319     while (length > 16)
320     {
321        bits[0] = 0;
322        index = dht[pos++];
323        count = 0;
324        for (i = 1; i <= 16; ++i)
325        {
326            bits[i] = dht[pos++];
327            count += bits[i];
328        }
329        length -= 17;
330
331        if (count > 256 || count > length)
332            return -1;
333
334        for (i = 0; i < count; ++i)
335            huffval[i] = dht[pos++];
336        length -= count;
337
338        if (index & 0x10)
339        {
340            index -= 0x10;
341            hufftbl = &ac_tables[index];
342        }
343        else
344            hufftbl = &dc_tables[index];
345
346        if (index < 0 || index >= NUM_HUFF_TBLS)
347            return -1;
348
349        if (*hufftbl == NULL)
350            *hufftbl = jpeg_alloc_huff_table ((j_common_ptr)info);
351        if (*hufftbl == NULL)
352            return -1;
353
354        memcpy ((*hufftbl)->bits, bits, sizeof (*hufftbl)->bits);
355        memcpy ((*hufftbl)->huffval, huffval, sizeof (*hufftbl)->huffval);
356     }
357
358     if (length != 0)
359        return -1;
360
361     return 0;
362 }
363
364 /***************************************************************************
365  * end of code for supportting MJPEG image files
366  * based on a message of Laurent Pinchart on the video4linux mailing list
367  ***************************************************************************/
368
369 bool  JpegDecoder::readData( Mat& img )
370 {
371     bool result = false;
372     uchar* data = img.data;
373     int step = img.step;
374     bool color = img.channels() > 1;
375     JpegState* state = (JpegState*)m_state;
376
377     if( state && m_width && m_height )
378     {
379         jpeg_decompress_struct* cinfo = &state->cinfo;
380         JpegErrorMgr* jerr = &state->jerr;
381         JSAMPARRAY buffer = 0;
382
383         if( setjmp( jerr->setjmp_buffer ) == 0 )
384         {
385             /* check if this is a mjpeg image format */
386             if ( cinfo->ac_huff_tbl_ptrs[0] == NULL &&
387                 cinfo->ac_huff_tbl_ptrs[1] == NULL &&
388                 cinfo->dc_huff_tbl_ptrs[0] == NULL &&
389                 cinfo->dc_huff_tbl_ptrs[1] == NULL )
390             {
391                 /* yes, this is a mjpeg image format, so load the correct
392                 huffman table */
393                 my_jpeg_load_dht( cinfo,
394                     my_jpeg_odml_dht,
395                     cinfo->ac_huff_tbl_ptrs,
396                     cinfo->dc_huff_tbl_ptrs );
397             }
398
399             if( color )
400             {
401                 if( cinfo->num_components != 4 )
402                 {
403                     cinfo->out_color_space = JCS_RGB;
404                     cinfo->out_color_components = 3;
405                 }
406                 else
407                 {
408                     cinfo->out_color_space = JCS_CMYK;
409                     cinfo->out_color_components = 4;
410                 }
411             }
412             else
413             {
414                 if( cinfo->num_components != 4 )
415                 {
416                     cinfo->out_color_space = JCS_GRAYSCALE;
417                     cinfo->out_color_components = 1;
418                 }
419                 else
420                 {
421                     cinfo->out_color_space = JCS_CMYK;
422                     cinfo->out_color_components = 4;
423                 }
424             }
425
426             jpeg_start_decompress( cinfo );
427
428             buffer = (*cinfo->mem->alloc_sarray)((j_common_ptr)cinfo,
429                                               JPOOL_IMAGE, m_width*4, 1 );
430
431             for( ; m_height--; data += step )
432             {
433                 jpeg_read_scanlines( cinfo, buffer, 1 );
434                 if( color )
435                 {
436                     if( cinfo->out_color_components == 3 )
437                         icvCvt_RGB2BGR_8u_C3R( buffer[0], 0, data, 0, cvSize(m_width,1) );
438                     else
439                         icvCvt_CMYK2BGR_8u_C4C3R( buffer[0], 0, data, 0, cvSize(m_width,1) );
440                 }
441                 else
442                 {
443                     if( cinfo->out_color_components == 1 )
444                         memcpy( data, buffer[0], m_width );
445                     else
446                         icvCvt_CMYK2Gray_8u_C4C1R( buffer[0], 0, data, 0, cvSize(m_width,1) );
447                 }
448             }
449             result = true;
450             jpeg_finish_decompress( cinfo );
451         }
452     }
453
454     close();
455     return result;
456 }
457
458
459 /////////////////////// JpegEncoder ///////////////////
460
461 struct JpegDestination
462 {
463     struct jpeg_destination_mgr pub;
464     vector<uchar> *buf, *dst;
465 };
466
467 METHODDEF(void)
468 stub(j_compress_ptr)
469 {
470 }
471
472 METHODDEF(void)
473 term_destination (j_compress_ptr cinfo)
474 {
475     JpegDestination* dest = (JpegDestination*)cinfo->dest;
476     size_t sz = dest->dst->size(), bufsz = dest->buf->size() - dest->pub.free_in_buffer;
477     if( bufsz > 0 )
478     {
479         dest->dst->resize(sz + bufsz);
480         memcpy( &(*dest->dst)[0] + sz, &(*dest->buf)[0], bufsz);
481     }
482 }
483
484 METHODDEF(boolean)
485 empty_output_buffer (j_compress_ptr cinfo)
486 {
487     JpegDestination* dest = (JpegDestination*)cinfo->dest;
488     size_t sz = dest->dst->size(), bufsz = dest->buf->size();
489     dest->dst->resize(sz + bufsz);
490     memcpy( &(*dest->dst)[0] + sz, &(*dest->buf)[0], bufsz);
491
492     dest->pub.next_output_byte = &(*dest->buf)[0];
493     dest->pub.free_in_buffer = bufsz;
494     return TRUE;
495 }
496
497 GLOBAL(void)
498 jpeg_buffer_dest(j_compress_ptr cinfo, JpegDestination* destination)
499 {
500     cinfo->dest = &destination->pub;
501
502     destination->pub.init_destination = stub;
503     destination->pub.empty_output_buffer = empty_output_buffer;
504     destination->pub.term_destination = term_destination;
505 }
506
507
508 JpegEncoder::JpegEncoder()
509 {
510     m_description = "JPEG files (*.jpeg;*.jpg;*.jpe)";
511     m_buf_supported = true;
512 }
513
514
515 JpegEncoder::~JpegEncoder()
516 {
517 }
518
519 ImageEncoder JpegEncoder::newEncoder() const
520 {
521     return new JpegEncoder;
522 }
523
524 bool  JpegEncoder::write( const Mat& img, const vector<int>& params )
525 {
526     int quality = 95;
527
528     for( size_t i = 0; i < params.size(); i += 2 )
529     {
530         if( params[i] == CV_IMWRITE_JPEG_QUALITY )
531         {
532             quality = params[i+1];
533             quality = MIN(MAX(quality, 0), 100);
534         }
535     }
536
537     bool result = false;
538     FILE* f = 0;
539     int _channels = img.channels();
540     int channels = _channels > 1 ? 3 : 1;
541     int width = img.cols, height = img.rows;
542
543     vector<uchar> out_buf(1 << 12);
544     AutoBuffer<uchar> _buffer;
545     uchar* buffer;
546
547     struct jpeg_compress_struct cinfo;
548     JpegErrorMgr jerr;
549     JpegDestination dest;
550
551     jpeg_create_compress(&cinfo);
552     cinfo.err = jpeg_std_error(&jerr.pub);
553     jerr.pub.error_exit = error_exit;
554
555     if( !m_buf )
556     {
557         f = fopen( m_filename.c_str(), "wb" );
558         if( !f )
559             goto _exit_;
560         jpeg_stdio_dest( &cinfo, f );
561     }
562     else
563     {
564         dest.dst = m_buf;
565         dest.buf = &out_buf;
566
567         jpeg_buffer_dest( &cinfo, &dest );
568
569         dest.pub.next_output_byte = &out_buf[0];
570         dest.pub.free_in_buffer = out_buf.size();
571     }
572
573     if( setjmp( jerr.setjmp_buffer ) == 0 )
574     {
575         cinfo.image_width = width;
576         cinfo.image_height = height;
577         cinfo.input_components = channels;
578         cinfo.in_color_space = channels > 1 ? JCS_RGB : JCS_GRAYSCALE;
579
580         jpeg_set_defaults( &cinfo );
581         jpeg_set_quality( &cinfo, quality,
582                           TRUE /* limit to baseline-JPEG values */ );
583         jpeg_start_compress( &cinfo, TRUE );
584
585         if( channels > 1 )
586             _buffer.allocate(width*channels);
587         buffer = _buffer;
588
589         for( int y = 0; y < height; y++ )
590         {
591             uchar *data = img.data + img.step*y, *ptr = data;
592
593             if( _channels == 3 )
594             {
595                 icvCvt_BGR2RGB_8u_C3R( data, 0, buffer, 0, cvSize(width,1) );
596                 ptr = buffer;
597             }
598             else if( _channels == 4 )
599             {
600                 icvCvt_BGRA2BGR_8u_C4C3R( data, 0, buffer, 0, cvSize(width,1), 2 );
601                 ptr = buffer;
602             }
603
604             jpeg_write_scanlines( &cinfo, &ptr, 1 );
605         }
606
607         jpeg_finish_compress( &cinfo );
608         result = true;
609     }
610
611 _exit_:
612     if(f) fclose(f);
613     jpeg_destroy_compress( &cinfo );
614
615     return result;
616 }
617
618 }
619
620 #endif
621
622 /* End of file. */