Homepage Demos Overview Downloads Tutorials Reference
Credits

FilterBankGenerator.h

Go to the documentation of this file.
00001 //-*-c++-*-
00002 #ifndef INCLUDED_FilterBankGenerator_h_
00003 #define INCLUDED_FilterBankGenerator_h_
00004 
00005 #include "Events/EventGeneratorBase.h"
00006 #include "Shared/LoadSave.h"
00007 
00008 //! Abstract base class for generators of FilterBankEvents
00009 /*! This is needed to provide an interface for the FilterBankEvent to
00010  *  call back when the actual image data is requested from it.  This
00011  *  facilitates lazy calculation of image data...  no sense in
00012  *  processing layers or channels which aren't actually going to be
00013  *  used...
00014  *
00015  *  Also this way we save on allocating/deallocating large memory
00016  *  blocks on each event... the buffers allocated here can be reused
00017  *  frame to frame.
00018  *
00019  *  Larger layer indicies generally indicate higher resolution images
00020  *  in a scaling pyramid, but you are free to store your own data
00021  *  however you wish.
00022  *
00023  *  For serializing, FilterBankGenerators inherit from the LoadSave
00024  *  interface.  Only one image (selected with setLoadSaveImage()) of
00025  *  the bank will loaded or saved at a time.  The default LoadSave
00026  *  will store some header information for you:
00027  *  
00028  *  - Creator code: string ("\008FBkImage\0")
00029  *  - Width: unsigned int
00030  *  - Height: unsigned int
00031  *  - Layer: unsigned int
00032  *  - Channel: unsigned int
00033  *  
00034  *  However, you will need to override the LoadSave functions (listed
00035  *  below) to provide your own code for interpreting the image data
00036  *  itself.  You may also want to add a few extra functions to allow
00037  *  users to set compression/data format parameters.
00038  *
00039  *  If you're doing fancy memory stuff, you probably want to override
00040  *  the freeCaches() and destruct() functions so that the default
00041  *  implementation won't try to free something it shouldn't.  Don't
00042  *  forget to call them from your own destructor though, otherwise
00043  *  your versions won't get called before the default implementation's
00044  *  does.
00045  *
00046  *  @see RawCameraGenerator
00047  */
00048 class FilterBankGenerator : public EventGeneratorBase, public LoadSave {
00049 public:
00050   //! constructor, calls setNumImages(1,1)
00051   FilterBankGenerator()
00052     : EventGeneratorBase(), numLayers(0), numChannels(0), widths(NULL), heights(NULL), skips(NULL), strides(NULL), increments(NULL), images(NULL), imageValids(NULL), selectedSaveLayer(0), selectedSaveChannel(0), frameNumber(0), framesProcessed(0)
00053   {
00054     setNumImages(1,1);
00055   }
00056 
00057   //! constructor
00058   FilterBankGenerator(unsigned int layers, unsigned int channels)
00059     : EventGeneratorBase(), numLayers(0), numChannels(0), widths(NULL), heights(NULL), skips(NULL), strides(NULL), increments(NULL), images(NULL), imageValids(NULL), selectedSaveLayer(0), selectedSaveChannel(0), frameNumber(0), framesProcessed(0)
00060   {
00061     setNumImages(layers,channels);
00062   }
00063 
00064   //! constructor
00065   FilterBankGenerator(const std::string& name,unsigned int layers, unsigned int channels, EventBase::EventGeneratorID_t srcgid, unsigned int srcsid, EventBase::EventGeneratorID_t mgid, unsigned int msid)
00066     : EventGeneratorBase(name,mgid,msid,srcgid,srcsid), numLayers(0), numChannels(0), widths(NULL), heights(NULL), skips(NULL), strides(NULL), increments(NULL), images(NULL), imageValids(NULL), selectedSaveLayer(0), selectedSaveChannel(0), frameNumber(0), framesProcessed(0)
00067   {
00068     setNumImages(layers,channels);
00069   }
00070 
00071   //! destructor
00072   ~FilterBankGenerator() {
00073     freeCaches();
00074     destruct();
00075   }
00076 
00077   //! returns the number of image layers (e.g. different resolutions available)
00078   virtual unsigned int getNumLayers() const { return numLayers; }
00079 
00080   //! returns the number of channels per image (e.g. Y, U, or V components)
00081   virtual unsigned int getNumChannels() const { return numChannels; }
00082   
00083   //! returns pointer to the beginning of the image data for the specified layer and channel
00084   /*! this will cause the data to be calculated and cached if it's not already available */
00085   virtual unsigned char * getImage(unsigned int layer, unsigned int channel) const;
00086 
00087   //! returns width (in samples) of the image in a given layer
00088   unsigned int getWidth(unsigned int layer) const { return widths[layer]; }
00089 
00090   //! returns height (in samples) of the image in a given layer
00091   unsigned int getHeight(unsigned int layer) const { return heights[layer]; }
00092   
00093   //! returns the bytes to skip from the one-past-end of a row to get the beginning of the next
00094   unsigned int getSkip(unsigned int layer) const { return skips[layer]; }
00095   
00096   //! returns the bytes to skip from the beginning of one row to get the beginning of the next
00097   /*! This is just for convenience; the stride is just the skip plus the width, but it's precomputed for you for speed and clarity */
00098   unsigned int getStride(unsigned int layer) const { return strides[layer]; }
00099 
00100   //! returns the increment (in bytes) to use to go from one sample to the next
00101   unsigned int getIncrement(unsigned int layer) const { return increments[layer]; }
00102   
00103   //! returns the frame number of the current frame, see #frameNumber
00104   unsigned int getFrameNumber() const { return frameNumber; }
00105   
00106   //! returns the number of frames processed, see #framesProcessed
00107   unsigned int getFramesProcessed() const { return framesProcessed; }
00108   
00109   //! deletes storage of cached images and marks it invalid
00110   /*! you should override this if the images cache pointer isn't actually an array of bytes... 
00111    *  Don't forget to call it in your subclass's destructor or your version won't get called... */
00112   virtual void freeCaches();
00113 
00114   //! marks all of the cached images as invalid (but doesn't free their memory)
00115   /*! You probably want to call this right before you send the FilterBankEvent */
00116   virtual void invalidateCaches();
00117 
00118   //! default implementation ignore events, just so you don't have to define it if you don't receive events
00119   virtual void processEvent(const EventBase & /*event*/) {}
00120   
00121   //!@name LoadSave interface
00122 
00123   virtual unsigned int getBinSize() const;
00124 
00125   virtual unsigned int LoadBuffer(const char buf[], unsigned int len);
00126 
00127   virtual unsigned int SaveBuffer(char buf[], unsigned int len) const;
00128 
00129   //! not actually part of the LoadSave interface, but allows you to select which image of the bank will be saved
00130   /*! when loading, the saved image's layer and channel will reset this */
00131   virtual void selectSaveImage(unsigned int layer, unsigned int channel) { selectedSaveLayer=layer; selectedSaveChannel=channel; }
00132 
00133   virtual unsigned int getSelectedSaveLayer() const { return selectedSaveLayer; } //!< returns layer to be saved, or layer of last image loaded
00134   virtual unsigned int getSelectedSaveChannel() const { return selectedSaveChannel; } //!< returns channel to be saved, or channel of last image loaded
00135 
00136   //@}
00137 
00138 
00139 protected:
00140   //! resizes the filter bank information storage area, you should override this to do your setup and call it from your constructor
00141   /*! In general, it isn't expected that FilterBankGenerator's should
00142    *  necessarily be dynamically resizeable (although it would be
00143    *  nice), which is why this isn't public.  If yours is, just add
00144    *  some pubic accessor functions which call this.  In general, the
00145    *  included subclasses should be able to handle being resized, but
00146    *  there's no reason to do so since the system won't be changing
00147    *  its available resolutions at run time. */
00148   virtual void setNumImages(unsigned int nLayers, unsigned int nChannels);
00149 
00150   //! create new image data storage area for the cache - this is only called when the corresponding entry in images is NULL
00151   /*! You should return the pointer you want stored in images to be
00152    *  returned by any calls to getFirstRow.  Interpretation of the
00153    *  data it points to is dependant on the the generator which
00154    *  creates it */
00155   virtual unsigned char * createImageCache(unsigned int layer, unsigned int channel) const=0;
00156 
00157   //! should calculate new image data, only called when imageValids indicates the image being requested is dirty
00158   /*! This is where you'll want to put your user-specific code for calculating the image data */
00159   virtual void calcImage(unsigned int layer, unsigned int channel) const=0;
00160 
00161   //! deletes the arrays
00162   virtual void destruct();
00163 
00164   unsigned int numLayers;   //!< current number of layers available
00165   unsigned int numChannels; //!< current number of channels available
00166 
00167   unsigned int * widths;    //!< an array of size numLayers, width (in samples) in pixels of each layer
00168   unsigned int * heights;   //!< an array of size numLayers, height (in samples) in pixels of each layer
00169   unsigned int * skips;     //!< an array of size numLayers, skip (in bytes) from row end to next row begin
00170   unsigned int * strides;   //!< an array of size numLayers, stride (in bytes) from a given column in one row to the same column in the next row
00171   unsigned int * increments;//!< an array of size numLayers, increment (in bytes) to use to get from one sample to the next
00172   
00173   mutable unsigned char *** images; //!< an array [numLayers][numChannels], stores pointer to cached image data
00174   mutable bool ** imageValids;      //!< an array [numLayers][numChannels], entry is true if cached data is still valid
00175 
00176   unsigned int selectedSaveLayer;   //!< layer to be manipulated with the LoadSave functions
00177   unsigned int selectedSaveChannel; //!< channel to be manipulated with the LoadSave functions
00178 
00179   //! the current frame number - subclasses will need to set to the source's frameNumber when they receive a new frame (probably from processEvent()) 
00180   /*! The idea is to use this as a unique serial number for each
00181    *  frame.  That way you can know if the current image in different
00182    *  generators is actually the same camera image before you try to
00183    *  compare or combine them.
00184    *
00185    *  You could also figure out the number of dropped frames by
00186    *  subtracting framesProcessed from this value.  Give some leeway
00187    *  however, because it takes the first 40-70 frames just to boot
00188    *  up, so there's no way they can be processed.
00189    */
00190   unsigned int frameNumber; 
00191   unsigned int framesProcessed; //!< subclasses should increment this any time they make a new filter bank available (probably by throwing an event)
00192 
00193 private:
00194   FilterBankGenerator(const FilterBankGenerator& fbk); //!< don't call
00195   const FilterBankGenerator& operator=(const FilterBankGenerator& fbk); //!< don't call
00196 };
00197 
00198 /*! @file
00199  * @brief Describes abstract base class for generators of FilterBankEvents
00200  * @author ejt (Creator)
00201  *
00202  * $Author: ejt $
00203  * $Name: tekkotsu-2_0 $
00204  * $Revision: 1.9 $
00205  * $State: Exp $
00206  * $Date: 2004/01/08 02:22:34 $
00207  */
00208 
00209 #endif

Tekkotsu v2.0
Generated Wed Jan 21 03:20:28 2004 by Doxygen 1.3.4