core/vil/vil_border.h
Go to the documentation of this file.
00001 // This is core/vil/vil_border.h
00002 #ifndef vil_border_h_
00003 #define vil_border_h_
00004 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00005 #pragma interface
00006 #endif
00007 //:
00008 // \file
00009 // \brief Border handling for images.
00010 // \author Nicolas Burrus - Paris
00011 
00012 #include <vcl_cassert.h>
00013 // not used? #include <vcl_limits.h>
00014 
00015 //: Vil border modes.
00016 enum vil_border_mode
00017 {
00018   //: Border pixels are constant
00019   vil_border_constant = 0,
00020 
00021   //: Border pixels take the value of the closest image point.
00022   // This ensures object continuity.
00023   // ex: im(im.ni()+2, -1) == im(im.ni()-1, 0)
00024   vil_border_geodesic = 1,
00025 
00026   //: Border pixels take the value of the image point which is its symmetric w.r.t. the closest image edge.
00027   // ex: im(im.ni()+3, 0) = im(im.ni()-4, 0)
00028   vil_border_reflect = 2,
00029 
00030   //: The image is seen as periodic, after the right (respectively bottom) edge comes the left (respectively top).
00031   // ex: im(im.ni()+2,0) == im(2,0)
00032   // ex: im(im.ni()+3, im.nj()+2) == im(3,2)
00033   vil_border_periodic = 3,
00034 };
00035 
00036 //: Border class.  Makes pixel access outside image range transparent and configurable.
00037 // Note that a border is not assigned to a specific image, but only holds border properties.
00038 template <class imT>
00039 class vil_border
00040 {
00041  public:
00042   typedef typename imT::pixel_type pixel_type;
00043 
00044  public:
00045   //: Default constructor, creates a constant border.
00046   vil_border ()
00047   : border_kind_(vil_border_constant)
00048   , constant_value_()
00049   {}
00050 
00051   //: Set the border kind.
00052   void set_kind (vil_border_mode brdr_kind) { border_kind_ = brdr_kind; }
00053   //: Get the current border kind.
00054   vil_border_mode kind() const { return border_kind_; }
00055 
00056   //: True if border values are constant.
00057   inline bool is_constant() const
00058   { return border_kind_ == vil_border_constant; }
00059 
00060   //: If border kind is vil_border_constant, returns the border value.
00061   inline const pixel_type& constant_value() const { return constant_value_; }
00062 
00063   //: Set the border value if the border kind is vil_border_constant.
00064   void set_constant_value (const pixel_type& val) { constant_value_ = val; }
00065 
00066   //: Return read-only reference to pixel at (i,j,p) on the given image.
00067   // If the pixel falls out of the image range, the border value is returned.
00068   inline const pixel_type&
00069   operator()(const imT& im, int i, int j, int p = 0) const
00070   {
00071     if (im.in_range(i,j,p))
00072       return im(i,j,p);
00073 
00074     return in_border(im, i, j, p);
00075   }
00076 
00077  protected:
00078   inline const pixel_type&
00079   in_border(const imT& im, int i, int j, int p = 0) const
00080   {
00081     switch (border_kind_)
00082     {
00083     case vil_border_constant:
00084       return constant_value_;
00085     case vil_border_geodesic:
00086       if (i < 0) i = 0; else if (i >= (int)im.ni()) i = im.ni()-1;
00087       if (j < 0) j = 0; else if (j >= (int)im.nj()) j = im.nj()-1;
00088       if (p < 0) p = 0; else if (p >= (int)im.nplanes()) p = im.nplanes()-1;
00089       return im(i,j,p);
00090     case vil_border_reflect:
00091       if (i < 0) i = -i-1; else if (i >= (int)im.ni()) i = 2*im.ni()-i-1;
00092       if (j < 0) j = -j-1; else if (j >= (int)im.nj()) j = 2*im.nj()-j-1;
00093       if (p < 0) p = -p-1; else if (p >= (int)im.nplanes()) p = 2*im.nplanes()-p-1;
00094       return im(i,j,p);
00095     case vil_border_periodic:
00096       if (i < 0) i = im.ni()-((-i)%im.ni());
00097       else i = i%im.ni();
00098 
00099       if (j < 0) j = im.nj()-((-j)%im.nj());
00100       else j = j%im.nj();
00101 
00102       if (p < 0) p = im.nplanes()-((-p)%im.nplanes());
00103       else p = p%im.nplanes();
00104 
00105       return im(i,j,p);
00106     default:
00107       assert(false);
00108       return constant_value_; // To avoid warnings
00109     };
00110   }
00111 
00112  private:
00113   vil_border_mode border_kind_;
00114   pixel_type constant_value_;
00115 };
00116 
00117 //: Provides a pixel accessor which is syntax-compatible with vil_image_view.
00118 // It acts like a proxy to the underlying image,
00119 // transparently providing border pixel values if required.
00120 template <class imT>
00121 class vil_border_accessor
00122 {
00123  public:
00124   typedef typename imT::pixel_type pixel_type;
00125 
00126  public:
00127   //: Constructor.
00128   vil_border_accessor(const imT& img, const vil_border<imT>& brdr)
00129   : im(img), border(brdr)
00130   {}
00131 
00132   //: Returns a const reference on the pixel (i,j,p).
00133   // If the pixel falls out of the image range, a border value is returned.
00134   inline const pixel_type&
00135   operator()(int i, int j, int p = 0) const
00136   { return border(im, i, j, p); }
00137 
00138  private:
00139   const imT& im;
00140   vil_border<imT> border;
00141 };
00142 
00143 //: Instantiates a border accessor, provided for convenience.
00144 template <class imT>
00145 vil_border_accessor<imT>
00146 vil_border_create_accessor(const imT& im, const vil_border<imT>& border)
00147 {
00148   return vil_border_accessor<imT>(im, border);
00149 }
00150 
00151 //: Instantiate a constant border whose type is derived from imT.
00152 template <class imT>
00153 inline vil_border<imT>
00154 vil_border_create_constant(const imT&, typename imT::pixel_type constant_val = 0)
00155 {
00156   vil_border<imT> border;
00157   border.set_kind(vil_border_constant);
00158   border.set_constant_value(constant_val);
00159   return border;
00160 }
00161 
00162 //: Instantiate a geodesic border whose type is derived from imT.
00163 template <class imT>
00164 inline vil_border<imT>
00165 vil_border_create_geodesic(const imT&)
00166 {
00167   vil_border<imT> border;
00168   border.set_kind(vil_border_geodesic);
00169   return border;
00170 }
00171 
00172 //: Instantiate a reflect border whose type is derived from imT.
00173 template <class imT>
00174 inline vil_border<imT>
00175 vil_border_create_reflect(const imT&)
00176 {
00177   vil_border<imT> border;
00178   border.set_kind(vil_border_reflect);
00179   return border;
00180 }
00181 
00182 //: Instantiate a reflect border whose type is derived from imT.
00183 template <class imT>
00184 inline vil_border<imT>
00185 vil_border_create_periodic(const imT&)
00186 {
00187   vil_border<imT> border;
00188   border.set_kind(vil_border_periodic);
00189   return border;
00190 }
00191 
00192 #endif // vil_border_h_