26 #include <fvutils/compression/jpeg_compressor.h>
27 #include <fvutils/color/yuvrgb.h>
28 #include <fvutils/color/rgbyuv.h>
30 #include <core/exception.h>
41 namespace firevision {
50 struct jpeg_error_mgr pub;
51 jmp_buf setjmp_buffer;
52 } fv_jpeg_error_mgr_t;
59 struct jpeg_destination_mgr pub;
63 } fv_jpeg_memory_destination_mgr_t;
71 fv_jpeg_init_destination (j_compress_ptr cinfo)
73 fv_jpeg_memory_destination_mgr_t *dest = (fv_jpeg_memory_destination_mgr_t *) cinfo->dest;
74 dest->pub.next_output_byte = dest->buffer;
75 dest->pub.free_in_buffer = dest->bufsize;
84 fv_jpeg_empty_output_buffer (j_compress_ptr cinfo)
86 fv_jpeg_memory_destination_mgr_t *dest = (fv_jpeg_memory_destination_mgr_t *) cinfo->dest;
87 dest->pub.next_output_byte = dest->buffer;
88 dest->pub.free_in_buffer = dest->bufsize;
99 fv_jpeg_term_destination (j_compress_ptr cinfo)
103 fv_jpeg_memory_destination_mgr_t *dest = (fv_jpeg_memory_destination_mgr_t *) cinfo->dest;
104 dest->datacount = dest->bufsize - dest->pub.free_in_buffer;
113 fv_jpeg_memory_destination_setup(j_compress_ptr cinfo, JOCTET *buffer,
int bufsize)
115 fv_jpeg_memory_destination_mgr_t *dest;
116 if ( cinfo->dest == NULL ) {
117 cinfo->dest = (
struct jpeg_destination_mgr *)
118 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
119 sizeof(fv_jpeg_memory_destination_mgr_t));
123 dest = (fv_jpeg_memory_destination_mgr_t *) cinfo->dest;
124 dest->bufsize = bufsize;
125 dest->buffer = buffer;
126 dest->pub.init_destination = fv_jpeg_init_destination;
127 dest->pub.empty_output_buffer = fv_jpeg_empty_output_buffer;
128 dest->pub.term_destination = fv_jpeg_term_destination;
132 init_source(j_decompress_ptr cinfo)
138 fill_input_buffer(j_decompress_ptr cinfo)
145 skip_input_data(j_decompress_ptr cinfo,
long num_bytes)
147 if ((
size_t)num_bytes > cinfo->src->bytes_in_buffer) {
148 cinfo->src->next_input_byte = NULL;
149 cinfo->src->bytes_in_buffer = 0;
151 cinfo->src->next_input_byte += (size_t) num_bytes;
152 cinfo->src->bytes_in_buffer -= (size_t) num_bytes;
157 term_source(j_decompress_ptr cinfo)
163 fv_jpeg_error_exit(j_common_ptr cinfo)
166 fv_jpeg_error_mgr_t *myerr = (fv_jpeg_error_mgr_t *) cinfo->err;
169 longjmp(myerr->setjmp_buffer, 1);
180 fv_jpeg_memory_source_setup(j_decompress_ptr cinfo,
unsigned char *ptr,
size_t size)
182 struct jpeg_source_mgr *src;
183 src = cinfo->src = (
struct jpeg_source_mgr *)
184 (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo,
187 src->init_source = init_source;
188 src->fill_input_buffer = fill_input_buffer;
189 src->skip_input_data = skip_input_data;
190 src->resync_to_restart = jpeg_resync_to_restart;
191 src->term_source = term_source;
192 src->next_input_byte = ptr;
193 src->bytes_in_buffer = size;
207 JpegImageCompressor::JpegImageCompressor(
unsigned int quality,
JpegColorspace jcs)
209 this->quality = quality;
214 JpegImageCompressor::~JpegImageCompressor()
220 JpegImageCompressor::compress()
222 struct jpeg_compress_struct cinfo;
223 fv_jpeg_error_mgr_t jerr;
224 unsigned int row_stride;
225 unsigned char *row_buffer;
228 fv_jpeg_memory_destination_mgr_t *dest;
231 FILE *outfile = NULL;
235 memset (&cinfo, 0,
sizeof(cinfo));
236 cinfo.err = jpeg_std_error(&jerr.pub);
237 jerr.pub.error_exit = fv_jpeg_error_exit;
240 if (setjmp(jerr.setjmp_buffer)) {
241 char buffer[JMSG_LENGTH_MAX];
242 (*cinfo.err->format_message) ((jpeg_common_struct *)&cinfo, buffer);
247 jpeg_destroy_compress(&cinfo);
251 jpeg_create_compress(&cinfo);
254 cinfo.image_width = width;
255 cinfo.image_height = height;
256 cinfo.input_components = 3;
257 if ( jpeg_cs == JPEG_CS_RGB ) {
258 cinfo.in_color_space = JCS_RGB;
260 cinfo.in_color_space = JCS_YCbCr;
263 row_stride = cinfo.image_width * cinfo.input_components;
265 if ( compdest == COMP_DEST_MEM ) {
267 fv_jpeg_memory_destination_setup(&cinfo, (JOCTET *)jpeg_buffer, jpeg_buffer_size);
269 outfile = fopen(filename,
"wb");
270 if (outfile == NULL) {
273 jpeg_stdio_dest( &cinfo, outfile );
276 jpeg_set_defaults(&cinfo);
277 jpeg_set_quality (&cinfo, quality,
true );
278 jpeg_start_compress(&cinfo,
true);
281 row_buffer = (
unsigned char *)malloc( row_stride );
284 if ( jpeg_cs == JPEG_CS_RGB ) {
285 while (cinfo.next_scanline < cinfo.image_height) {
286 convert_line_yuv422planar_to_rgb( buffer, row_buffer,
287 cinfo.image_width, cinfo.image_height,
288 cinfo.next_scanline, 0 );
289 jpeg_write_scanlines(&cinfo, &row_buffer, 1);
292 while (cinfo.next_scanline < cinfo.image_height) {
293 convert_line_yuv422planar_to_yuv444packed( buffer, row_buffer,
294 cinfo.image_width, cinfo.image_height,
295 cinfo.next_scanline, 0 );
296 jpeg_write_scanlines(&cinfo, &row_buffer, 1);
301 jpeg_finish_compress(&cinfo);
303 if ( compdest == COMP_DEST_MEM ) {
305 dest=(fv_jpeg_memory_destination_mgr_t *)cinfo.dest;
306 jpeg_bytes = dest->datacount;
312 jpeg_destroy_compress(&cinfo);
318 JpegImageCompressor::set_image_dimensions(
unsigned int width,
unsigned int height)
321 this->height = height;
326 JpegImageCompressor::set_image_buffer(colorspace_t cspace,
unsigned char *buffer)
328 if ( cspace == YUV422_PLANAR ) {
329 this->buffer = buffer;
349 JpegImageCompressor::set_destination_buffer(
unsigned char *buf,
unsigned int buf_size)
352 jpeg_buffer_size = buf_size;
357 JpegImageCompressor::compressed_size()
363 JpegImageCompressor::recommended_compressed_buffer_size()
365 return width * height / 4;
370 JpegImageCompressor::set_filename(
const char *filename)
372 this->filename = filename;
JpegColorspace
JPEG color space.
CompressionDestination
Where to put the compressed image.
Base class for exceptions in Fawkes.