jpeg_decompressor.cpp

00001
00002 /***************************************************************************
00003  *  imagedecompressor.h - image de-compressor interface
00004  *
00005  *  Created: July 2007 (Sci-Bono, South Africa, B&B)
00006  *  Copyright  2006-2007  Daniel Beck
00007  *             2007       Tim Niemueller [www.niemueller.de]
00008  *
00009  ****************************************************************************/
00010
00011 /*  This program is free software; you can redistribute it and/or modify
00012  *  it under the terms of the GNU General Public License as published by
00013  *  the Free Software Foundation; either version 2 of the License, or
00014  *  (at your option) any later version. A runtime exception applies to
00015  *  this software (see LICENSE.GPL_WRE file mentioned below for details).
00016  *
00017  *  This program is distributed in the hope that it will be useful,
00018  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00019  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020  *  GNU Library General Public License for more details.
00021  *
00022  *  Read the full text in the LICENSE.GPL_WRE file in the doc directory.
00023  */
00024
00025 #include <fvutils/color/conversions.h>
00026 #include <fvutils/compression/jpeg_decompressor.h>
00027
00028 #include <sys/types.h>
00029 #include <cstdio>
00030 #include <cstdlib>
00031
00032 extern "C" {
00033 #include <jpeglib.h>
00034 #include <jerror.h>
00035 }
00036 
00037 ///@cond INTERNALS
00038 
00039 typedef struct {
00040   struct jpeg_source_mgr pub;
00041
00042   JOCTET * buffer;
00043 } my_source_mgr;
00044
00045 typedef my_source_mgr * my_src_ptr;
00046
00047
00048 METHODDEF(void)
00049 init_source (j_decompress_ptr cinfo)
00050 {
00051 }
00052
00053
00054 METHODDEF(boolean)
00055 fill_input_buffer (j_decompress_ptr cinfo)
00056 {
00057   return TRUE;
00058 }
00059
00060 METHODDEF(void)
00061 skip_input_data (j_decompress_ptr cinfo, long num_bytes)
00062 {
00063   my_src_ptr src = (my_src_ptr) cinfo->src;
00064   /* Just a dumb implementation for now.  Could use fseek() except
00065    * it doesn't work on pipes.  Not clear that being smart is worth
00066    * any trouble anyway --- large skips are infrequent.
00067    */
00068   if (num_bytes > 0) {
00069     while (num_bytes > (long) src->pub.bytes_in_buffer) {
00070       num_bytes -= (long) src->pub.bytes_in_buffer;
00071       (void) fill_input_buffer(cinfo);
00072       /* note we assume that fill_input_buffer will never return FALSE,
00073        * so suspension need not be handled.
00074        */
00075     }
00076     src->pub.next_input_byte += (size_t) num_bytes;
00077     src->pub.bytes_in_buffer -= (size_t) num_bytes;
00078   }
00079 }
00080
00081 METHODDEF(void)
00082 term_source (j_decompress_ptr cinfo)
00083 {
00084   /* no work necessary here */
00085 }
00086
00087 GLOBAL(void)
00088 my_mem_src (j_decompress_ptr cinfo, JOCTET * buffer, size_t bytes)
00089 {
00090   my_src_ptr src;
00091
00092  if (cinfo->src == NULL) {      /* first time for this JPEG object? */
00093    cinfo->src = (struct jpeg_source_mgr *)
00094      (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
00095                                  sizeof(my_source_mgr));
00096    src = (my_src_ptr) cinfo->src;
00097 //    src->buffer = (JOCTET *)
00098 //      (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
00099 //                               INPUT_BUF_SIZE * SIZEOF(JOCTET));
00100   }
00101
00102   src = (my_src_ptr) cinfo->src;
00103   src->pub.init_source = init_source;
00104   src->pub.fill_input_buffer = fill_input_buffer;
00105   src->pub.skip_input_data = skip_input_data;
00106   src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
00107   src->pub.term_source = term_source;
00108   src->pub.bytes_in_buffer = bytes;
00109   src->pub.next_input_byte = buffer;
00110 }
00111 
00112 /// @endcond
00113 
00114 /** @class JpegImageDecompressor <fvutils/compression/jpeg_decompressor.h>
00115  * Decompressor for JPEG images.
00116  * @author Daniel Beck
00117  * @author Tim Niemueller
00118  */
00119 
00120 /** Constructor. */
00121 JpegImageDecompressor::JpegImageDecompressor()
00122 {
00123 }
00124
00125 void
00126 JpegImageDecompressor::decompress()
00127 {
00128   JSAMPROW row_pointer[1];
00129   unsigned long location = 0;
00130   unsigned char *buffer;
00131
00132   // JPEG decompression
00133   // Allocate and initialize a JPEG decompression object
00134   struct jpeg_decompress_struct cinfo;
00135   struct jpeg_error_mgr jerr;
00136
00137   cinfo.err = jpeg_std_error(&jerr);
00138   jpeg_create_decompress(&cinfo);
00139
00140   // Specify the source of the compressed data
00141   my_mem_src(&cinfo, _compressed_buffer, _compressed_buffer_size);
00142
00143   // Call jpeg_read_header() to obtain image info
00144   jpeg_read_header(&cinfo, TRUE);
00145
00146   // set output color space
00147   //  cinfo.out_color_space = JCS_YCbCr;
00148
00149   // Set parameters for decompression
00150
00151   // jpeg_start_decompress(...);
00152   jpeg_start_decompress(&cinfo);
00153
00154   buffer = (unsigned char*)malloc( cinfo.output_width * cinfo.output_height * cinfo.num_components );
00155
00156   row_pointer[0] = (unsigned char *)malloc( cinfo.output_width * cinfo.num_components );
00157
00158   // while (scan lines remain to be read)
00159   //   jpeg_read_scanlines(...);
00160   while( cinfo.output_scanline < cinfo.image_height )
00161     {
00162       jpeg_read_scanlines( &cinfo, row_pointer, 1 );
00163       for( unsigned int i=0; i < cinfo.image_width * cinfo.num_components; i++)
00164         buffer[location++] = row_pointer[0][i];
00165     }
00166
00167   // jpeg_finish_decompress(...);
00168   jpeg_finish_decompress(&cinfo);
00169
00170   // Release the JPEG decompression object
00171   jpeg_destroy_decompress(&cinfo);
00172
00173   free(row_pointer[0]);
00174
00175 //   FILE* imagefile = fopen("asdf.ppm", "w");
00176
00177 //   fprintf(imagefile,"P6\n%u %u\n255\n", image_data.width,
00178 //           image_data.height );
00179 //   fwrite(buffer, 1, cinfo.output_width * cinfo.num_components * cinfo.image_width, imagefile);
00180 //   fclose(imagefile);
00181
00182   // convert to yuv422packed and store in member frame_buffer
00183   convert(RGB, YUV422_PLANAR, buffer, _decompressed_buffer, cinfo.output_width, cinfo.output_height);
00184
00185   free(buffer);
00186
00187 }