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
34extern "C" {
35#include <jerror.h>
36#include <jpeglib.h>
37}
38
39namespace firevision {
40
41///@cond INTERNALS
42
43typedef struct
44{
45 struct jpeg_source_mgr pub;
46
47 JOCTET *buffer;
48} my_source_mgr;
49
50typedef my_source_mgr *my_src_ptr;
51
52struct my_error_mgr
53{
54 struct jpeg_error_mgr pub; /* "public" fields */
55
56 jmp_buf setjmp_buffer; /* for return to caller */
57};
58
59typedef struct my_error_mgr *my_error_ptr;
60
61/*
62 * Here's the routine that will replace the standard error_exit method:
63 */
64
65METHODDEF(void)
66my_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
75METHODDEF(void)
76init_source(j_decompress_ptr cinfo)
77{
78}
79
80METHODDEF(boolean)
81fill_input_buffer(j_decompress_ptr cinfo)
82{
83 return TRUE;
84}
85
86METHODDEF(void)
87skip_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
107METHODDEF(void)
108term_source(j_decompress_ptr cinfo)
109{
110 /* no work necessary here */
111}
112
113GLOBAL(void)
114my_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
151void
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
Base class for exceptions in Fawkes.
Definition: exception.h:36
unsigned char * _compressed_buffer
Buffer containing the compressed image.
unsigned char * _decompressed_buffer
Buffer containing the decompressed image after decompression.
unsigned int _compressed_buffer_size
Size in bytes of _compressed_buffer.
virtual void decompress()
Decompress image.