contrib/tbl/vipl/filter/vipl_filter.h
Go to the documentation of this file.
00001 // This is tbl/vipl/filter/vipl_filter.h
00002 #ifndef vipl_filter_h_
00003 #define vipl_filter_h_
00004 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00005 #pragma interface
00006 #endif
00007 //:
00008 // \file
00009 // Here is how the get/set macros are used.
00010 // First note there are 4 types of access:
00011 // for each of get and set we can do it with or without bounds/cache checking.
00012 // These are respectively defined in 4 macros:
00013 // GET_PIXEL SET_PIXEL FGET_PIXEL FSET_PIXEL (fast get...)
00014 // Arguments for GET_PIXEL and FGET_PIXEL are (x,y)  (i.e. column,row) and they return the value.
00015 // For SET_PIXEL FSET_PIXEL, the syntax is SET_PIXEL(x,y,value).
00016 // Note that SET_PIXEL is expected to return value!
00017 // We support operator() being the access, or if the used defines USE_NAMED_ACCESSORS, the named accessors.
00018 // For the named accessors the user can #define the names to use.
00019 // (And if they really want to, they can change the #defines for GET_PIXEL SET_PIXEL...
00020 //  but be careful as existing code uses the args in the given order.)
00021 
00022 #include "vipl_filter_abs.h"
00023 #include <vipl/filter/vipl_trivial_pixeliter.h>
00024 
00025 template < class ImgIn, class ImgOut, class DataIn, class DataOut, int Arity, class PixelItr = vipl_trivial_pixeliter >
00026  class vipl_filter ;
00027 
00028 #include <vipl/section/vipl_section_descriptor.h>
00029 #include <vipl/section/vipl_section_container.h>
00030 
00031 #include <vcl_stlfwd.h> // forward declaration for vcl_vector
00032 
00033 #ifdef USE_NAMED_ACCESSORS // cannot have both set,
00034 #undef USE_OPERATOR_ACCESSORS // to be safe if we have named we undefine operator()
00035 #else
00036 #ifndef USE_OPERATOR_ACCESSORS // if neither is set
00037 #define USE_NAMED_ACCESSORS    // use names by default
00038 #endif
00039 #endif
00040 
00041 #ifndef GET_NAME
00042 #define GET_NAME get_pixel
00043 #endif
00044 #ifndef SET_NAME
00045 #define SET_NAME set_pixel
00046 #endif
00047 #ifndef FGET_NAME
00048 #define FGET_NAME fget_pixel
00049 #endif
00050 #ifndef FSET_NAME
00051 #define FSET_NAME fset_pixel
00052 #endif
00053 #ifdef USE_OPERATOR_ACCESSORS
00054 // if not we use operator accessors
00055 #ifndef GET_PIXEL
00056 #define GET_PIXEL(img,x,y)  (img)(x,y)
00057 #endif
00058 #ifndef SET_PIXEL
00059 #define SET_PIXEL(img,x,y,expr)  (img)(x,y) = expr
00060 #endif
00061 #ifndef FGET_PIXEL
00062 #define FGET_PIXEL(img,x,y)  (img)(x,y)
00063 #endif
00064 #ifndef FSET_PIXEL
00065 #define FSET_PIXEL(img,x,y,expr)  (img)(x,y) = expr
00066 #endif
00067 #else // USE_NAMED_ACCESSORS
00068 #ifndef GET_PIXEL
00069 #define GET_PIXEL(img,x,y)  (img). GET_NAME (x,y)
00070 #endif
00071 #ifndef SET_PIXEL
00072 #define SET_PIXEL(img,x,y,expr)  (img). SET_NAME (expr, x,y)
00073 #endif
00074 #ifndef FGET_PIXEL
00075 #define FGET_PIXEL(img,x,y)  (img). FGET_NAME (x,y)
00076 #endif
00077 #ifndef FSET_PIXEL
00078 #define FSET_PIXEL(img,x,y,expr)  (img). FSET_NAME (expr, x,y)
00079 #endif
00080 #endif // end use NAMED ACCESSORS
00081 
00082 #ifndef CONVERT_TO_OUT
00083 #define CONVERT_TO_OUT(v) ((DataOut) (v))
00084 #endif
00085 // the include file below defines the type VIPL_FILTER_STATE
00086 #include "vipl_filter_helper.h" // for adding members by macros....
00087 
00088 class vipl_trivial_pixeliter;
00089 extern const void * DAhelp(vipl_trivial_pixeliter const*,int level=0);
00090 
00091 template < class ImgIn, class ImgOut, class DataIn, class DataOut, int Arity, class PixelItr >
00092 class vipl_filter          : public vipl_filter_abs
00093 {
00094   // declare some static consts....
00095   static const VIPL_FILTER_STATE Not_Ready      VCL_STATIC_CONST_INIT_INT_DECL(0);
00096   static const VIPL_FILTER_STATE Ready          VCL_STATIC_CONST_INIT_INT_DECL(1);
00097   static const VIPL_FILTER_STATE Unchanged      VCL_STATIC_CONST_INIT_INT_DECL(2);
00098   static const VIPL_FILTER_STATE Filter_Owned   VCL_STATIC_CONST_INIT_INT_DECL(4);
00099   // typedef iterators from our "iterator" class
00100 
00101  public: typedef typename PixelItr::Titerator Titerator;
00102  public: typedef typename PixelItr::Yiterator Yiterator;
00103  public: typedef typename PixelItr::Xiterator Xiterator;
00104  public: typedef typename PixelItr::Ziterator Ziterator;
00105  public: typedef vipl_filter_abs parent;
00106  public: typedef ImgIn const* inimagept; // make it easy to use.
00107  public: typedef ImgOut* outimagept; // make it easy to use.
00108  public: typedef vipl_filter thisclass; // needed for macro use
00109 
00110   //declare variable to hold "border" size for images.
00111   // May change to array in future (with argless accessor defaulting to largest)
00112  private: int hsimage_border_size;
00113  public: int image_border_size() const { return hsimage_border_size; }
00114  public: int & ref_image_border_size() { return hsimage_border_size; }
00115   // when too close to border what should we use as "fill" value.  It's up to
00116   // the filter implementer to "use" this value in their implementation so it
00117   // might get ignored...
00118  private: DataOut hsdef_fill_value;
00119  public: DataOut def_fill_value() const { return hsdef_fill_value; }
00120  public: DataOut & ref_def_fill_value() { return hsdef_fill_value; }
00121   // we track "state" for input, output and overall filter using these
00122   // ints. g++ had problems with nested enums as types outside of class
00123  private: VIPL_FILTER_STATE  hsinput_state;
00124  public: VIPL_FILTER_STATE input_state() const { return hsinput_state; }
00125  public: VIPL_FILTER_STATE & ref_input_state() { return hsinput_state; }
00126  private: VIPL_FILTER_STATE  hsfilter_state;
00127  public: VIPL_FILTER_STATE filter_state() const { return hsfilter_state; }
00128  public: VIPL_FILTER_STATE & ref_filter_state() { return hsfilter_state; }
00129  private: VIPL_FILTER_STATE  hsoutput_state;
00130  public: VIPL_FILTER_STATE output_state() const { return hsoutput_state; }
00131  public: VIPL_FILTER_STATE & ref_output_state() { return hsoutput_state; }
00132  public: void put_output_state(VIPL_FILTER_STATE const t) { hsoutput_state = t; }
00133   // how many input images are there.
00134  private: int hsnuminputs;
00135  public: int numinputs() const { return hsnuminputs; }
00136  public: int & ref_numinputs() { return hsnuminputs; }
00137   // how many output images are there. currently only 1 is allowed but this will change...
00138  private: int hsnumoutputs;
00139  public: int numoutputs() const { return hsnumoutputs; }
00140  public: int & ref_numoutputs() { return hsnumoutputs; }
00141   // raw "C" like array of pointers to input images
00142  private: vcl_vector<inimagept> hsinf;
00143  public: vcl_vector<inimagept> inf() const { return hsinf; }
00144  public: vcl_vector<inimagept> & ref_inf() { return hsinf; }
00145   // should be raw "C" like array of pointers to output images but
00146   // right now it is a direct pointer to the output image
00147  private: outimagept hsoutf;
00148  public: outimagept outf() const { return hsoutf; }
00149  public: outimagept & ref_outf() { return hsoutf; }
00150  public: void put_outf(outimagept const& t) { hsoutf = t; }
00151   // input section container.  Macros cannot handle commas so use typedef.
00152   // Assume one container works for all input images (implies multi-image filters cannot be ptr-safe.. FIXME)
00153   typedef vipl_section_container< DataIn >* in_section_type;
00154  private:   in_section_type hssrc_section;
00155  public: in_section_type src_section() const { return hssrc_section; }
00156  public: in_section_type & ref_src_section() { return hssrc_section; }
00157   // section descriptor for "current" input section
00158   typedef vipl_section_descriptor< DataIn >* in_descriptor_type;
00159  private:  in_descriptor_type hsinsecp;
00160  public: in_descriptor_type insecp() const { return hsinsecp; }
00161  public: in_descriptor_type & ref_insecp() { return hsinsecp; }
00162  public: void put_insecp(in_descriptor_type const t) { hsinsecp = t; }
00163   // output section container.  Macros cannot handle commas so use typedef
00164   typedef vipl_section_container< DataOut >* out_section_type;
00165  private:  out_section_type hsdst_section;
00166  public: out_section_type dst_section() const { return hsdst_section; }
00167  public: out_section_type & ref_dst_section() { return hsdst_section; }
00168   // section descriptor for "current" output section
00169   typedef vipl_section_descriptor< DataOut>* out_descriptor_type;
00170  private:  out_descriptor_type hssecp;
00171  public: out_descriptor_type secp() const { return hssecp; }
00172  public: out_descriptor_type & ref_secp() { return hssecp; }
00173  public: void put_secp(out_descriptor_type t) { hssecp = t; }
00174   // section descriptor for input ROA
00175   typedef vipl_section_descriptor< DataIn >* in_ROA_descriptor_type;
00176  private:  in_ROA_descriptor_type hsinROA;
00177  public: in_ROA_descriptor_type inROA() const { return hsinROA; }
00178  public: in_ROA_descriptor_type & ref_inROA() { return hsinROA; }
00179   // section descriptor for output ROA
00180   typedef vipl_section_descriptor< DataOut >* out_ROA_descriptor_type;
00181  private:  out_ROA_descriptor_type hsROA;
00182  public: out_descriptor_type ROA() const { return hsROA; }
00183  public: out_descriptor_type & ref_ROA() { return hsROA; }
00184   // if false (default) the ROA is taken from output image
00185   // if true, it is taken from the input image.
00186  private:  bool hsis_input_driven;
00187  public: bool is_input_driven() const { return hsis_input_driven; }
00188  public: bool & ref_is_input_driven() { return hsis_input_driven; }
00189  public: void put_is_input_driven(bool b=true) { hsis_input_driven=b; }
00190 
00191  public:
00192   //:
00193   // A workhorse constructor for this abstract class. If dst_image
00194   // (by default) the output will be generated automatically when
00195   // filtering is about to proceed. (Either way, the filter
00196   // increments refcount when set and decrements the refcount of
00197   // the output when it is destroyed.) Some filters support
00198   // multiple inputs, if ninputs is >1 then this constructor expects
00199   // src_img to be the first element pointer to the input
00200   // (i.e. src_img+1 is the location of input image2). Note that
00201   // the filter keeps pointers to the input (properly refcounted).
00202   vipl_filter(ImgIn const* src_img,
00203               ImgOut* dst_img=0,
00204               int ninputs=1,
00205               int img_border=0 ,
00206               DataOut fill_val=0 ) ;
00207   //:
00208   // A second workhorse constructor for this abstract class. If
00209   // dst_img is null (by default), the output will be generated
00210   // automatically when filtering is about to proceed. The filter
00211   // decrements the refcount of the output when it is
00212   // destroyed. Some filters support multiple inputs, if ninputs is
00213   // >1 then this constructor uses non_consecutive input images (with
00214   // their address in a c_vector, i.e. *(src_img+1) is the location
00215   // of input image2). Note that the filter keeps pointers to the
00216   // input (properly refcounted).
00217   vipl_filter(ImgIn const** src_img,
00218               ImgOut* dst_img=0,
00219               int ninputs=1,
00220               int img_border=0 ,
00221               DataOut fill_val=0 );
00222   virtual ~vipl_filter();
00223   vipl_filter();
00224   vipl_filter(vipl_filter< ImgIn, ImgOut, DataIn, DataOut, Arity, PixelItr > const&);
00225 
00226   // begin method list for class filter
00227 
00228   //:
00229   // The main operation of the class, filters input images to
00230   // produce output image.
00231   // Before this function can run to completion, all arguments must
00232   // be set via the respective ``put_*'' functions (or
00233   // be supplied at construction time). Particularly important is
00234   // the filter input. The programmer should take a look at the
00235   // concrete child classes of filter to see what additional
00236   // parameters they need before the actual filter operation can
00237   // proceed.
00238   virtual bool filter();
00239 
00240   //:
00241   // For those filters that only need one input and output set (after
00242   // construction), the following function allows one to treat the filter
00243   // object more like a function calling
00244   // obj.process(inimg, outimg)
00245   // will set the input and output then call filter()
00246   // It does not require pointers but takes the address of its
00247   // inputs, set the fields in the filter
00248   // does the filter and un-sets the in/out fields in the filter.
00249   bool process(ImgIn const& inimg, ImgOut& outimg);
00250   // second form passing pointers...
00251   bool process(ImgIn const* inimg, ImgOut* outimg);
00252 
00253   //: The ``start'' coordinate for the current apply section.
00254   // This always leaves a border around the
00255   // section. (E.g. if there is no ROA this is actual section start
00256   // + image_boarder_size; remember section iteration overlaps). If
00257   // the current section is outside the ROA, the section_start and
00258   // section_end may be equal.
00259   int start(int axis) const;
00260   int start(int axis, int other_axis_value) const;
00261 
00262   //: The ``stopping'' coordinate for the current apply section.
00263   // This always leaves a border around the
00264   // section. (E.g. if there is no ROA this is actual section end -
00265   // image_boarder_size; remember section iteration overlaps). If
00266   // the current section is outside the ROA, the section_start and
00267   // section_end may be equal.
00268   int stop(int axis) const;
00269   int stop(int axis, int other_axis_value) const;
00270 
00271   //: The ``start'' coordinate for the current source apply section.
00272   // This always leaves a border around the
00273   // section. (E.g. if there is no ROA this is actual section start
00274   // + image_boarder_size; remember section iteration overlaps). If
00275   // the current section is outside the ROA, the section_start and
00276   // section_end may be equal.
00277   int start_src(int axis) const;
00278 
00279   //: The ``stopping'' coordinate for the current source apply section.
00280   // This always leaves a border around the
00281   // section. (E.g. if there is no ROA this is actual section end -
00282   // image_boarder_size; remember section iteration overlaps). If
00283   // the current section is outside the ROA, the section_start and
00284   // section_end may be equal.
00285   int stop_src(int axis) const;
00286 
00287   //: The ``start'' coordinate for the current destination apply section.
00288   // This always leaves a border around the
00289   // section. (E.g. if there is no ROA this is actual section start
00290   // + image_boarder_size; remember section iteration overlaps). If
00291   // the current section is outside the ROA, the section_start and
00292   // section_end may be equal.
00293   int start_dst(int axis) const;
00294 
00295   //: The ``stopping'' coordinate for the current destination apply section.
00296   // This always leaves a border around the
00297   // section. (E.g. if there is no ROA this is actual section end -
00298   // image_boarder_size; remember section iteration overlaps). If
00299   // the current section is outside the ROA, the section_start and
00300   // section_end may be equal.
00301   int stop_dst(int axis) const;
00302 
00303 
00304   //:
00305   // Put the given pointer into an input "image" at the provided
00306   // index. Decrements old objects refcount, increments
00307   // newobjects refcount
00308   bool put_in_data_ptr(ImgIn const* fpointer, int index=0);
00309 
00310   //:
00311   // Return a smart pointer to the input ``image'' at the
00312   // provided index. Increments refcount before returning
00313   inimagept in_data_ptr( int index=0);
00314 
00315   //:
00316   // Return a ref to the input ``data object'' at the provided
00317   // index (dereferences the internal pointer).
00318   const ImgIn& in_data( int index=0) const ;
00319 
00320   //:
00321   // Put the given pointer into output data at the given index
00322   // location Decrements old putput refcount, Inc's newobjects
00323   // refcount
00324   bool put_out_data_ptr(ImgOut* fpointer, int /*index*/=0);
00325 
00326   //:
00327   // Get ptr to specified output data item given index
00328   // location. Inc's refcount before returning ptr
00329   virtual outimagept out_data_ptr(int index=0);
00330 
00331   //:
00332   // Get ref to specified output data item given index location
00333   virtual ImgOut& out_data(int index=0) const;
00334 
00335  protected:
00336 
00337   //:
00338   // This is the function that gets called for every iteration of
00339   // the filtering operation, before the actual filtering
00340   // routine. Can be used for normalization or such. Default op is
00341   // noop
00342   virtual bool preop();
00343 
00344   //:
00345   // This is the function that gets called after every iteration of
00346   // the actual filtering routine. Can be used for post_processing
00347   // normalization or cleaning up the edges. Default op is noop
00348   virtual bool postop();
00349 
00350   //:
00351   // This is the method that implements the basic form for the
00352   // filtering operation.
00353   virtual bool applyop() = 0;
00354 
00355   //:
00356   // For each section, this method runs before
00357   // section_applyop. Default at this level is no_op. (lower level
00358   // class redefines it to ``fill'' the image borders).
00359   virtual bool section_preop();
00360 
00361   //:
00362   // For each section, this method runs after
00363   // section_applyop. Default is no_op
00364   virtual bool section_postop();
00365 
00366   //:
00367   // This is the method that implements the filtering inside each
00368   // section. You must supply this function.
00369   // pure virtual function
00370   virtual bool section_applyop() = 0;
00371 
00372   //:
00373   // If a section is pointer safe, then this function is called to
00374   // filter it. default is just to call section_applyop
00375   virtual bool ptr_based_section_applyop();
00376 
00377   //:
00378   // Called by filter(). checks for input/output
00379   // being set.  User can make it check for additional
00380   // parameters required before the filtering operation can
00381   // proceed.  Allows filter to "proceed" on warnings so not public
00382   virtual bool check_params_1(bool& proceed_on_warn) const ;
00383 
00384  public:
00385 
00386   //:
00387   // returns if the filter is "ready" to run, i.e. all needed
00388   // parameters are "set".  Default just calls check_parms_1()
00389   virtual bool is_ready() const;
00390 
00391   //:
00392   // Is the current apply section intersected with the ROA an empty
00393   // region, if so we should not load it. If it's empty there is no
00394   // guarantee that the section_start and section_end will not overlap.
00395   int is_section_within_ROA( int axis) const;
00396 
00397 #ifdef USE_COMPOSE_WITH
00398   //:
00399   // Try to set the output of this filter to be the input of
00400   // ``to'', and if possible make the filtering more efficient than
00401   // just sequential calls. Currently unimplemented so far this
00402   // function does nothing. Arg should be a nonconst ref because
00403   // composition may change the filter!.
00404   bool compose_with( vipl_filter_abs& to);
00405 #endif
00406 
00407 }; // end of class definition
00408 
00409 #ifdef INSTANTIATE_TEMPLATES
00410 #include "vipl_filter.txx"
00411 #endif
00412 
00413 #endif // file guard