Fawkes API  Fawkes Development Version
jpeg_decompressor.cpp
1 
2 /***************************************************************************
3  * imagedecompressor.h - image de-compressor interface
4  *
5  * Created: July 2007 (Sci-Bono, South Africa, B&B)
6  * Copyright 2006-2007 Daniel Beck
7  * 2007-2011 Tim Niemueller [www.niemueller.de]
8  *
9  ****************************************************************************/
10 
11 /* This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version. A runtime exception applies to
15  * this software (see LICENSE.GPL_WRE file mentioned below for details).
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU Library General Public License for more details.
21  *
22  * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
23  */
24 
25 #include <fvutils/color/conversions.h>
26 #include <fvutils/compression/jpeg_decompressor.h>
27 #include <core/exception.h>
28 
29 #include <sys/types.h>
30 #include <cstdio>
31 #include <cstdlib>
32 #include <setjmp.h>
33 
34 extern "C" {
35 #include <jpeglib.h>
36 #include <jerror.h>
37 }
38 
39 namespace firevision {
40 #if 0 /* just to make Emacs auto-indent happy */
41 }
42 #endif
43 
44 ///@cond INTERNALS
45 
46 typedef struct {
47  struct jpeg_source_mgr pub;
48 
49  JOCTET * buffer;
50 } my_source_mgr;
51 
52 typedef my_source_mgr * my_src_ptr;
53 
54 
55 struct my_error_mgr {
56  struct jpeg_error_mgr pub; /* "public" fields */
57 
58  jmp_buf setjmp_buffer; /* for return to caller */
59 };
60 
61 typedef struct my_error_mgr * my_error_ptr;
62 
63 /*
64  * Here's the routine that will replace the standard error_exit method:
65  */
66 
67 METHODDEF(void)
68 my_error_exit (j_common_ptr cinfo)
69 {
70  /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
71  my_error_ptr myerr = (my_error_ptr) cinfo->err;
72 
73  /* Return control to the setjmp point */
74  longjmp(myerr->setjmp_buffer, 1);
75 }
76 
77 METHODDEF(void)
78 init_source (j_decompress_ptr cinfo)
79 {
80 }
81 
82 
83 METHODDEF(boolean)
84 fill_input_buffer (j_decompress_ptr cinfo)
85 {
86  return TRUE;
87 }
88 
89 METHODDEF(void)
90 skip_input_data (j_decompress_ptr cinfo, long num_bytes)
91 {
92  my_src_ptr src = (my_src_ptr) cinfo->src;
93  /* Just a dumb implementation for now. Could use fseek() except
94  * it doesn't work on pipes. Not clear that being smart is worth
95  * any trouble anyway --- large skips are infrequent.
96  */
97  if (num_bytes > 0) {
98  while (num_bytes > (long) src->pub.bytes_in_buffer) {
99  num_bytes -= (long) src->pub.bytes_in_buffer;
100  (void) fill_input_buffer(cinfo);
101  /* note we assume that fill_input_buffer will never return FALSE,
102  * so suspension need not be handled.
103  */
104  }
105  src->pub.next_input_byte += (size_t) num_bytes;
106  src->pub.bytes_in_buffer -= (size_t) num_bytes;
107  }
108 }
109 
110 METHODDEF(void)
111 term_source (j_decompress_ptr cinfo)
112 {
113  /* no work necessary here */
114 }
115 
116 GLOBAL(void)
117 my_mem_src (j_decompress_ptr cinfo, JOCTET * buffer, size_t bytes)
118 {
119  my_src_ptr src;
120 
121  if (cinfo->src == NULL) { /* first time for this JPEG object? */
122  cinfo->src = (struct jpeg_source_mgr *)
123  (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
124  sizeof(my_source_mgr));
125  src = (my_src_ptr) cinfo->src;
126 // src->buffer = (JOCTET *)
127 // (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
128 // INPUT_BUF_SIZE * SIZEOF(JOCTET));
129  }
130 
131  src = (my_src_ptr) cinfo->src;
132  src->pub.init_source = init_source;
133  src->pub.fill_input_buffer = fill_input_buffer;
134  src->pub.skip_input_data = skip_input_data;
135  src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
136  src->pub.term_source = term_source;
137  src->pub.bytes_in_buffer = bytes;
138  src->pub.next_input_byte = buffer;
139 }
140 
141 /// @endcond
142 
143 /** @class JpegImageDecompressor <fvutils/compression/jpeg_decompressor.h>
144  * Decompressor for JPEG images.
145  * @author Daniel Beck
146  * @author Tim Niemueller
147  */
148 
149 /** Constructor. */
151 {
152 }
153 
154 void
156 {
157  JSAMPROW row_pointer[1];
158  unsigned long location = 0;
159  unsigned char *buffer;
160 
161  // JPEG decompression
162  // Allocate and initialize a JPEG decompression object
163  struct jpeg_decompress_struct cinfo;
164 
165  struct my_error_mgr jerr;
166  cinfo.err = jpeg_std_error(&jerr.pub);
167  jerr.pub.error_exit = my_error_exit;
168  /* Establish the setjmp return context for my_error_exit to use. */
169  if (setjmp(jerr.setjmp_buffer)) {
170  char buffer[JMSG_LENGTH_MAX];
171  (*cinfo.err->format_message) ((jpeg_common_struct *)&cinfo, buffer);
172 
173  /* If we get here, the JPEG code has signaled an error.
174  * We need to clean up the JPEG object, close the input file, and return.
175  */
176  jpeg_destroy_decompress(&cinfo);
177  throw fawkes::Exception("Decompression failed: %s", buffer);
178  }
179 
180  jpeg_create_decompress(&cinfo);
181 
182  // Specify the source of the compressed data
183  my_mem_src(&cinfo, _compressed_buffer, _compressed_buffer_size);
184 
185  // Call jpeg_read_header() to obtain image info
186  jpeg_read_header(&cinfo, TRUE);
187 
188  // set output color space
189  // cinfo.out_color_space = JCS_YCbCr;
190 
191  // Set parameters for decompression
192 
193  // jpeg_start_decompress(...);
194  jpeg_start_decompress(&cinfo);
195 
196  buffer = (unsigned char*)malloc( cinfo.output_width * cinfo.output_height * cinfo.num_components );
197 
198  row_pointer[0] = (unsigned char *)malloc( cinfo.output_width * cinfo.num_components );
199 
200  // while (scan lines remain to be read)
201  // jpeg_read_scanlines(...);
202  while( cinfo.output_scanline < cinfo.image_height )
203  {
204  jpeg_read_scanlines( &cinfo, row_pointer, 1 );
205  for( unsigned int i=0; i < cinfo.image_width * cinfo.num_components; i++)
206  buffer[location++] = row_pointer[0][i];
207  }
208 
209  // jpeg_finish_decompress(...);
210  jpeg_finish_decompress(&cinfo);
211 
212  // Release the JPEG decompression object
213  jpeg_destroy_decompress(&cinfo);
214 
215  free(row_pointer[0]);
216 
217  // convert to yuv422packed and store in member frame_buffer
218  convert(RGB, YUV422_PLANAR, buffer, _decompressed_buffer, cinfo.output_width, cinfo.output_height);
219 
220  free(buffer);
221 
222 }
223 
224 } // end namespace firevision
virtual void decompress()
Decompress image.
Base class for exceptions in Fawkes.
Definition: exception.h:36