MgzJEncoder.C

Go to the documentation of this file.
00001 /*!@file Media/MgzJEncoder.C Low-level class to decode mgzj files */
00002 
00003 // //////////////////////////////////////////////////////////////////// //
00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005   //
00005 // by the University of Southern California (USC) and the iLab at USC.  //
00006 // See http://iLab.usc.edu for information about this project.          //
00007 // //////////////////////////////////////////////////////////////////// //
00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00010 // in Visual Environments, and Applications'' by Christof Koch and      //
00011 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00012 // pending; application number 09/912,225 filed July 23, 2001; see      //
00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00014 // //////////////////////////////////////////////////////////////////// //
00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00016 //                                                                      //
00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00018 // redistribute it and/or modify it under the terms of the GNU General  //
00019 // Public License as published by the Free Software Foundation; either  //
00020 // version 2 of the License, or (at your option) any later version.     //
00021 //                                                                      //
00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00025 // PURPOSE.  See the GNU General Public License for more details.       //
00026 //                                                                      //
00027 // You should have received a copy of the GNU General Public License    //
00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00030 // Boston, MA 02111-1307 USA.                                           //
00031 // //////////////////////////////////////////////////////////////////// //
00032 //
00033 // Primary maintainer for this file: Randolph Voorhies <voories at usc dot edu>
00034 
00035 #include "Media/MgzJEncoder.H"
00036 
00037 #include "Image/Image.H"
00038 #include "Image/Pixels.H"
00039 #include "Util/log.H"
00040 #include "Util/sformat.H"
00041 #include "rutz/trace.h"
00042 
00043 #include <zlib.h>
00044 #include <sstream>
00045 
00046 // ######################################################################
00047 MgzJEncoder::MgzJEncoder(const std::string& fname, const int complev)
00048 {
00049   LINFO("Opening File: %s", fname.c_str());
00050   itsFile.open(fname.c_str(), std::ios::out | std::ios::binary);
00051   itsComplev = complev;
00052 }
00053 
00054 // ######################################################################
00055 MgzJEncoder::~MgzJEncoder()
00056 {
00057   this->close();
00058 }
00059 
00060 // ######################################################################
00061 int MgzJEncoder::close()
00062 {
00063   if(itsFile.is_open())
00064   {
00065     LINFO("Please wait... Writing %lu entries to the file journal", (unsigned long)itsJournal.size());
00066     //Get the current position of the put pointer - this will be the start location of the journal
00067     uint64 journal_position = itsFile.tellp();
00068 
00069     //Allocate the memory for our journal. 
00070     //  0: Number of entries     (8 bytes)
00071     //  8: Flags                 (8 bytes)
00072     // 16: JOURNAL               (? bytes)
00073     // ??: Journal Start         (8 bytes)
00074     size_t journal_size = 8 + 8 + itsJournal.size() * sizeof(MgzJEncoder::journalEntry) + 8;
00075     byte journal[journal_size];
00076 
00077     //Copy the number of journal entries to the journal buffer
00078     uint64 num_entries = itsJournal.size();
00079     memcpy(journal, (char*)&num_entries, 8);
00080 
00081     //Copy the format flags to the journal buffer.
00082     //This is just reserved space, in case we need to later add some more meta information,
00083     //such as some versioning of the journal entries, or journal compression, etc...
00084     uint64 flags = 0;
00085     memcpy(journal+8, (char*)&flags, 8);
00086 
00087     //Serialize all of our journal entries and write them to disk
00088     //TODO: Investigate just using a big memcpy or std::copy here, as general
00089     //consensus says that vectors are always contiguous
00090     for(size_t jIdx=0; jIdx<itsJournal.size(); jIdx++)
00091     {
00092 
00093       //Calculate the position of this new journal entry
00094       size_t jPos = 16+jIdx*sizeof(MgzJEncoder::journalEntry);
00095 
00096       //Copy this entry into the journal buffer
00097       memcpy(journal+jPos, (char *)&itsJournal[jIdx], sizeof(MgzJEncoder::journalEntry));
00098     }
00099 
00100     //The last 64 bits of the file will be the file position of the start of the journal
00101     memcpy(journal + 8 + 8 + itsJournal.size() * sizeof(MgzJEncoder::journalEntry), &journal_position, 8);
00102 
00103     //Write the journal to disk
00104     itsFile.write((char*)journal, journal_size);
00105 
00106     itsFile.close();
00107   }
00108   return 1;
00109 }
00110 
00111 // ######################################################################
00112 void MgzJEncoder::writeFrame(const GenericFrame& frame)
00113 {
00114   //Create a journal entry for this new frame
00115   MgzJEncoder::journalEntry entry;
00116   entry.pix_type   = frame.nativeType();
00117   entry.width      = frame.getWidth();
00118   entry.height     = frame.getHeight();
00119 
00120   //Fill in the special fields if necessary
00121   if(frame.nativeType() == GenericFrame::VIDEO)
00122   {
00123     entry.flags     = frame.asVideo().getMode();
00124     entry.byte_swap = frame.asVideo().getByteSwap();
00125   }
00126   else
00127   {
00128     entry.flags      = frame.floatFlags();
00129   }
00130 
00131   int    num_pix           = frame.getWidth() * frame.getHeight();
00132   size_t num_bytes         = -1;
00133   unsigned char* frameBase = NULL;
00134   switch(frame.nativeType())
00135   {
00136     case GenericFrame::GRAY_U8:
00137       num_bytes = sizeof(byte) * num_pix;
00138       frameBase = (unsigned char*)frame.asGrayU8().getArrayPtr();
00139       break;
00140     case GenericFrame::GRAY_U16:
00141       num_bytes = sizeof(uint16) * num_pix;
00142       frameBase = (unsigned char*)frame.asGrayU16().getArrayPtr();
00143       break;
00144     case GenericFrame::GRAY_F32:
00145       num_bytes = sizeof(float) * num_pix;
00146       frameBase = (unsigned char*)frame.asGrayF32().getArrayPtr();
00147       break;
00148     case GenericFrame::RGB_U8:
00149       num_bytes = sizeof(PixRGB<byte>) * num_pix;
00150       frameBase = (unsigned char*)frame.asRgbU8().getArrayPtr();
00151       break;
00152     case GenericFrame::RGB_U16:
00153       num_bytes = sizeof(PixRGB<uint16>) * num_pix;
00154       frameBase = (unsigned char*)frame.asRgbU16().getArrayPtr();
00155       break;
00156     case GenericFrame::RGB_F32:
00157       num_bytes = sizeof(PixRGB<float>) * num_pix;
00158       frameBase = (unsigned char*)frame.asRgbF32().getArrayPtr();
00159       break;
00160     case GenericFrame::VIDEO:
00161       num_bytes = frame.asVideo().getBufSize();
00162       frameBase = (unsigned char*)frame.asVideo().getBuffer();
00163       break;
00164     case GenericFrame::NONE:
00165       //nothing to do here
00166       break;
00167     default:
00168       LFATAL("Cannot write frames of type %s", frame.nativeTypeName().c_str());
00169   }
00170   
00171   //Allocate an output buffer, allowing for some extra space for a header in case
00172   //our input data is totally incompressable
00173   size_t outputBufferSize = num_bytes + 1000;
00174   unsigned char outputBuffer[outputBufferSize];
00175 
00176   //Setup our DEFLATE compression stream
00177   z_stream strm;
00178   strm.zalloc = Z_NULL;
00179   strm.zfree  = Z_NULL;
00180   strm.opaque = Z_NULL;
00181 
00182   int msg = deflateInit(&strm, itsComplev);
00183   if(msg != Z_OK)
00184   { 
00185     std::stringstream reason;
00186     reason << "Could not initialize mgzj encoder (";
00187     switch(msg)
00188     {
00189       case Z_MEM_ERROR:
00190         reason << "Z_MEM_ERROR: Insufficient Memory";
00191         break;
00192       case Z_STREAM_ERROR:
00193         reason << "Z_STREAM_ERROR: Likely an invalid compression level (You chose" << itsComplev << ")";
00194         break;
00195       case Z_VERSION_ERROR:
00196         reason << "Z_VERSION_ERROR: You're using an incompatible version of zlib.h";
00197         break;
00198       default:
00199         reason << "Unknown Error!";
00200         break;
00201     }
00202     reason << ")";
00203     LFATAL("%s", reason.str().c_str()); 
00204   }
00205 
00206   //Setup the input and output buffers
00207   strm.avail_in  = num_bytes;
00208   strm.next_in   = frameBase;
00209   strm.avail_out = outputBufferSize;
00210   strm.next_out  = outputBuffer;
00211 
00212   //Perform the actual decompression and just die on any errors
00213   msg = deflate(&strm, Z_FINISH);
00214   (void)deflateEnd(&strm);
00215   if(msg != Z_STREAM_END)
00216   { 
00217     std::stringstream reason;
00218     reason << "Failure to deflate (";
00219     switch(msg)
00220     {
00221       case Z_OK:
00222         reason << "Z_OK";
00223         break;
00224       case Z_STREAM_ERROR:
00225         reason << "Z_STREAM_ERROR";
00226         break;
00227       case Z_BUF_ERROR:
00228         reason << "Z_BUF_ERROR";
00229         break;
00230       default:
00231         reason << "Unknown Error!";
00232         break;
00233     }
00234     reason << ")";
00235     LFATAL("%s", reason.str().c_str()); 
00236   }
00237   size_t compressedSize = outputBufferSize - strm.avail_out;
00238 
00239   //Fill in the rest of the journal entry for this frame, and push it onto the
00240   //journal
00241   entry.start_byte = itsFile.tellp();
00242   entry.end_byte   = entry.start_byte + compressedSize;
00243   itsJournal.push_back(entry);
00244 
00245   //Write the compressed frame to disk
00246   itsFile.write((const char*)outputBuffer, compressedSize);
00247 }
00248 
00249 
00250 
Generated on Sun May 8 08:05:20 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3