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 <core/exception.h>
26 #include <fvutils/color/conversions.h>
27 #include <fvutils/compression/jpeg_decompressor.h>
28 #include <sys/types.h>
29 
30 #include <cstdio>
31 #include <cstdlib>
32 #include <setjmp.h>
33 
34 extern "C" {
35 #include <jerror.h>
36 #include <jpeglib.h>
37 }
38 
39 namespace firevision {
40 
41 ///@cond INTERNALS
42 
43 typedef struct
44 {
45  struct jpeg_source_mgr pub;
46 
47  JOCTET *buffer;
48 } my_source_mgr;
49 
50 typedef my_source_mgr *my_src_ptr;
51 
52 struct my_error_mgr
53 {
54  struct jpeg_error_mgr pub; /* "public" fields */
55 
56  jmp_buf setjmp_buffer; /* for return to caller */
57 };
58 
59 typedef struct my_error_mgr *my_error_ptr;
60 
61 /*
62  * Here's the routine that will replace the standard error_exit method:
63  */
64 
65 METHODDEF(void)
66 my_error_exit(j_common_ptr cinfo)
67 {
68  /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
69  my_error_ptr myerr = (my_error_ptr)cinfo->err;
70 
71  /* Return control to the setjmp point */
72  longjmp(myerr->setjmp_buffer, 1);
73 }
74 
75 METHODDEF(void)
76 init_source(j_decompress_ptr cinfo)
77 {
78 }
79 
80 METHODDEF(boolean)
81 fill_input_buffer(j_decompress_ptr cinfo)
82 {
83  return TRUE;
84 }
85 
86 METHODDEF(void)
87 skip_input_data(j_decompress_ptr cinfo, long num_bytes)
88 {
89  my_src_ptr src = (my_src_ptr)cinfo->src;
90  /* Just a dumb implementation for now. Could use fseek() except
91  * it doesn't work on pipes. Not clear that being smart is worth
92  * any trouble anyway --- large skips are infrequent.
93  */
94  if (num_bytes > 0) {
95  while (num_bytes > (long)src->pub.bytes_in_buffer) {
96  num_bytes -= (long)src->pub.bytes_in_buffer;
97  (void)fill_input_buffer(cinfo);
98  /* note we assume that fill_input_buffer will never return FALSE,
99  * so suspension need not be handled.
100  */
101  }
102  src->pub.next_input_byte += (size_t)num_bytes;
103  src->pub.bytes_in_buffer -= (size_t)num_bytes;
104  }
105 }
106 
107 METHODDEF(void)
108 term_source(j_decompress_ptr cinfo)
109 {
110  /* no work necessary here */
111 }
112 
113 GLOBAL(void)
114 my_mem_src(j_decompress_ptr cinfo, JOCTET *buffer, size_t bytes)
115 {
116  my_src_ptr src;
117 
118  if (cinfo->src == NULL) { /* first time for this JPEG object? */
119  cinfo->src = (struct jpeg_source_mgr *)(*cinfo->mem->alloc_small)((j_common_ptr)cinfo,
120  JPOOL_PERMANENT,
121  sizeof(my_source_mgr));
122  src = (my_src_ptr)cinfo->src;
123  // src->buffer = (JOCTET *)
124  // (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
125  // INPUT_BUF_SIZE * SIZEOF(JOCTET));
126  }
127 
128  src = (my_src_ptr)cinfo->src;
129  src->pub.init_source = init_source;
130  src->pub.fill_input_buffer = fill_input_buffer;
131  src->pub.skip_input_data = skip_input_data;
132  src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
133  src->pub.term_source = term_source;
134  src->pub.bytes_in_buffer = bytes;
135  src->pub.next_input_byte = buffer;
136 }
137 
138 /// @endcond
139 
140 /** @class JpegImageDecompressor <fvutils/compression/jpeg_decompressor.h>
141  * Decompressor for JPEG images.
142  * @author Daniel Beck
143  * @author Tim Niemueller
144  */
145 
146 /** Constructor. */
148 {
149 }
150 
151 void
153 {
154  JSAMPROW row_pointer[1];
155  unsigned long location = 0;
156  unsigned char *buffer;
157 
158  // JPEG decompression
159  // Allocate and initialize a JPEG decompression object
160  struct jpeg_decompress_struct cinfo;
161 
162  struct my_error_mgr jerr;
163  cinfo.err = jpeg_std_error(&jerr.pub);
164  jerr.pub.error_exit = my_error_exit;
165  /* Establish the setjmp return context for my_error_exit to use. */
166  if (setjmp(jerr.setjmp_buffer)) {
167  char buffer[JMSG_LENGTH_MAX];
168  (*cinfo.err->format_message)((jpeg_common_struct *)&cinfo, buffer);
169 
170  /* If we get here, the JPEG code has signaled an error.
171  * We need to clean up the JPEG object, close the input file, and return.
172  */
173  jpeg_destroy_decompress(&cinfo);
174  throw fawkes::Exception("Decompression failed: %s", buffer);
175  }
176 
177  jpeg_create_decompress(&cinfo);
178 
179  // Specify the source of the compressed data
180  my_mem_src(&cinfo, _compressed_buffer, _compressed_buffer_size);
181 
182  // Call jpeg_read_header() to obtain image info
183  jpeg_read_header(&cinfo, TRUE);
184 
185  // set output color space
186  // cinfo.out_color_space = JCS_YCbCr;
187 
188  // Set parameters for decompression
189 
190  // jpeg_start_decompress(...);
191  jpeg_start_decompress(&cinfo);
192 
193  buffer = (unsigned char *)malloc((size_t)cinfo.output_width * (size_t)cinfo.output_height
194  * (size_t)cinfo.num_components);
195 
196  row_pointer[0] =
197  (unsigned char *)malloc((size_t)cinfo.output_width * (size_t)cinfo.num_components);
198 
199  // while (scan lines remain to be read)
200  // jpeg_read_scanlines(...);
201  while (cinfo.output_scanline < cinfo.image_height) {
202  jpeg_read_scanlines(&cinfo, row_pointer, 1);
203  for (unsigned int i = 0; i < cinfo.image_width * cinfo.num_components; i++)
204  buffer[location++] = row_pointer[0][i];
205  }
206 
207  // jpeg_finish_decompress(...);
208  jpeg_finish_decompress(&cinfo);
209 
210  // Release the JPEG decompression object
211  jpeg_destroy_decompress(&cinfo);
212 
213  free(row_pointer[0]);
214 
215  // convert to yuv422packed and store in member frame_buffer
216  convert(
217  RGB, YUV422_PLANAR, buffer, _decompressed_buffer, cinfo.output_width, cinfo.output_height);
218 
219  free(buffer);
220 }
221 
222 } // end namespace firevision
firevision::ImageDecompressor::_decompressed_buffer
unsigned char * _decompressed_buffer
Definition: imagedecompressor.h:66
firevision::JpegImageDecompressor::JpegImageDecompressor
JpegImageDecompressor()
Constructor.
Definition: jpeg_decompressor.cpp:154
firevision::JpegImageDecompressor::decompress
virtual void decompress()
Definition: jpeg_decompressor.cpp:159
firevision::ImageDecompressor::_compressed_buffer_size
unsigned int _compressed_buffer_size
Definition: imagedecompressor.h:67
firevision::ImageDecompressor::_compressed_buffer
unsigned char * _compressed_buffer
Definition: imagedecompressor.h:65
fawkes::Exception
Definition: exception.h:41