core/vil/vil_convert.h

Go to the documentation of this file.
00001 // This is core/vil/vil_convert.h
00002 #ifndef vil_convert_h_
00003 #define vil_convert_h_
00004 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00005 #pragma interface
00006 #endif
00007 //:
00008 // \file
00009 // \brief Some standard conversion functions.
00010 // \author Ian Scott.
00011 //
00012 // This file contains a large number of image to image conversion
00013 // functions.
00014 // They are in two basic function types (plus a few helper functions.)
00015 // Some involve only explicit types and convert
00016 // a vil_image_view<T> to a vil_image_view<T>,
00017 // the others take an unknown pixel type, using a
00018 // vil_image_view_base_sptr. The basic conversion
00019 // operations (e.g. casting, rounding) are available in both types.
00020 // All of the conversions attempt to find shortcuts, so the output
00021 // may be a reconfigured, or shallow copy of the input.
00022 //
00023 // \par vil_convert with explicit pixel types
00024 // These are useful when you have two vil_image_view objects you want
00025 // to convert between. You can use them in templates where the pixel
00026 // type is one of the template parameters. These functions
00027 // may create a shallow copy of the input if the types match to save
00028 // unnecessary work.
00029 // - vil_convert_cast
00030 // - vil_convert_round
00031 // - vil_convert_rgb_to_grey
00032 // - vil_convert_planes_to_grey
00033 // - vil_convert_stretch_range
00034 //
00035 // \par vil_convert with unknown pixel types
00036 // These functions are useful when taking an image from vil_load
00037 // or vil_image_resource::get_view(), where you may not know the
00038 // pixel type in advance, but want to force the image into a
00039 // particular pixel type.
00040 // - vil_convert_cast
00041 // - vil_convert_round
00042 // - vil_convert_rgb_to_grey
00043 // - vil_convert_planes_to_grey
00044 // - vil_convert_stretch_range
00045 // - vil_convert_to_component_order
00046 // - vil_convert_to_n_planes
00047 //
00048 // In general these functions expect to take scalar pixel images as
00049 // inputs. Even though many of these functions could return a known
00050 // pixel-typed image, they all return a vil_image_view_base_sptr,
00051 // so that the functions can be strung along.
00052 //
00053 // Note that these vil_convert_..( vil_image_view_base_sptr ) functions
00054 // are provided as a convenience for users of vil_load and
00055 // vil_image_resource::get_view(). Their existence should not suggest
00056 // that it is sensible to use a vil_image_view_base_sptr as storage,
00057 // nor that it is a good idea to write functions that
00058 // take or return a vil_image_view_base_sptr. If you need a
00059 // pixel-type-agnostic image container then use a vil_image_resource_sptr
00060 //
00061 // It may be a good idea to provide vil_image_resource_sptr based
00062 // vil_converts as well.
00063 //
00064 // The ITK project (in Code/IO/itkConvertPixelBuffer.txx) has
00065 // functionality similar to the RGB to grayscale conversion here.  A
00066 // change was made in ITK so the computation is
00067 // (2125.0*r+7154.0*g+0721.0*b)/1000.0 instead of
00068 // 0.2125*r+0.7154*g+0.0721*b.  The reason is that the latter
00069 // expression can produce different results between Intel and
00070 // non-Intel platforms (even in cases where r==g && g==b), probably
00071 // due to different floating point representations.  This may not be
00072 // too important, but it is worth noting here.  In vil_convert.h we
00073 // cannot make the same change without adding computation because
00074 // vil_convert_rgb_to_grey() lets you pass in the weights.  We'd have
00075 // to multiply by 10000 to maintain the current API.
00076 //
00077 // \verbatim
00078 //  Modifications
00079 //   23 Oct.2003 - Peter Vanroose - Added support for 64-bit int pixels
00080 //   30 Mar.2007 - Peter Vanroose - Commented out deprecated versions of vil_convert_cast & vil_convert_to_grey_using_average
00081 // \endverbatim
00082 
00083 #include <vcl_cassert.h>
00084 #include <vcl_limits.h>
00085 #include <vil/vil_transform.h>
00086 #include <vil/vil_math.h>
00087 #include <vil/vil_plane.h>
00088 #include <vil/vil_copy.h>
00089 #include <vil/vil_exception.h>
00090 
00091 //: Performs conversion between different pixel types.
00092 template <class In, class Out>
00093 class vil_convert_cast_pixel
00094 {
00095  public:
00096   void operator () (In v, Out &d) const;
00097 };
00098 
00099 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00100 // deal with conversions from floating point types to/from some compounds
00101 #define macro( in , out )\
00102 VCL_DEFINE_SPECIALIZATION \
00103 inline void vil_convert_cast_pixel<in, vil_rgb<out > >::operator () (in v, vil_rgb<out >& d) const \
00104 { d.r = d.g = d.b = (out)v; } \
00105 VCL_DEFINE_SPECIALIZATION \
00106 inline void vil_convert_cast_pixel<vil_rgb<out >, in >::operator () (vil_rgb<out > v, in& d) const \
00107 { d = (in)(0.2125*v.r+0.7154*v.g+0.0721*v.b); } \
00108 VCL_DEFINE_SPECIALIZATION \
00109 inline void vil_convert_cast_pixel<in, vil_rgba<out > >::operator () (in v, vil_rgba<out >& d) const \
00110 { d.r = d.g = d.b = (out)v; d.a=1; } \
00111 VCL_DEFINE_SPECIALIZATION \
00112 inline void vil_convert_cast_pixel<vil_rgba<out >, in >::operator () (vil_rgba<out > v, in& d) const \
00113 { d = (in)(0.2125*v.r+0.7154*v.g+0.0721*v.b); }
00114 macro( vxl_byte , vxl_byte )
00115 macro( vxl_int_16 , vxl_byte )
00116 macro( vxl_uint_16 , vxl_byte )
00117 macro( vxl_int_32 , vxl_byte )
00118 macro( vxl_uint_32 , vxl_byte )
00119 macro( float , vxl_byte )
00120 macro( double , vxl_byte )
00121 macro( vxl_byte , vxl_sbyte )
00122 macro( vxl_int_16 , vxl_sbyte )
00123 macro( vxl_uint_16 , vxl_sbyte )
00124 macro( vxl_int_32 , vxl_sbyte )
00125 macro( vxl_uint_32 , vxl_sbyte )
00126 macro( float , vxl_sbyte )
00127 macro( double , vxl_sbyte )
00128 macro( vxl_int_16 , vxl_int_16 )
00129 macro( float , vxl_int_16 )
00130 macro( double , vxl_int_16 )
00131 macro( vxl_uint_16 , vxl_uint_16 )
00132 macro( float , vxl_uint_16 )
00133 macro( double , vxl_uint_16 )
00134 macro( vxl_int_32 , vxl_int_32 )
00135 macro( float , vxl_int_32 )
00136 macro( double , vxl_int_32 )
00137 macro( vxl_uint_32 , vxl_uint_32 )
00138 macro( float , vxl_uint_32 )
00139 macro( double , vxl_uint_32 )
00140 macro( double , float )
00141 #if VXL_HAS_INT_64
00142 macro( vxl_int_64 , vxl_byte )
00143 macro( vxl_uint_64 , vxl_byte )
00144 macro( vxl_int_64 , vxl_sbyte )
00145 macro( vxl_uint_64 , vxl_sbyte )
00146 macro( vxl_int_64 , vxl_int_64 )
00147 macro( float , vxl_int_64 )
00148 macro( double , vxl_int_64 )
00149 macro( vxl_uint_64 , vxl_uint_64 )
00150 macro( float , vxl_uint_64 )
00151 macro( double , vxl_uint_64 )
00152 #endif
00153 #undef macro
00154 #define macro( inout )\
00155 VCL_DEFINE_SPECIALIZATION \
00156 inline void vil_convert_cast_pixel<inout, inout >::operator () ( \
00157   inout v, inout& d) const { d=v; }
00158 macro( vxl_byte )
00159 macro( vxl_sbyte )
00160 macro( vxl_uint_16 )
00161 macro( vxl_int_16 )
00162 macro( vxl_uint_32 )
00163 macro( vxl_int_32 )
00164 #if VXL_HAS_INT_64
00165 macro( vxl_uint_64 )
00166 macro( vxl_int_64 )
00167 #endif
00168 macro( float )
00169 macro( double )
00170 #undef macro
00171 VCL_DEFINE_SPECIALIZATION
00172 inline void vil_convert_cast_pixel<vil_rgb<vxl_byte>, vil_rgb<vxl_byte> >::operator () (
00173   vil_rgb<vxl_byte> v, vil_rgb<vxl_byte>& d) const { d.r=v.r, d.g=v.g, d.b=v.b; }
00174 VCL_DEFINE_SPECIALIZATION
00175 inline void vil_convert_cast_pixel<vil_rgba<vxl_byte>, vil_rgba<vxl_byte> >::operator () (
00176   vil_rgba<vxl_byte> v, vil_rgba<vxl_byte>& d) const { d.r=v.r, d.g=v.g, d.b=v.b, d.a=v.a; }
00177 #define macro( in )\
00178 VCL_DEFINE_SPECIALIZATION \
00179 inline void vil_convert_cast_pixel<in,vcl_complex<double> >::operator () (in v, vcl_complex<double>& d) const \
00180 { d = vcl_complex<double>(double(v),0.0); } \
00181 VCL_DEFINE_SPECIALIZATION \
00182 inline void vil_convert_cast_pixel<in,vcl_complex<float> >::operator () (in v, vcl_complex<float>& d) const \
00183 { d = vcl_complex<float>(float(v),0.0f); }
00184 macro( vxl_byte )
00185 macro( vxl_sbyte )
00186 macro( vxl_int_16 )
00187 macro( vxl_uint_16 )
00188 macro( vxl_int_32 )
00189 macro( vxl_uint_32 )
00190 #if VXL_HAS_INT_64
00191 macro( vxl_int_64 )
00192 macro( vxl_uint_64 )
00193 #endif
00194 #undef macro
00195 #define macro( out )\
00196 VCL_DEFINE_SPECIALIZATION \
00197 inline void vil_convert_cast_pixel<vcl_complex<double>,out >::operator () (vcl_complex<double> d, out& v) const \
00198 { v = (out)(d.real()); } \
00199 VCL_DEFINE_SPECIALIZATION \
00200 inline void vil_convert_cast_pixel<vcl_complex<float>,out >::operator () (vcl_complex<float> d, out& v) const \
00201 { v = (out)(d.real()); }
00202 macro( vxl_byte )
00203 macro( vxl_sbyte )
00204 macro( vxl_int_16 )
00205 macro( vxl_uint_16 )
00206 macro( vxl_int_32 )
00207 macro( vxl_uint_32 )
00208 #if VXL_HAS_INT_64
00209 macro( vxl_int_64 )
00210 macro( vxl_uint_64 )
00211 #endif
00212 #undef macro
00213 #endif //DOXYGEN_SHOULD_SKIP_THIS
00214 // declare general case in case anyone needs something weird.
00215 
00216 #if defined(VCL_VC)
00217 // Visual C++ intentionally warns when a non-bool is assigned or
00218 // cast to a bool. Since the following cast is valid, we suppress the
00219 // warning.
00220 # pragma warning( push )
00221 # pragma warning( disable : 4800 )
00222 #endif
00223 
00224 template <class In, class Out>
00225 inline void vil_convert_cast_pixel<In, Out>::operator () (In v, Out &d) const
00226 {
00227   d = static_cast<Out>(v);
00228 }
00229 
00230 #if defined(VCL_VC)
00231 # pragma warning( pop )
00232 #endif
00233 
00234 
00235 //: Cast one pixel type to another (with rounding).
00236 // There must be a cast operator from inP to outP
00237 //
00238 // If the two pixel types are the same, the destination may only be a shallow
00239 // copy of the source.
00240 // \relates vil_image_view
00241 template <class inP, class outP>
00242 inline void vil_convert_cast(const vil_image_view<inP >&src,
00243                              vil_image_view<outP >&dest)
00244 {
00245   if (vil_pixel_format_of(inP()) == vil_pixel_format_of(outP()))
00246     dest = src;
00247   else
00248     vil_transform2(src, dest, vil_convert_cast_pixel<inP, outP>());
00249 }
00250 
00251 #if 0 // TODO ?
00252 
00253 //: Cast the unknown pixel type to the known one, if possible.
00254 //
00255 // Will call the other vil_convert_case to do the actual
00256 // conversion. For template instantiation reasons, this will only
00257 // convert to a scalar type, not an RGB or RGBA type.
00258 // However, the destination image will have a plane step of 1 if the source
00259 // image is RGB or RGBA, i.e., the pixel layout will still be RGBRGB...
00260 //
00261 // \relates vil_image_view
00262 //
00263 template <class outP>
00264 inline void vil_convert_cast(const vil_image_view_base_sptr&src, vil_image_view<outP >&dest)
00265 {
00266 #define docase(T) \
00267    case T: \
00268      vil_convert_cast( vil_image_view< typename vil_pixel_format_type_of<T >::component_type >(src), dest );\
00269      break
00270 
00271   switch ( src->pixel_format() )
00272   {
00273     docase( VIL_PIXEL_FORMAT_UINT_32 );
00274     docase( VIL_PIXEL_FORMAT_INT_32 );
00275     docase( VIL_PIXEL_FORMAT_UINT_16 );
00276     docase( VIL_PIXEL_FORMAT_INT_16 );
00277     docase( VIL_PIXEL_FORMAT_BYTE );
00278     docase( VIL_PIXEL_FORMAT_SBYTE );
00279     docase( VIL_PIXEL_FORMAT_FLOAT );
00280     docase( VIL_PIXEL_FORMAT_DOUBLE );
00281     docase( VIL_PIXEL_FORMAT_BOOL );
00282 
00283     docase( VIL_PIXEL_FORMAT_RGB_UINT_32 );
00284     docase( VIL_PIXEL_FORMAT_RGB_INT_32 );
00285     docase( VIL_PIXEL_FORMAT_RGB_UINT_16 );
00286     docase( VIL_PIXEL_FORMAT_RGB_INT_16 );
00287     docase( VIL_PIXEL_FORMAT_RGB_BYTE );
00288     docase( VIL_PIXEL_FORMAT_RGB_SBYTE );
00289     docase( VIL_PIXEL_FORMAT_RGB_FLOAT );
00290     docase( VIL_PIXEL_FORMAT_RGB_DOUBLE );
00291 
00292     docase( VIL_PIXEL_FORMAT_RGBA_UINT_32 );
00293     docase( VIL_PIXEL_FORMAT_RGBA_INT_32 );
00294     docase( VIL_PIXEL_FORMAT_RGBA_UINT_16 );
00295     docase( VIL_PIXEL_FORMAT_RGBA_INT_16 );
00296     docase( VIL_PIXEL_FORMAT_RGBA_BYTE );
00297     docase( VIL_PIXEL_FORMAT_RGBA_SBYTE );
00298     docase( VIL_PIXEL_FORMAT_RGBA_FLOAT );
00299     docase( VIL_PIXEL_FORMAT_RGBA_DOUBLE );
00300 
00301     docase( VIL_PIXEL_FORMAT_COMPLEX_FLOAT );
00302     docase( VIL_PIXEL_FORMAT_COMPLEX_DOUBLE );
00303 
00304     default:
00305      ;
00306   }
00307 #undef docase
00308 }
00309 
00310 #endif // 0
00311 
00312 //: Performs rounding between different pixel types.
00313 template <class In, class Out>
00314 class vil_convert_round_pixel
00315 {
00316  public:
00317   void operator () (In v, Out &d) const;
00318 };
00319 
00320 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00321 // deal with conversions from floating point types to some compounds
00322 #define macro( in , out )\
00323 VCL_DEFINE_SPECIALIZATION \
00324 inline void vil_convert_round_pixel<in, out >::operator () ( \
00325   in v, out& d) const { \
00326   d.r = (out::value_type)(v.r+0.5); \
00327   d.g = (out::value_type)(v.g+0.5); \
00328   d.b = (out::value_type)(v.b+0.5); }
00329 
00330 macro( vil_rgb<float> , vil_rgb<vxl_byte> )
00331 macro( vil_rgb<double> , vil_rgb<vxl_byte> )
00332 macro( vil_rgb<float> , vil_rgb<vxl_sbyte> )
00333 macro( vil_rgb<double> , vil_rgb<vxl_sbyte> )
00334 macro( vil_rgb<float> , vil_rgb<vxl_int_16> )
00335 macro( vil_rgb<double> , vil_rgb<vxl_int_16> )
00336 macro( vil_rgb<float> , vil_rgb<vxl_uint_16> )
00337 macro( vil_rgb<double> , vil_rgb<vxl_uint_16> )
00338 macro( vil_rgb<float> , vil_rgb<vxl_int_32> )
00339 macro( vil_rgb<double> , vil_rgb<vxl_int_32> )
00340 macro( vil_rgb<float> , vil_rgb<vxl_uint_32> )
00341 macro( vil_rgb<double> , vil_rgb<vxl_uint_32> )
00342 #if VXL_HAS_INT_64
00343 macro( vil_rgb<float> , vil_rgb<vxl_int_64> )
00344 macro( vil_rgb<double> , vil_rgb<vxl_int_64> )
00345 macro( vil_rgb<float> , vil_rgb<vxl_uint_64> )
00346 macro( vil_rgb<double> , vil_rgb<vxl_uint_64> )
00347 #endif
00348 #undef macro
00349 #define macro( in , out )\
00350 VCL_DEFINE_SPECIALIZATION \
00351 inline void vil_convert_round_pixel<in, out >::operator () (in v, out& d) \
00352   const { \
00353   d.r = (out::value_type)(v.r); \
00354   d.g = (out::value_type)(v.g); \
00355   d.b = (out::value_type)(v.b); }
00356 macro( vil_rgb<float> , vil_rgb<float> )
00357 macro( vil_rgb<double> , vil_rgb<double> )
00358 #undef macro
00359 #define macro( in , out )\
00360 VCL_DEFINE_SPECIALIZATION \
00361 inline void vil_convert_round_pixel<in, out >::operator () (in v, out& d) \
00362   const { \
00363   d.r = (out::value_type)(v.r+0.5); \
00364   d.g = (out::value_type)(v.g+0.5); \
00365   d.b = (out::value_type)(v.b+0.5); \
00366   d.a = (out::value_type)(v.a+0.5); }
00367 macro( vil_rgba<float> , vil_rgba<vxl_byte> )
00368 macro( vil_rgba<double> , vil_rgba<vxl_byte> )
00369 macro( vil_rgba<float> , vil_rgba<vxl_sbyte> )
00370 macro( vil_rgba<double> , vil_rgba<vxl_sbyte> )
00371 macro( vil_rgba<float> , vil_rgba<vxl_int_16> )
00372 macro( vil_rgba<double> , vil_rgba<vxl_int_16> )
00373 macro( vil_rgba<float> , vil_rgba<vxl_uint_16> )
00374 macro( vil_rgba<double> , vil_rgba<vxl_uint_16> )
00375 macro( vil_rgba<float> , vil_rgba<vxl_int_32> )
00376 macro( vil_rgba<double> , vil_rgba<vxl_int_32> )
00377 macro( vil_rgba<float> , vil_rgba<vxl_uint_32> )
00378 macro( vil_rgba<double> , vil_rgba<vxl_uint_32> )
00379 #if VXL_HAS_INT_64
00380 macro( vil_rgba<float> , vil_rgba<vxl_int_64> )
00381 macro( vil_rgba<double> , vil_rgba<vxl_int_64> )
00382 macro( vil_rgba<float> , vil_rgba<vxl_uint_64> )
00383 macro( vil_rgba<double> , vil_rgba<vxl_uint_64> )
00384 #endif
00385 #undef macro
00386 #define macro( in , out )\
00387 VCL_DEFINE_SPECIALIZATION \
00388 inline void vil_convert_round_pixel<in, out >::operator () (in v, out& d) \
00389   const { \
00390   d.r = (out::value_type)(v.r); \
00391   d.g = (out::value_type)(v.g); \
00392   d.b = (out::value_type)(v.b); \
00393   d.a = (out::value_type)(v.a); }
00394 macro( vil_rgba<float> , vil_rgba<float> )
00395 macro( vil_rgba<double> , vil_rgba<double> )
00396 #undef macro
00397 
00398 #define macro( in , out )\
00399 VCL_DEFINE_SPECIALIZATION \
00400 inline void vil_convert_round_pixel<in, out >::operator () (in v, out& d) \
00401 const { d = (out)(v > 0.0 ? v + 0.5 : v - 0.5); }
00402 macro( float , vxl_byte )
00403 macro( double , vxl_byte )
00404 macro( float , vxl_sbyte )
00405 macro( double , vxl_sbyte )
00406 macro( float , vxl_int_16 )
00407 macro( double , vxl_int_16 )
00408 macro( float , vxl_uint_16 )
00409 macro( double , vxl_uint_16 )
00410 macro( float , vxl_int_32 )
00411 macro( double , vxl_int_32 )
00412 macro( float , vxl_uint_32 )
00413 macro( double , vxl_uint_32 )
00414 #if VXL_HAS_INT_64
00415 macro( float , vxl_int_64 )
00416 macro( double , vxl_int_64 )
00417 macro( float , vxl_uint_64 )
00418 macro( double , vxl_uint_64 )
00419 #endif
00420 #undef macro
00421 #endif //DOXYGEN_SHOULD_SKIP_THIS
00422 
00423 // declare general case for scalars
00424 template <class In, class Out>
00425 inline void vil_convert_round_pixel<In, Out>::operator () (In v, Out &d) const
00426 {
00427   d = (Out)(v);
00428 }
00429 
00430 
00431 //: Convert one pixel type to another with rounding.
00432 // This should only be used to convert scalar pixel types to other scalar
00433 // pixel types, or RGBs to RGBs. This function only rounds in terms of the
00434 // destination type.
00435 //
00436 // If the two pixel types are the same, the destination may only be a
00437 // shallow copy of the source.
00438 // \relates vil_image_view
00439 template <class inP, class outP>
00440 inline void vil_convert_round(const vil_image_view<inP >&src,
00441                               vil_image_view<outP >&dest)
00442 {
00443   if (vil_pixel_format_of(inP()) == vil_pixel_format_of(outP()))
00444     dest = src;
00445   else
00446     vil_transform2(src, dest, vil_convert_round_pixel<inP, outP>());
00447 }
00448 
00449 
00450 //: Convert various rgb types to greyscale, using given weights
00451 template <class inP, class outP>
00452 class vil_convert_rgb_to_grey_pixel
00453 {
00454   double rw_, gw_, bw_;
00455  public:
00456   vil_convert_rgb_to_grey_pixel(double rw, double gw, double bw):
00457     rw_(rw), gw_(gw), bw_(bw) {}
00458 
00459   void operator() (vil_rgb<inP> v, outP& d) const {
00460     vil_convert_round_pixel<double,outP>()(rw_*v.r+gw_*v.g+bw_*v.b, d); }
00461   void operator() (vil_rgba<inP> v, outP& d) const {
00462     vil_convert_round_pixel<double,outP>()(rw_*v.r+gw_*v.g+bw_*v.b, d); }
00463 };
00464 
00465 //: Convert single plane rgb (or rgba) images to greyscale.
00466 // Component types can be different. Rounding will take place if appropriate.
00467 //
00468 // Default weights convert from linear RGB to CIE luminance assuming a
00469 // modern monitor.  See Charles Poynton's Colour FAQ
00470 // http://www.poynton.com/ColorFAQ.html
00471 template <class rgbP, class outP>
00472 inline void vil_convert_rgb_to_grey(const vil_image_view<rgbP >&src,
00473                                     vil_image_view<outP >&dest,
00474                                     double rw=0.2125, double gw=0.7154, double bw=0.0721)
00475 {
00476   vil_convert_rgb_to_grey_pixel<VCL_DISAPPEARING_TYPENAME rgbP::value_type, outP>
00477     func(rw, gw, bw);
00478   assert(src.nplanes() == 1);
00479   vil_transform2(src, dest, func);
00480 }
00481 
00482 
00483 //: Convert first three planes of src image to grey, assuming rgb.
00484 // Pixel types can be different. Rounding will take place if appropriate.
00485 //
00486 // Default weights convert from linear RGB to CIE luminance assuming a
00487 // modern monitor.  See Charles Pontyon's Colour FAQ
00488 // http://www.poynton.com/ColorFAQ.html
00489 template <class inP, class outP>
00490 inline void vil_convert_planes_to_grey(const vil_image_view<inP>&src,
00491                                        vil_image_view<outP>&dest,
00492                                        double rw=0.2125, double gw=0.7154, double bw=0.0721)
00493 {
00494   assert(src.nplanes() >= 3);
00495   assert(vil_pixel_format_num_components(src.pixel_format()) == 1);
00496   assert(vil_pixel_format_num_components(dest.pixel_format()) == 1);
00497   dest.set_size(src.ni(), src.nj(), 1);
00498   for (unsigned j = 0; j < src.nj(); ++j)
00499     for (unsigned i = 0; i < src.ni(); ++i)
00500       vil_convert_round_pixel<double,outP>()(
00501         src(i,j,0)*rw + src(i,j,1)*gw + src(i,j,2)*bw, dest(i,j));
00502 }
00503 
00504 
00505 //: Convert src to byte image dest by stretching to range [0,255]
00506 // \relates vil_image_view
00507 template <class T>
00508 inline void vil_convert_stretch_range(const vil_image_view<T>& src,
00509                                       vil_image_view<vxl_byte>& dest)
00510 {
00511   T min_b,max_b;
00512   vil_math_value_range(src,min_b,max_b);
00513   double a = -1.0*double(min_b);
00514   double b = 0.0;
00515   if (max_b-min_b >0) b = 255.0/(max_b-min_b);
00516   dest.set_size(src.ni(), src.nj(), src.nplanes());
00517   for (unsigned p = 0; p < src.nplanes(); ++p)
00518     for (unsigned j = 0; j < src.nj(); ++j)
00519       for (unsigned i = 0; i < src.ni(); ++i)
00520          dest(i,j,p) = static_cast<vxl_byte>( b*( src(i,j,p)+ a ) );
00521 }
00522 
00523 
00524 // It doesn't seem sensible to write a general stretch
00525 // conversion function from any type to any type.
00526 // The individual pixel transfer function has to perform
00527 // multiplications which have to be done in double
00528 // to provide both the range and precision. You may as well
00529 // leave the image in double, and convert it again later.
00530 
00531 //: Convert src to double image dest by stretching to range [lo,hi]
00532 template <class inP>
00533 inline void vil_convert_stretch_range(const vil_image_view<inP>& src,
00534                                       vil_image_view<double>& dest,
00535                                       double lo, double hi)
00536 {
00537   inP min_b=0, max_b=0;
00538   vil_math_value_range(src,min_b,max_b);
00539   double b = 0.0;
00540   if (max_b-min_b >0)
00541     b = static_cast<double>(hi-lo)/static_cast<double>(max_b-min_b);
00542   double a = -1.0*min_b*b + lo;
00543   dest.set_size(src.ni(), src.nj(), src.nplanes());
00544   for (unsigned p = 0; p < src.nplanes(); ++p)
00545     for (unsigned j = 0; j < src.nj(); ++j)
00546       for (unsigned i = 0; i < src.ni(); ++i)
00547         dest(i,j,p) =  b*src(i,j,p) + a;
00548 }
00549 
00550 //: Convert src to float image dest by stretching to range [lo,hi]
00551 template <class inP>
00552 inline void vil_convert_stretch_range(const vil_image_view<inP>& src,
00553                                       vil_image_view<float>& dest,
00554                                       float lo, float hi)
00555 {
00556   inP min_b=0, max_b=0;
00557   vil_math_value_range(src,min_b,max_b);
00558   float b = 0.0;
00559   if (max_b-min_b >0)
00560     b = (hi-lo)/static_cast<float>(max_b-min_b);
00561   float a = -1.0f*min_b*b + lo;
00562   dest.set_size(src.ni(), src.nj(), src.nplanes());
00563   for (unsigned p = 0; p < src.nplanes(); ++p)
00564     for (unsigned j = 0; j < src.nj(); ++j)
00565       for (unsigned i = 0; i < src.ni(); ++i)
00566         dest(i,j,p) =  b*src(i,j,p) + a;
00567 }
00568 
00569 
00570 //: Convert src image<inP> to dest image<double> by stretching input range [src_lo, src_hi] to output range [dest_lo, dest_hi].
00571 // Inputs < src_lo are mapped to dest_lo, and inputs > src_hi to dest_hi.
00572 template <class inP>
00573 inline void vil_convert_stretch_range_limited(const vil_image_view<inP>& src,
00574                                               vil_image_view<double>& dest,
00575                                               const inP src_lo,
00576                                               const inP src_hi,
00577                                               const double dest_lo,
00578                                               const double dest_hi)
00579 {
00580   double ddest = dest_hi - dest_lo;
00581   double dsrc = static_cast<double>(src_hi - src_lo);
00582   double dds = ddest / dsrc;
00583 
00584   dest.set_size(src.ni(), src.nj(), src.nplanes());
00585   for (unsigned p = 0; p < src.nplanes(); ++p)
00586     for (unsigned j = 0; j < src.nj(); ++j)
00587       for (unsigned i = 0; i < src.ni(); ++i)
00588       {
00589         inP s = src(i,j,p);
00590         dest(i,j,p) = s<=src_lo ? dest_lo :
00591                       s>=src_hi ? dest_hi :
00592                                   dest_lo + dds*static_cast<double>(s-src_lo);
00593       }
00594 }
00595 
00596 //: Convert src image<inP> to dest image<float> by stretching input range [src_lo, src_hi] to output range [dest_lo, dest_hi].
00597 // Inputs < src_lo are mapped to dest_lo, and inputs > src_hi to dest_hi.
00598 template <class inP>
00599 inline void vil_convert_stretch_range_limited(const vil_image_view<inP>& src,
00600                                               vil_image_view<float>& dest,
00601                                               const inP src_lo,
00602                                               const inP src_hi,
00603                                               const float dest_lo,
00604                                               const float dest_hi)
00605 {
00606   float ddest = dest_hi - dest_lo;
00607   float dsrc = static_cast<float>(src_hi - src_lo);
00608   float dds = ddest / dsrc;
00609 
00610   dest.set_size(src.ni(), src.nj(), src.nplanes());
00611   for (unsigned p = 0; p < src.nplanes(); ++p)
00612     for (unsigned j = 0; j < src.nj(); ++j)
00613       for (unsigned i = 0; i < src.ni(); ++i)
00614       {
00615         inP s = src(i,j,p);
00616         dest(i,j,p) = s<=src_lo ? dest_lo :
00617                       s>=src_hi ? dest_hi :
00618                                   dest_lo + dds*static_cast<float>(s-src_lo);
00619       }
00620 }
00621 
00622 //: Convert src image<inP> to dest image<float> by stretching input range [src_lo, src_hi] to output range [dest_lo, dest_hi].
00623 // Inputs < src_lo are mapped to dest_lo, and inputs > src_hi to dest_hi.
00624 template <class inP>
00625 inline void vil_convert_stretch_range_limited(const vil_image_view<inP>& src,
00626                                               vil_image_view<vxl_byte>& dest,
00627                                               const inP src_lo,
00628                                               const inP src_hi,
00629                                               const vxl_byte dest_lo,
00630                                               const vxl_byte dest_hi)
00631 {
00632   const double ddest = dest_hi - dest_lo;
00633   const double dsrc = static_cast<double>(src_hi - src_lo);
00634   const double dds = ddest / dsrc;
00635 
00636   dest.set_size(src.ni(), src.nj(), src.nplanes());
00637   for (unsigned p = 0; p < src.nplanes(); ++p)
00638     for (unsigned j = 0; j < src.nj(); ++j)
00639       for (unsigned i = 0; i < src.ni(); ++i)
00640       {
00641         inP s = src(i,j,p);
00642         dest(i,j,p) = s<=src_lo ? dest_lo :
00643                       s>=src_hi ? dest_hi :
00644                                   static_cast<vxl_byte>(dest_lo + dds*(s-src_lo)+0.5);
00645       }
00646 }
00647 
00648 //: Convert src image<inP> to dest image<vxl_byte> by stretching input range [src_lo, src_hi] to output range [0, 255].
00649 // Inputs < src_lo are mapped to 0, and inputs > src_hi to 255.
00650 template <class inP>
00651 inline void vil_convert_stretch_range_limited(const vil_image_view<inP>& src,
00652                                               vil_image_view<vxl_byte>& dest,
00653                                               const inP src_lo,
00654                                               const inP src_hi)
00655 {
00656   const double dsrc = static_cast<double>(src_hi - src_lo);
00657   const double dds = 255.0 / dsrc;
00658 
00659   dest.set_size(src.ni(), src.nj(), src.nplanes());
00660   for (unsigned p = 0; p < src.nplanes(); ++p)
00661     for (unsigned j = 0; j < src.nj(); ++j)
00662       for (unsigned i = 0; i < src.ni(); ++i)
00663       {
00664         inP s = src(i,j,p);
00665         dest(i,j,p) = s<=src_lo ? 0u :
00666                       static_cast<vxl_byte>( s>=src_hi ? 255 : (dds*(s-src_lo)+0.5) );
00667       }
00668 }
00669 
00670 //: Cast the unknown pixel type to the known one.
00671 //
00672 // This function is designed to be used with vil_load or
00673 // vil_image_resource::get_view()
00674 // where you do not know the pixel type in advance.
00675 // If you need a
00676 // multi-component view, then call this to get the corresponding
00677 // multi-planar view, and do a second (cheap) conversion.
00678 // The input image's storage arrangement may not be preserved.
00679 template <class outP>
00680 inline vil_image_view_base_sptr vil_convert_cast(outP /*dummy*/,
00681                                                  const vil_image_view_base_sptr& src)
00682 {
00683   if (!src) return vil_image_view_base_sptr();
00684 
00685   vil_image_view_base_sptr dest = new vil_image_view<outP>;
00686   vil_image_view<outP> & dest_ref = static_cast<vil_image_view<outP> &>(*dest);
00687 
00688   switch ( vil_pixel_format_component_format(src->pixel_format()) )
00689   {
00690 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00691 #define macro(F , T) \
00692     case F: vil_convert_cast( vil_image_view<T >(*src), dest_ref ); break
00693 
00694 #if VXL_HAS_INT_64
00695     macro( VIL_PIXEL_FORMAT_UINT_64, vxl_uint_64 );
00696     macro( VIL_PIXEL_FORMAT_INT_64, vxl_int_64 );
00697 #endif
00698     macro( VIL_PIXEL_FORMAT_UINT_32, vxl_uint_32 );
00699     macro( VIL_PIXEL_FORMAT_INT_32, vxl_int_32 );
00700     macro( VIL_PIXEL_FORMAT_UINT_16, vxl_uint_16 );
00701     macro( VIL_PIXEL_FORMAT_INT_16, vxl_int_16 );
00702     macro( VIL_PIXEL_FORMAT_BYTE, vxl_byte );
00703     macro( VIL_PIXEL_FORMAT_SBYTE, vxl_sbyte );
00704     macro( VIL_PIXEL_FORMAT_FLOAT, float );
00705     macro( VIL_PIXEL_FORMAT_DOUBLE, double );
00706     macro( VIL_PIXEL_FORMAT_BOOL, bool );
00707 #undef macro
00708 #endif // DOXYGEN_SHOULD_SKIP_THIS
00709     default:
00710       vil_exception_warning(vil_exception_unsupported_pixel_format(
00711         src->pixel_format(), "vil_convert_cast") );
00712       dest = 0;
00713   }
00714   return dest;
00715 }
00716 
00717 #if 0 // deprecated
00718 //: Cast the unknown pixel type to the known one, if possible.
00719 //
00720 // Will call the other vil_convert_cast to do the actual
00721 // conversion. For template instantiation reasons, this will only
00722 // convert to a scalar type, not a RGB or RGBA type. If you need a
00723 // multi-component view, then call this to get the corresponding
00724 // multi-planar view, and do a second (cheap) conversion.
00725 //
00726 // \deprecated Use other vil_convert_cast()
00727 // Can be removed after VXL 1.1.1
00728 template <class outP>
00729 inline void vil_convert_cast(const vil_image_view_base_sptr& src,
00730                              vil_image_view<outP >&dest)
00731 {
00732   VXL_DEPRECATED( "void vil_convert_cast(const vil_image_view_base_sptr&,"
00733                   " vil_image_view<outP>&)" );
00734 
00735   switch ( src->pixel_format() )
00736   {
00737 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00738 #define macro(F , T) \
00739     case F: vil_convert_cast( vil_image_view<T >(src), dest ); break;
00740 
00741 #if VXL_HAS_INT_64
00742     macro( VIL_PIXEL_FORMAT_UINT_64, vxl_uint_64 )
00743     macro( VIL_PIXEL_FORMAT_INT_64, vxl_int_64 )
00744 #endif
00745     macro( VIL_PIXEL_FORMAT_UINT_32, vxl_uint_32 )
00746     macro( VIL_PIXEL_FORMAT_INT_32, vxl_int_32 )
00747     macro( VIL_PIXEL_FORMAT_UINT_16, vxl_uint_16 )
00748     macro( VIL_PIXEL_FORMAT_INT_16, vxl_int_16 )
00749     macro( VIL_PIXEL_FORMAT_BYTE, vxl_byte )
00750     macro( VIL_PIXEL_FORMAT_SBYTE, vxl_sbyte )
00751     macro( VIL_PIXEL_FORMAT_FLOAT, float )
00752     macro( VIL_PIXEL_FORMAT_DOUBLE, double )
00753     macro( VIL_PIXEL_FORMAT_BOOL, bool )
00754 #undef macro
00755 #endif // DOXYGEN_SHOULD_SKIP_THIS
00756 
00757     // Skip the RGB type conversions because the vil_convert_cast are
00758     // not complete. For example, a cast from vxl_uint_16 to
00759     // vil_rgb<vxl_uint_32> is not defined.
00760     default:
00761       dest.clear();
00762   }
00763 }
00764 #endif // 0
00765 
00766 //: Convert an image of any pixel type to another with rounding.
00767 // This should only be used to convert to scalar
00768 // pixel types. This function only rounds in terms of the
00769 // destination type.
00770 // This function is designed to be used with vil_load or
00771 // vil_image_resource::get_view()
00772 // where you do not know the pixel type in advance.
00773 //
00774 // If the input image already has outP as its pixel type, the destination
00775 // may only be a shallow copy of the source.
00776 // outP should be a scalar pixel type.
00777 // The input image's storage arrangement may not be preserved.
00778 template <class outP>
00779 inline vil_image_view_base_sptr vil_convert_round(
00780   outP /*dummy*/, const vil_image_view_base_sptr &src)
00781 {
00782   assert(vil_pixel_format_num_components(vil_pixel_format_of(outP()))==1);
00783 
00784   if (!src) return vil_image_view_base_sptr();
00785 
00786   if (vil_pixel_format_component_format(src->pixel_format()) ==
00787       vil_pixel_format_of(outP()))
00788     return src;
00789 
00790   vil_image_view_base_sptr dest = new vil_image_view<outP >;
00791   vil_image_view<outP > &dest_ref = static_cast<vil_image_view<outP >&>(*dest);
00792 
00793   switch (vil_pixel_format_component_format(src->pixel_format()))
00794   {
00795 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00796 #define macro( F , T ) \
00797    case F: { \
00798     vil_image_view<T > src1 = src; \
00799     vil_transform2(src1, dest_ref, vil_convert_round_pixel<T , outP>()); \
00800     break; }
00801 macro(VIL_PIXEL_FORMAT_BYTE, vxl_byte )
00802 macro(VIL_PIXEL_FORMAT_SBYTE , vxl_sbyte )
00803 #if VXL_HAS_INT_64
00804 macro(VIL_PIXEL_FORMAT_UINT_64 , vxl_uint_64 )
00805 macro(VIL_PIXEL_FORMAT_INT_64 , vxl_int_64 )
00806 #endif
00807 macro(VIL_PIXEL_FORMAT_UINT_32 , vxl_uint_32 )
00808 macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
00809 macro(VIL_PIXEL_FORMAT_UINT_16 , vxl_uint_16 )
00810 macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
00811 macro(VIL_PIXEL_FORMAT_FLOAT , float )
00812 macro(VIL_PIXEL_FORMAT_DOUBLE , double )
00813 #undef macro
00814 #endif // DOXYGEN_SHOULD_SKIP_THIS
00815   default:
00816     vil_exception_warning(vil_exception_unsupported_pixel_format(
00817       src->pixel_format(), "vil_convert_round") );
00818     dest=0;
00819   }
00820   return dest;
00821 }
00822 
00823 
00824 //: Force data to be suitable for viewing as multi component view.
00825 // The output data will have values from different planes but the same
00826 // pixel location stored in adjacent memory locations. After using this
00827 // function on an input with 3 planes, an assignment to a
00828 // vil_image_view<vil_rgb<T> > will always work.
00829 // The input image's scalar pixel type will be preserved.
00830 inline vil_image_view_base_sptr vil_convert_to_component_order(
00831   const vil_image_view_base_sptr& src)
00832 {
00833   if (!src) return vil_image_view_base_sptr();
00834 
00835   vil_image_view_base_sptr dest;
00836 
00837   switch (vil_pixel_format_component_format(src->pixel_format()))
00838   {
00839 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00840 #define macro( F , T )\
00841    case F: { \
00842     vil_image_view<T > src_ref(src); \
00843     if (!src_ref) return vil_image_view_base_sptr(); \
00844     if (src_ref.planestep()==1) return src; \
00845     const unsigned ni=src->ni(), nj=src->nj(), nplanes=src->nplanes(); \
00846     vil_memory_chunk_sptr chunk = new vil_memory_chunk(ni*nj*nplanes*sizeof(T), \
00847                                                        vil_pixel_format_component_format(F)); \
00848     dest = new vil_image_view<T >(chunk, reinterpret_cast<T*>(chunk->data()), \
00849                                   ni, nj, nplanes, nplanes, nplanes*ni, 1); \
00850     vil_image_view<T > & dest_ref = static_cast<vil_image_view<T >&>(*dest); \
00851     vil_copy_reformat(src_ref, dest_ref); \
00852     break; }
00853 macro(VIL_PIXEL_FORMAT_BYTE, vxl_byte )
00854 macro(VIL_PIXEL_FORMAT_SBYTE , vxl_sbyte )
00855 #if VXL_HAS_INT_64
00856 macro(VIL_PIXEL_FORMAT_UINT_64 , vxl_uint_64 )
00857 macro(VIL_PIXEL_FORMAT_INT_64 , vxl_int_64 )
00858 #endif
00859 macro(VIL_PIXEL_FORMAT_UINT_32 , vxl_uint_32 )
00860 macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
00861 macro(VIL_PIXEL_FORMAT_UINT_16 , vxl_uint_16 )
00862 macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
00863 macro(VIL_PIXEL_FORMAT_FLOAT , float )
00864 macro(VIL_PIXEL_FORMAT_DOUBLE , double )
00865 #undef macro
00866 #endif // DOXYGEN_SHOULD_SKIP_THIS
00867 
00868     default:
00869       vil_exception_warning(vil_exception_unsupported_pixel_format(
00870         src->pixel_format(), "vil_convert_to_compound_order") );
00871       dest=0;
00872   }
00873   return dest;
00874 }
00875 
00876 #if 0 // deprecated
00877 //: Create a greyscale image from any image src.
00878 // This function is designed to be used with vil_load or
00879 // vil_image_resource::get_view()
00880 // where you do not know the pixel type in advance. e.g.
00881 // \code
00882 // vil_image_view<float> input =
00883 //   vil_convert_to_grey_using_average(vil_load(filename), float());
00884 // \endcode
00885 // If you have a image_view of known pixel_type then you should use one of
00886 // the other vil_convert functions.
00887 // The output may be a reconfigured view of the input.
00888 // \deprecated Use other vil_convert_to_grey_using_average()
00889 template <class outP>
00890 inline vil_image_view<outP> vil_convert_to_grey_using_average(
00891   const vil_image_view_base_sptr &src, outP /*dummy*/)
00892 {
00893   VXL_DEPRECATED( "vil_convert_to_grey_using_average<outP>("
00894                   "const vil_image_view_base_sptr &, outP)" );
00895 
00896   // Check output is scalar component image.
00897   assert (vil_pixel_format_num_components(vil_pixel_format_of(outP())) == 1);
00898 
00899   if (!src) return vil_image_view<outP>();
00900 
00901   // try to do it quickly
00902   if (vil_pixel_format_of(outP()) == src->pixel_format() && src->nplanes() == 1)
00903     return vil_image_view<outP>(src);
00904 
00905   // create output view
00906   vil_image_view<outP> dest;
00907 
00908   // convert via vil_image_view<double>
00909   switch (vil_pixel_format_component_format(src->pixel_format()))
00910   {
00911 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00912 #define macro( F , T ) \
00913    case F: { \
00914     vil_image_view<T > src1 = *src; \
00915     vil_math_mean_over_planes(src1, dest, double()); \
00916     break; }
00917    macro(VIL_PIXEL_FORMAT_BYTE, vxl_byte )
00918    macro(VIL_PIXEL_FORMAT_SBYTE , vxl_sbyte )
00919 #if VXL_HAS_INT_64
00920    macro(VIL_PIXEL_FORMAT_UINT_64 , vxl_uint_64 )
00921    macro(VIL_PIXEL_FORMAT_INT_64 , vxl_int_64 )
00922 #endif
00923    macro(VIL_PIXEL_FORMAT_UINT_32 , vxl_uint_32 )
00924    macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
00925    macro(VIL_PIXEL_FORMAT_UINT_16 , vxl_uint_16 )
00926    macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
00927    macro(VIL_PIXEL_FORMAT_FLOAT , float )
00928    macro(VIL_PIXEL_FORMAT_DOUBLE , double )
00929 #undef macro
00930 #endif // DOXYGEN_SHOULD_SKIP_THIS
00931    default:
00932     dest.clear();
00933   }
00934   return dest;
00935 }
00936 #endif // 0
00937 
00938 //: Create a greyscale image of specified pixel type from any image src.
00939 // This function is designed to be used with vil_load or
00940 // vil_image_resource::get_view()
00941 // where you do not know the pixel type in advance. e.g.
00942 // \code
00943 // vil_image_view<float> input = vil_convert_cast(
00944 //   convert_to_grey_using_average(vil_load(filename)), float());
00945 // \endcode
00946 // The output may be a reconfigured view of the input.
00947 // The input image's pixel type and storage arrangement may not be preserved.
00948 inline vil_image_view_base_sptr vil_convert_to_grey_using_average(
00949   const vil_image_view_base_sptr &src)
00950 {
00951   if (!src) return vil_image_view_base_sptr();
00952 
00953   // convert via vil_image_view<double>
00954   switch (vil_pixel_format_component_format(src->pixel_format()))
00955   {
00956 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00957 #define macro( F , T ) \
00958   case F: { \
00959     /* try to do it quickly */ \
00960     if (src->nplanes() == 1 && \
00961         vil_pixel_format_component_format(src->pixel_format())==1) \
00962       return src; \
00963     /* create output view */ \
00964     vil_image_view<T > dest; \
00965     vil_image_view<T > src1 = *src; \
00966     vil_math_mean_over_planes(src1, dest, double()); \
00967     return vil_image_view_base_sptr(new vil_image_view<T >(dest)); }
00968   macro(VIL_PIXEL_FORMAT_BYTE, vxl_byte )
00969   macro(VIL_PIXEL_FORMAT_SBYTE , vxl_sbyte )
00970 #if VXL_HAS_INT_64 && !defined(VCL_VC_6)
00971   macro(VIL_PIXEL_FORMAT_UINT_64 , vxl_uint_64 )
00972   macro(VIL_PIXEL_FORMAT_INT_64 , vxl_int_64 )
00973 #endif
00974   macro(VIL_PIXEL_FORMAT_UINT_32 , vxl_uint_32 )
00975   macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
00976   macro(VIL_PIXEL_FORMAT_UINT_16 , vxl_uint_16 )
00977   macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
00978   macro(VIL_PIXEL_FORMAT_FLOAT , float )
00979   macro(VIL_PIXEL_FORMAT_DOUBLE , double )
00980 #undef macro
00981 #endif // DOXYGEN_SHOULD_SKIP_THIS
00982   default:
00983     vil_exception_warning(vil_exception_unsupported_pixel_format(
00984       src->pixel_format(), "vil_convert_to_grey_using_average") );
00985     return 0;
00986   }
00987 }
00988 
00989 
00990 //: Create a greyscale image from any image src.
00991 // This function is designed to be used with vil_load or
00992 // vil_image_resource::get_view()
00993 // where you do not know the pixel type in advance.
00994 // The output may be a reconfigured view of the input.
00995 // The input image's pixel type and storage arrangement may not be preserved.
00996 inline vil_image_view_base_sptr vil_convert_to_grey_using_rgb_weighting(
00997   double rw, double gw, double bw, const vil_image_view_base_sptr &src)
00998 {
00999   if (!src)
01000     return vil_image_view_base_sptr();
01001 
01002   // convert via vil_image_view<double>
01003   switch (vil_pixel_format_component_format(src->pixel_format()))
01004   {
01005 #ifndef DOXYGEN_SHOULD_SKIP_THIS
01006 #define macro( F , T ) \
01007   case F: { \
01008     /* try to do it quickly */ \
01009     if (src->nplanes() == 1 && \
01010         vil_pixel_format_num_components(src->pixel_format()) == 1) \
01011       return vil_image_view_base_sptr(src); \
01012     vil_image_view<T > src1 = src; \
01013     vil_image_view<double> dest1; \
01014     vil_convert_planes_to_grey(src1, dest1, rw, gw, bw); \
01015     vil_image_view<T > dest; \
01016     vil_convert_round(dest1,dest); \
01017     return vil_image_view_base_sptr(new vil_image_view<T >(dest)); }
01018   macro(VIL_PIXEL_FORMAT_BYTE, vxl_byte )
01019   macro(VIL_PIXEL_FORMAT_SBYTE , vxl_sbyte )
01020 #if VXL_HAS_INT_64 && !defined(VCL_VC_6)
01021   macro(VIL_PIXEL_FORMAT_UINT_64 , vxl_uint_64 )
01022   macro(VIL_PIXEL_FORMAT_INT_64 , vxl_int_64 )
01023 #endif
01024   macro(VIL_PIXEL_FORMAT_UINT_32 , vxl_uint_32 )
01025   macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
01026   macro(VIL_PIXEL_FORMAT_UINT_16 , vxl_uint_16 )
01027   macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
01028   macro(VIL_PIXEL_FORMAT_FLOAT , float )
01029   macro(VIL_PIXEL_FORMAT_DOUBLE , double )
01030 #undef macro
01031 #endif // DOXYGEN_SHOULD_SKIP_THIS
01032   default:
01033       vil_exception_warning(vil_exception_unsupported_pixel_format(
01034         src->pixel_format(), "vil_convert_to_grey_using_rgb_weighting") );
01035     return vil_image_view_base_sptr();
01036   }
01037 }
01038 
01039 //: Create a greyscale image from any image src using default weights.
01040 // This function is designed to be used with vil_load or
01041 // vil_image_resource::get_view()
01042 // where you do not know the pixel type in advance.
01043 // The output may be a reconfigured view of the input.
01044 // The input image's pixel type and storage arrangement may not be preserved.
01045 //
01046 // Default weights convert from linear RGB to CIE luminance assuming a
01047 // modern monitor.  See Charles Poynton's Colour FAQ
01048 // http://www.poynton.com/ColorFAQ.html
01049 
01050 inline vil_image_view_base_sptr vil_convert_to_grey_using_rgb_weighting(
01051   const vil_image_view_base_sptr &src)
01052 {
01053   return vil_convert_to_grey_using_rgb_weighting(0.2125, 0.7154, 0.0721, src);
01054 }
01055 
01056 #if 0 // deprecated version of this function now commented out
01057 //: Create a greyscale image of specified pixel type from any image src.
01058 // This function is designed to be used with vil_load or
01059 // vil_image_resource::get_view()
01060 // where you do not know the pixel type in advance.
01061 // The output may be a reconfigured view of the input.
01062 //
01063 // Default weights convert from linear RGB to CIE luminance assuming a
01064 // modern monitor.  See Charles Poynton's Colour FAQ
01065 // http://www.poynton.com/ColorFAQ.html
01066 // \deprecated Use other version of vil_convert_to_grey_using_rgb_weighting
01067 template <class outP>
01068 inline vil_image_view<outP> vil_convert_to_grey_using_rgb_weighting(
01069                           const vil_image_view_base_sptr &src,
01070                           outP /*dummy*/,
01071                           double rw=0.2125,
01072                           double gw=0.7154,
01073                           double bw=0.0721)
01074 {
01075   VXL_DEPRECATED( "vil_convert_to_grey_using_rgb_weighting<outP>("
01076                   "const vil_image_view_base_sptr &, outP)" );
01077 
01078   // Check output is scalar component image.
01079   assert (vil_pixel_format_num_components(vil_pixel_format_of(outP())) == 1);
01080 
01081   if (!src) return vil_image_view<outP>();
01082 
01083   // try to do it quickly
01084   if (vil_pixel_format_of(outP()) == src->pixel_format() && src->nplanes() == 1)
01085     return vil_image_view<outP>(src);
01086 
01087   // create output view
01088   vil_image_view<outP> dest;
01089 
01090   // convert via vil_image_view<double>
01091   switch (vil_pixel_format_component_format(src->pixel_format()))
01092   {
01093 #ifndef DOXYGEN_SHOULD_SKIP_THIS
01094 #define macro( F , T ) \
01095    case F: { \
01096     vil_image_view<T > src1 = src; \
01097     vil_image_view<double> dest1; \
01098     vil_convert_planes_to_grey(src1, dest1, rw, gw, bw); \
01099     vil_convert_round(dest1,dest); \
01100     break; }
01101    macro(VIL_PIXEL_FORMAT_BYTE, vxl_byte )
01102    macro(VIL_PIXEL_FORMAT_SBYTE , vxl_sbyte )
01103 #if VXL_HAS_INT_64
01104    macro(VIL_PIXEL_FORMAT_UINT_64 , vxl_uint_64 )
01105    macro(VIL_PIXEL_FORMAT_INT_64 , vxl_int_64 )
01106 #endif
01107    macro(VIL_PIXEL_FORMAT_UINT_32 , vxl_uint_32 )
01108    macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
01109    macro(VIL_PIXEL_FORMAT_UINT_16 , vxl_uint_16 )
01110    macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
01111    macro(VIL_PIXEL_FORMAT_FLOAT , float )
01112    macro(VIL_PIXEL_FORMAT_DOUBLE , double )
01113    // Don't even want to think about rgb<complex<float> >
01114 #undef macro
01115 #endif // DOXYGEN_SHOULD_SKIP_THIS
01116    default:
01117     dest.clear();
01118   }
01119   return dest;
01120 }
01121 #endif // 0
01122 
01123 //: Create an n plane image from any image src.
01124 // This function is designed to be used with vil_load or
01125 // vil_image_resource::get_view()
01126 // where you do not know the pixel type or number of planes in advance.
01127 // If the input images have too many planes, the higher planes will be
01128 // truncated. If the input image has too few planes, the new planes will be
01129 // copies of the first plane.
01130 //
01131 // The output may be a shallow copy of the input.
01132 // The input image's storage arrangement may not be preserved.
01133 //
01134 // This function works on scalar pixel types only, however it can be used to
01135 // produce an rgb image as in the following example
01136 // \code
01137 // vil_image_view<vil_rgb<float> > =
01138 //   vil_convert_cast(
01139 //     vil_convert_to_component_order(
01140 //       vil_convert_to_n_planes(
01141 //         vil_load(filename),
01142 //       3),
01143 //     ),
01144 //   float());
01145 // \endcode
01146 inline vil_image_view_base_sptr vil_convert_to_n_planes(
01147   unsigned n_planes, const vil_image_view_base_sptr &src)
01148 {
01149   if (!src || n_planes == 0)
01150     return vil_image_view_base_sptr();
01151 
01152 
01153   switch (vil_pixel_format_component_format(src->pixel_format()))
01154   {
01155 #ifndef DOXYGEN_SHOULD_SKIP_THIS
01156  #define macro( F, T ) \
01157    case F: { \
01158     vil_image_view<T > src_ref = src; \
01159     if (!src_ref) return vil_image_view_base_sptr(); \
01160     /* try to do it quickly 1 */ \
01161     if (src_ref.nplanes() >= n_planes) /* reduce number of planes */ \
01162       return vil_image_view_base_sptr( new vil_image_view<T >( \
01163           vil_planes(vil_image_view<T > (src),0,1,n_planes) )); \
01164     else { /* expand number of planes with copying */ \
01165       vil_image_view_base_sptr dest = new vil_image_view<T >(src_ref.ni(), src_ref.nj(), n_planes); \
01166       vil_image_view<T > & dest_ref = static_cast<vil_image_view<T >&>(*dest); \
01167       vil_image_view<T > dest_slices = vil_planes(dest_ref, 0, 1, src_ref.nplanes()); \
01168       vil_copy_reformat(src_ref, dest_slices); \
01169       vil_image_view<T > src_slice(vil_plane(src_ref, 0)); \
01170       for (unsigned i=src_ref.nplanes(); i<n_planes; ++i) { \
01171         dest_slices = vil_plane(dest_ref, i); \
01172         vil_copy_reformat(src_slice,  dest_slices); } \
01173       return dest; } }
01174    macro(VIL_PIXEL_FORMAT_BYTE, vxl_byte )
01175    macro(VIL_PIXEL_FORMAT_SBYTE , vxl_sbyte )
01176 #if VXL_HAS_INT_64
01177    macro(VIL_PIXEL_FORMAT_UINT_64 , vxl_uint_64 )
01178    macro(VIL_PIXEL_FORMAT_INT_64 , vxl_int_64 )
01179 #endif
01180    macro(VIL_PIXEL_FORMAT_UINT_32 , vxl_uint_32 )
01181    macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
01182    macro(VIL_PIXEL_FORMAT_UINT_16 , vxl_uint_16 )
01183    macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
01184    macro(VIL_PIXEL_FORMAT_FLOAT , float )
01185    macro(VIL_PIXEL_FORMAT_DOUBLE , double )
01186 #undef macro
01187 #endif // DOXYGEN_SHOULD_SKIP_THIS
01188    default:
01189      vil_exception_warning(vil_exception_unsupported_pixel_format(
01190         src->pixel_format(), "vil_convert_to_n_planes") );
01191 
01192     return vil_image_view_base_sptr();
01193   }
01194 }
01195 
01196 
01197 //: Create an image of the desired type by stretching the range to fit.
01198 // This function is designed to be used with vil_load or
01199 // vil_image_resource::get_view()
01200 // where you do not know the pixel type in advance.
01201 // In the case of floating point output pixels the range is set to [0,1]
01202 // The input image's storage arrangement may not be preserved.
01203 //
01204 // This function works on scalar pixel types only. You can convert the image
01205 // to rgb using a cheap assignment afterwards.
01206 template <class outP>
01207 inline vil_image_view_base_sptr vil_convert_stretch_range(
01208   outP /*dummy*/, const vil_image_view_base_sptr &src)
01209 {
01210   // Check that input isn't trying to produce multi-component pixels
01211   assert (vil_pixel_format_num_components(vil_pixel_format_of(outP())) == 1);
01212 
01213   if (!src)
01214     return vil_image_view_base_sptr();
01215 
01216   double hi,lo;
01217 
01218   if (vcl_numeric_limits<outP>::is_integer)
01219   {
01220     hi = vcl_numeric_limits<outP>::max()+0.999;
01221     lo = vcl_numeric_limits<outP>::min();
01222   }
01223   else
01224   {
01225     hi=1.0;
01226     lo=0.0;
01227   }
01228 
01229   vil_image_view_base_sptr dest = new vil_image_view<outP>;
01230   vil_image_view<outP> & dest_ref = static_cast<vil_image_view<outP> &>(*dest);
01231   vil_image_view<double> inter;
01232   switch (vil_pixel_format_component_format(src->pixel_format()))
01233   {
01234 #ifndef DOXYGEN_SHOULD_SKIP_THIS
01235 #define macro( F , T ) \
01236    case F: { \
01237     vil_image_view<T> src_ref = src; \
01238     if (!src_ref) return vil_image_view_base_sptr(); \
01239     vil_convert_stretch_range(src_ref, inter, lo, hi); \
01240     vil_convert_cast(inter, dest_ref); \
01241     break; }
01242    macro(VIL_PIXEL_FORMAT_BYTE, vxl_byte )
01243    macro(VIL_PIXEL_FORMAT_SBYTE , vxl_sbyte )
01244 #if VXL_HAS_INT_64 && !defined(VCL_VC_6)
01245    macro(VIL_PIXEL_FORMAT_UINT_64 , vxl_uint_64 )
01246    macro(VIL_PIXEL_FORMAT_INT_64 , vxl_int_64 )
01247 #endif
01248    macro(VIL_PIXEL_FORMAT_UINT_32 , vxl_uint_32 )
01249    macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
01250    macro(VIL_PIXEL_FORMAT_UINT_16 , vxl_uint_16 )
01251    macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
01252    macro(VIL_PIXEL_FORMAT_FLOAT , float )
01253    macro(VIL_PIXEL_FORMAT_DOUBLE , double )
01254 #undef macro
01255 #endif // DOXYGEN_SHOULD_SKIP_THIS
01256   default:
01257     vil_exception_warning(vil_exception_unsupported_pixel_format(
01258       src->pixel_format(), "vil_convert_stretch_range") );
01259 
01260 
01261      dest_ref.clear();
01262   }
01263   return dest;
01264 }
01265 
01266 
01267 #endif // vil_convert_h_

Generated on Mon Nov 23 05:08:36 2009 for core/vil by  doxygen 1.5.1