IceImageCompressor.C

00001 #ifndef ICEIMAGECOMPRESSION_C
00002 #define ICEIMAGECOMPRESSION_C
00003 
00004 #include "Ice/IceImageCompressor.H"
00005 #include <vector>
00006 
00007 //The output buffer size... I believe this should be as large as possible
00008 //so that empty_output_buffer will never need to be called as an intermediary
00009 //step, and we can just rely on term_destination to write all of our data
00010 #define OUTPUT_BUF_SIZE  100000
00011 
00012 namespace IIC_NS
00013 {
00014   typedef struct {
00015     //The public fields common to destination managers
00016     struct jpeg_destination_mgr pub;
00017 
00018     //The input buffer pointer
00019     JOCTET* in_buffer;
00020 
00021     //The destination queue of
00022     std::vector<unsigned char>* out_buffer;
00023 
00024   } buff_dest_mgr;
00025 
00026   ////////////////////////////////////////////////////////////////
00027   // Initialize destination --- called by jpeg_start_compress
00028   // before any data is actually written.
00029   ////////////////////////////////////////////////////////////////
00030   METHODDEF(void) init_destination(j_compress_ptr cinfo)
00031   {
00032     //Get the pointer to our cinfo's destination manager
00033     buff_dest_mgr* dest = (buff_dest_mgr*) cinfo->dest;
00034 
00035     //Allocate the input buffer --- it will be released when done with image
00036     dest->in_buffer = (JOCTET *)
00037       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
00038           OUTPUT_BUF_SIZE * sizeof(JOCTET));
00039 
00040     //Reset the input buffer
00041     dest->pub.next_output_byte = dest->in_buffer;
00042     dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
00043   }
00044 
00045   ////////////////////////////////////////////////////////////////
00046   // Empty the output buffer --- called whenever buffer fills up.
00047   ////////////////////////////////////////////////////////////////
00048   METHODDEF(boolean) empty_output_buffer (j_compress_ptr cinfo)
00049   {
00050     //Get the pointer to our cinfo's destination manager
00051     buff_dest_mgr* dest = (buff_dest_mgr*) cinfo->dest;
00052 
00053     //Copy the rest of the input buffer onto the end of our output buffer
00054     dest->out_buffer->insert(dest->out_buffer->end(),
00055         dest->in_buffer,
00056         dest->in_buffer+OUTPUT_BUF_SIZE);
00057 
00058     //Reset the input buffer
00059     dest->pub.next_output_byte = dest->in_buffer;
00060     dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
00061 
00062     return TRUE;
00063   }
00064 
00065   ////////////////////////////////////////////////////////////////
00066   // Terminate destination --- called by jpeg_finish_compress
00067   // after all data has been written.  Usually needs to flush buffer.
00068   ////////////////////////////////////////////////////////////////
00069   METHODDEF(void) term_destination (j_compress_ptr cinfo)
00070   {
00071     //Get the pointer to our cinfo's destination manager
00072     buff_dest_mgr* dest = (buff_dest_mgr*) cinfo->dest;
00073 
00074     //Calculate the number of bytes left to be written
00075     size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
00076 
00077     //Copy the rest of the input buffer onto the end of our output buffer
00078     dest->out_buffer->insert(dest->out_buffer->end(),
00079         dest->in_buffer,
00080         dest->in_buffer+datacount);
00081   }
00082 }
00083 
00084 
00085 IceImageCompressor::IceImageCompressor()
00086 {
00087   //Initialize our jpeg error handler to the default
00088   //(spit out non-fatal error messages on cerr, and
00089   // exit() on fatal errors)
00090   cinfo.err = jpeg_std_error(&jerr);
00091 
00092   //Create our jpeg compression object
00093   jpeg_create_compress(&cinfo);
00094 }
00095 
00096 std::vector<unsigned char> IceImageCompressor::CompressImage(Image<PixRGB<byte> > input)
00097 {
00098   std::vector<unsigned char> jpeg_buffer;
00099 
00100   //Initialize our data destination
00101   InitImageIceDest(&jpeg_buffer);
00102 
00103   //Set our image and compression parameters
00104   cinfo.image_width   = input.getWidth();
00105   cinfo.image_height  = input.getHeight();
00106   cinfo.input_components = 3;
00107   cinfo.in_color_space = JCS_RGB;
00108   jpeg_set_defaults(&cinfo);
00109 
00110   //Begin the compression
00111   jpeg_start_compress(&cinfo, TRUE);
00112 
00113   //Get a pointer to the start of the image's raw data array. This assumes that
00114   //all of the image data is layed out as R G B R G B, with each element as a
00115   //byte in contiguous memory. This should be a valid assumption for any
00116   //Image<PixRGB<byte> >
00117   JSAMPLE* p_start = reinterpret_cast<JSAMPLE*>(input.getArrayPtr());
00118 
00119   //Pass a pointer to each row of the image to the jpeg compressor.  It would
00120   //be nice to do this all in one shot, but libjpeg segfaults when I try.
00121   for(int row_idx=0; row_idx<input.getHeight(); row_idx++)
00122   {
00123     JSAMPLE* p = (p_start + (row_idx * input.getWidth()*3) );
00124     jpeg_write_scanlines(&cinfo, &p, 1);
00125   }
00126 
00127   //Clean up the compression, and finish writing all bytes to the output buffer
00128   jpeg_finish_compress(&cinfo);
00129 
00130   return jpeg_buffer;
00131 }
00132 
00133 
00134 void IceImageCompressor::InitImageIceDest(std::vector<unsigned char>* output_buffer)
00135 {
00136   IIC_NS::buff_dest_mgr* dest;
00137 
00138   if(cinfo.dest == NULL)
00139   {
00140     //Allocate some memory space for our destination manager.
00141     cinfo.dest = (struct jpeg_destination_mgr *)
00142       (*(cinfo.mem->alloc_small)) ((j_common_ptr) &cinfo, JPOOL_PERMANENT, sizeof(IIC_NS::buff_dest_mgr));
00143   }
00144 
00145   //Initialize our destination manager by filling in all of the appropriate
00146   //function pointers, and assigning the output buffer.
00147   dest = (IIC_NS::buff_dest_mgr*) cinfo.dest;
00148   dest->pub.init_destination    = IIC_NS::init_destination;
00149   dest->pub.empty_output_buffer = IIC_NS::empty_output_buffer;
00150   dest->pub.term_destination    = IIC_NS::term_destination;
00151   dest->out_buffer              = output_buffer;
00152 }
00153 
00154 #endif
00155 
Generated on Sun May 8 08:40:44 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3