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.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 
00623 //: Convert src image<inP> to dest image<vxl_byte> by stretching input range [src_lo, src_hi] to output range [0, 255].
00624 // Inputs < src_lo are mapped to 0, and inputs > src_hi to 255.
00625 template <class inP>
00626 inline void vil_convert_stretch_range_limited(const vil_image_view<inP>& src,
00627                                               vil_image_view<vxl_byte>& dest,
00628                                               const inP src_lo,
00629                                               const inP src_hi)
00630 {
00631   const double dsrc = static_cast<double>(src_hi - src_lo);
00632   const double dds = 255.0 / dsrc;
00633 
00634   dest.set_size(src.ni(), src.nj(), src.nplanes());
00635   for (unsigned p = 0; p < src.nplanes(); ++p)
00636     for (unsigned j = 0; j < src.nj(); ++j)
00637       for (unsigned i = 0; i < src.ni(); ++i)
00638       {
00639         inP s = src(i,j,p);
00640         dest(i,j,p) = s<=src_lo ? 0 :
00641                       ( s>=src_hi ? 255 :
00642                                     static_cast<vxl_byte>(dds*(s-src_lo)+0.5) );
00643       }
00644 }
00645 
00646 //: Cast the unknown pixel type to the known one.
00647 //
00648 // This function is designed to be used with vil_load or
00649 // vil_image_resource::get_view()
00650 // where you do not know the pixel type in advance.
00651 // If you need a
00652 // multi-component view, then call this to get the corresponding
00653 // multi-planar view, and do a second (cheap) conversion.
00654 // The input image's storage arrangement may not be preserved.
00655 template <class outP>
00656 inline vil_image_view_base_sptr vil_convert_cast(outP /*dummy*/,
00657                                                  const vil_image_view_base_sptr& src)
00658 {
00659   if (!src) return vil_image_view_base_sptr();
00660 
00661   vil_image_view_base_sptr dest = new vil_image_view<outP>;
00662   vil_image_view<outP> & dest_ref = static_cast<vil_image_view<outP> &>(*dest);
00663 
00664   switch ( vil_pixel_format_component_format(src->pixel_format()) )
00665   {
00666 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00667 #define macro(F , T) \
00668     case F: vil_convert_cast( vil_image_view<T >(*src), dest_ref ); break
00669 
00670 #if VXL_HAS_INT_64
00671     macro( VIL_PIXEL_FORMAT_UINT_64, vxl_uint_64 );
00672     macro( VIL_PIXEL_FORMAT_INT_64, vxl_int_64 );
00673 #endif
00674     macro( VIL_PIXEL_FORMAT_UINT_32, vxl_uint_32 );
00675     macro( VIL_PIXEL_FORMAT_INT_32, vxl_int_32 );
00676     macro( VIL_PIXEL_FORMAT_UINT_16, vxl_uint_16 );
00677     macro( VIL_PIXEL_FORMAT_INT_16, vxl_int_16 );
00678     macro( VIL_PIXEL_FORMAT_BYTE, vxl_byte );
00679     macro( VIL_PIXEL_FORMAT_SBYTE, vxl_sbyte );
00680     macro( VIL_PIXEL_FORMAT_FLOAT, float );
00681     macro( VIL_PIXEL_FORMAT_DOUBLE, double );
00682     macro( VIL_PIXEL_FORMAT_BOOL, bool );
00683 #undef macro
00684 #endif // DOXYGEN_SHOULD_SKIP_THIS
00685     default:
00686       vil_exception_warning(vil_exception_unsupported_pixel_format(
00687         src->pixel_format(), "vil_convert_cast") );
00688       dest = 0;
00689   }
00690   return dest;
00691 }
00692 
00693 #if 0 // deprecated
00694 //: Cast the unknown pixel type to the known one, if possible.
00695 //
00696 // Will call the other vil_convert_cast to do the actual
00697 // conversion. For template instantiation reasons, this will only
00698 // convert to a scalar type, not a RGB or RGBA type. If you need a
00699 // multi-component view, then call this to get the corresponding
00700 // multi-planar view, and do a second (cheap) conversion.
00701 //
00702 // \deprecated Use other vil_convert_cast()
00703 // Can be removed after VXL 1.1.1
00704 template <class outP>
00705 inline void vil_convert_cast(const vil_image_view_base_sptr& src,
00706                              vil_image_view<outP >&dest)
00707 {
00708   VXL_DEPRECATED( "void vil_convert_cast(const vil_image_view_base_sptr&,"
00709                   " vil_image_view<outP>&)" );
00710 
00711   switch ( src->pixel_format() )
00712   {
00713 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00714 #define macro(F , T) \
00715     case F: vil_convert_cast( vil_image_view<T >(src), dest ); break;
00716 
00717 #if VXL_HAS_INT_64
00718     macro( VIL_PIXEL_FORMAT_UINT_64, vxl_uint_64 )
00719     macro( VIL_PIXEL_FORMAT_INT_64, vxl_int_64 )
00720 #endif
00721     macro( VIL_PIXEL_FORMAT_UINT_32, vxl_uint_32 )
00722     macro( VIL_PIXEL_FORMAT_INT_32, vxl_int_32 )
00723     macro( VIL_PIXEL_FORMAT_UINT_16, vxl_uint_16 )
00724     macro( VIL_PIXEL_FORMAT_INT_16, vxl_int_16 )
00725     macro( VIL_PIXEL_FORMAT_BYTE, vxl_byte )
00726     macro( VIL_PIXEL_FORMAT_SBYTE, vxl_sbyte )
00727     macro( VIL_PIXEL_FORMAT_FLOAT, float )
00728     macro( VIL_PIXEL_FORMAT_DOUBLE, double )
00729     macro( VIL_PIXEL_FORMAT_BOOL, bool )
00730 #undef macro
00731 #endif // DOXYGEN_SHOULD_SKIP_THIS
00732 
00733     // Skip the RGB type conversions because the vil_convert_cast are
00734     // not complete. For example, a cast from vxl_uint_16 to
00735     // vil_rgb<vxl_uint_32> is not defined.
00736     default:
00737       dest.clear();
00738   }
00739 }
00740 #endif // 0
00741 
00742 //: Convert an image of any pixel type to another with rounding.
00743 // This should only be used to convert to scalar
00744 // pixel types. This function only rounds in terms of the
00745 // destination type.
00746 // This function is designed to be used with vil_load or
00747 // vil_image_resource::get_view()
00748 // where you do not know the pixel type in advance.
00749 //
00750 // If the input image already has outP as its pixel type, the destination
00751 // may only be a shallow copy of the source.
00752 // outP should be a scalar pixel type.
00753 // The input image's storage arrangement may not be preserved.
00754 template <class outP>
00755 inline vil_image_view_base_sptr vil_convert_round(
00756   outP /*dummy*/, const vil_image_view_base_sptr &src)
00757 {
00758   assert(vil_pixel_format_num_components(vil_pixel_format_of(outP()))==1);
00759 
00760   if (!src) return vil_image_view_base_sptr();
00761 
00762   if (vil_pixel_format_component_format(src->pixel_format()) ==
00763       vil_pixel_format_of(outP()))
00764     return src;
00765 
00766   vil_image_view_base_sptr dest = new vil_image_view<outP >;
00767   vil_image_view<outP > &dest_ref = static_cast<vil_image_view<outP >&>(*dest);
00768 
00769   switch (vil_pixel_format_component_format(src->pixel_format()))
00770   {
00771 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00772 #define macro( F , T ) \
00773    case F: { \
00774     vil_image_view<T > src1 = src; \
00775     vil_transform2(src1, dest_ref, vil_convert_round_pixel<T , outP>()); \
00776     break; }
00777 macro(VIL_PIXEL_FORMAT_BYTE, vxl_byte )
00778 macro(VIL_PIXEL_FORMAT_SBYTE , vxl_sbyte )
00779 #if VXL_HAS_INT_64
00780 macro(VIL_PIXEL_FORMAT_UINT_64 , vxl_uint_64 )
00781 macro(VIL_PIXEL_FORMAT_INT_64 , vxl_int_64 )
00782 #endif
00783 macro(VIL_PIXEL_FORMAT_UINT_32 , vxl_uint_32 )
00784 macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
00785 macro(VIL_PIXEL_FORMAT_UINT_16 , vxl_uint_16 )
00786 macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
00787 macro(VIL_PIXEL_FORMAT_FLOAT , float )
00788 macro(VIL_PIXEL_FORMAT_DOUBLE , double )
00789 #undef macro
00790 #endif // DOXYGEN_SHOULD_SKIP_THIS
00791   default:
00792     vil_exception_warning(vil_exception_unsupported_pixel_format(
00793       src->pixel_format(), "vil_convert_round") );    
00794     dest=0;
00795   }
00796   return dest;
00797 }
00798 
00799 
00800 //: Force data to be suitable for viewing as multi component view.
00801 // The output data will have values from different planes but the same
00802 // pixel location stored in adjacent memory locations. After using this
00803 // function on an input with 3 planes, an assignment to a
00804 // vil_image_view<vil_rgb<T> > will always work.
00805 // The input image's scalar pixel type will be preserved.
00806 inline vil_image_view_base_sptr vil_convert_to_component_order(
00807   const vil_image_view_base_sptr& src)
00808 {
00809   if (!src) return vil_image_view_base_sptr();
00810 
00811   vil_image_view_base_sptr dest;
00812 
00813   switch (vil_pixel_format_component_format(src->pixel_format()))
00814   {
00815 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00816 #define macro( F , T )\
00817    case F: { \
00818     vil_image_view<T > src_ref(src); \
00819     if (!src_ref) return vil_image_view_base_sptr(); \
00820     if (src_ref.planestep()==1) return src; \
00821     const unsigned ni=src->ni(), nj=src->nj(), nplanes=src->nplanes(); \
00822     vil_memory_chunk_sptr chunk = new vil_memory_chunk(ni*nj*nplanes*sizeof(T), \
00823                                                        vil_pixel_format_component_format(F)); \
00824     dest = new vil_image_view<T >(chunk, reinterpret_cast<T*>(chunk->data()), \
00825                                   ni, nj, nplanes, nplanes, nplanes*ni, 1); \
00826     vil_image_view<T > & dest_ref = static_cast<vil_image_view<T >&>(*dest); \
00827     vil_copy_reformat(src_ref, dest_ref); \
00828     break; }
00829 macro(VIL_PIXEL_FORMAT_BYTE, vxl_byte )
00830 macro(VIL_PIXEL_FORMAT_SBYTE , vxl_sbyte )
00831 #if VXL_HAS_INT_64
00832 macro(VIL_PIXEL_FORMAT_UINT_64 , vxl_uint_64 )
00833 macro(VIL_PIXEL_FORMAT_INT_64 , vxl_int_64 )
00834 #endif
00835 macro(VIL_PIXEL_FORMAT_UINT_32 , vxl_uint_32 )
00836 macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
00837 macro(VIL_PIXEL_FORMAT_UINT_16 , vxl_uint_16 )
00838 macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
00839 macro(VIL_PIXEL_FORMAT_FLOAT , float )
00840 macro(VIL_PIXEL_FORMAT_DOUBLE , double )
00841 #undef macro
00842 #endif // DOXYGEN_SHOULD_SKIP_THIS
00843 
00844     default:
00845       vil_exception_warning(vil_exception_unsupported_pixel_format(
00846         src->pixel_format(), "vil_convert_to_compound_order") );
00847       dest=0;
00848   }
00849   return dest;
00850 }
00851 
00852 #if 0 // deprecated
00853 //: Create a greyscale image from any image src.
00854 // This function is designed to be used with vil_load or
00855 // vil_image_resource::get_view()
00856 // where you do not know the pixel type in advance. e.g.
00857 // \verbatim
00858 // vil_image_view<float> input =
00859 //   vil_convert_to_grey_using_average(vil_load(filename), float());
00860 // \endverbatim
00861 // If you have a image_view of known pixel_type then you should use one of
00862 // the other vil_convert functions.
00863 // The output may be a reconfigured view of the input.
00864 // \deprecated Use other vil_convert_to_grey_using_average()
00865 template <class outP>
00866 inline vil_image_view<outP> vil_convert_to_grey_using_average(
00867   const vil_image_view_base_sptr &src, outP /*dummy*/)
00868 {
00869   VXL_DEPRECATED( "vil_convert_to_grey_using_average<outP>("
00870                   "const vil_image_view_base_sptr &, outP)" );
00871 
00872   // Check output is scalar component image.
00873   assert (vil_pixel_format_num_components(vil_pixel_format_of(outP())) == 1);
00874 
00875   if (!src) return vil_image_view<outP>();
00876 
00877   // try to do it quickly
00878   if (vil_pixel_format_of(outP()) == src->pixel_format() && src->nplanes() == 1)
00879     return vil_image_view<outP>(src);
00880 
00881   // create output view
00882   vil_image_view<outP> dest;
00883 
00884   // convert via vil_image_view<double>
00885   switch (vil_pixel_format_component_format(src->pixel_format()))
00886   {
00887 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00888 #define macro( F , T ) \
00889    case F: { \
00890     vil_image_view<T > src1 = *src; \
00891     vil_math_mean_over_planes(src1, dest, double()); \
00892     break; }
00893    macro(VIL_PIXEL_FORMAT_BYTE, vxl_byte )
00894    macro(VIL_PIXEL_FORMAT_SBYTE , vxl_sbyte )
00895 #if VXL_HAS_INT_64
00896    macro(VIL_PIXEL_FORMAT_UINT_64 , vxl_uint_64 )
00897    macro(VIL_PIXEL_FORMAT_INT_64 , vxl_int_64 )
00898 #endif
00899    macro(VIL_PIXEL_FORMAT_UINT_32 , vxl_uint_32 )
00900    macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
00901    macro(VIL_PIXEL_FORMAT_UINT_16 , vxl_uint_16 )
00902    macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
00903    macro(VIL_PIXEL_FORMAT_FLOAT , float )
00904    macro(VIL_PIXEL_FORMAT_DOUBLE , double )
00905 #undef macro
00906 #endif // DOXYGEN_SHOULD_SKIP_THIS
00907    default:
00908     dest.clear();
00909   }
00910   return dest;
00911 }
00912 #endif // 0
00913 
00914 //: Create a greyscale image of specified pixel type from any image src.
00915 // This function is designed to be used with vil_load or
00916 // vil_image_resource::get_view()
00917 // where you do not know the pixel type in advance. e.g.
00918 // \verbatim
00919 // vil_image_view<float> input = vil_convert_cast(
00920 //   convert_to_grey_using_average(vil_load(filename)), float());
00921 // \endverbatim
00922 // The output may be a reconfigured view of the input.
00923 // The input image's pixel type and storage arrangement may not be preserved.
00924 inline vil_image_view_base_sptr vil_convert_to_grey_using_average(
00925   const vil_image_view_base_sptr &src)
00926 {
00927   if (!src) return vil_image_view_base_sptr();
00928 
00929   // convert via vil_image_view<double>
00930   switch (vil_pixel_format_component_format(src->pixel_format()))
00931   {
00932 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00933 #define macro( F , T ) \
00934   case F: { \
00935     /* try to do it quickly */ \
00936     if (src->nplanes() == 1 && \
00937         vil_pixel_format_component_format(src->pixel_format())==1) \
00938       return src; \
00939     /* create output view */ \
00940     vil_image_view<T > dest; \
00941     vil_image_view<T > src1 = *src; \
00942     vil_math_mean_over_planes(src1, dest, double()); \
00943     return vil_image_view_base_sptr(new vil_image_view<T >(dest)); }
00944   macro(VIL_PIXEL_FORMAT_BYTE, vxl_byte )
00945   macro(VIL_PIXEL_FORMAT_SBYTE , vxl_sbyte )
00946 #if VXL_HAS_INT_64 && !defined(VCL_VC_6)
00947   macro(VIL_PIXEL_FORMAT_UINT_64 , vxl_uint_64 )
00948   macro(VIL_PIXEL_FORMAT_INT_64 , vxl_int_64 )
00949 #endif
00950   macro(VIL_PIXEL_FORMAT_UINT_32 , vxl_uint_32 )
00951   macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
00952   macro(VIL_PIXEL_FORMAT_UINT_16 , vxl_uint_16 )
00953   macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
00954   macro(VIL_PIXEL_FORMAT_FLOAT , float )
00955   macro(VIL_PIXEL_FORMAT_DOUBLE , double )
00956 #undef macro
00957 #endif // DOXYGEN_SHOULD_SKIP_THIS
00958   default:
00959     vil_exception_warning(vil_exception_unsupported_pixel_format(
00960       src->pixel_format(), "vil_convert_to_grey_using_average") );
00961     return 0;
00962   }
00963 }
00964 
00965 
00966 //: Create a greyscale image from any image src.
00967 // This function is designed to be used with vil_load or
00968 // vil_image_resource::get_view()
00969 // where you do not know the pixel type in advance.
00970 // The output may be a reconfigured view of the input.
00971 // The input image's pixel type and storage arrangement may not be preserved.
00972 inline vil_image_view_base_sptr vil_convert_to_grey_using_rgb_weighting(
00973   double rw, double gw, double bw, const vil_image_view_base_sptr &src)
00974 {
00975   if (!src)
00976     return vil_image_view_base_sptr();
00977 
00978   // convert via vil_image_view<double>
00979   switch (vil_pixel_format_component_format(src->pixel_format()))
00980   {
00981 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00982 #define macro( F , T ) \
00983   case F: { \
00984     /* try to do it quickly */ \
00985     if (src->nplanes() == 1 && \
00986         vil_pixel_format_num_components(src->pixel_format()) == 1) \
00987       return vil_image_view_base_sptr(src); \
00988     vil_image_view<T > src1 = src; \
00989     vil_image_view<double> dest1; \
00990     vil_convert_planes_to_grey(src1, dest1, rw, gw, bw); \
00991     vil_image_view<T > dest; \
00992     vil_convert_round(dest1,dest); \
00993     return vil_image_view_base_sptr(new vil_image_view<T >(dest)); }
00994   macro(VIL_PIXEL_FORMAT_BYTE, vxl_byte )
00995   macro(VIL_PIXEL_FORMAT_SBYTE , vxl_sbyte )
00996 #if VXL_HAS_INT_64 && !defined(VCL_VC_6)
00997   macro(VIL_PIXEL_FORMAT_UINT_64 , vxl_uint_64 )
00998   macro(VIL_PIXEL_FORMAT_INT_64 , vxl_int_64 )
00999 #endif
01000   macro(VIL_PIXEL_FORMAT_UINT_32 , vxl_uint_32 )
01001   macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
01002   macro(VIL_PIXEL_FORMAT_UINT_16 , vxl_uint_16 )
01003   macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
01004   macro(VIL_PIXEL_FORMAT_FLOAT , float )
01005   macro(VIL_PIXEL_FORMAT_DOUBLE , double )
01006 #undef macro
01007 #endif // DOXYGEN_SHOULD_SKIP_THIS
01008   default:
01009       vil_exception_warning(vil_exception_unsupported_pixel_format(
01010         src->pixel_format(), "vil_convert_to_grey_using_rgb_weighting") );
01011     return vil_image_view_base_sptr();
01012   }
01013 }
01014 
01015 //: Create a greyscale image from any image src using default weights.
01016 // This function is designed to be used with vil_load or
01017 // vil_image_resource::get_view()
01018 // where you do not know the pixel type in advance.
01019 // The output may be a reconfigured view of the input.
01020 // The input image's pixel type and storage arrangement may not be preserved.
01021 //
01022 // Default weights convert from linear RGB to CIE luminance assuming a
01023 // modern monitor.  See Charles Poynton's Colour FAQ
01024 // http://www.poynton.com/ColorFAQ.html
01025 
01026 inline vil_image_view_base_sptr vil_convert_to_grey_using_rgb_weighting(
01027   const vil_image_view_base_sptr &src)
01028 {
01029   return vil_convert_to_grey_using_rgb_weighting(0.2125, 0.7154, 0.0721, src);
01030 }
01031 
01032 #if 0 // deprecated version of this function now commented out
01033 //: Create a greyscale image of specified pixel type from any image src.
01034 // This function is designed to be used with vil_load or
01035 // vil_image_resource::get_view()
01036 // where you do not know the pixel type in advance.
01037 // The output may be a reconfigured view of the input.
01038 //
01039 // Default weights convert from linear RGB to CIE luminance assuming a
01040 // modern monitor.  See Charles Poynton's Colour FAQ
01041 // http://www.poynton.com/ColorFAQ.html
01042 // \deprecated Use other version of vil_convert_to_grey_using_rgb_weighting
01043 template <class outP>
01044 inline vil_image_view<outP> vil_convert_to_grey_using_rgb_weighting(
01045                           const vil_image_view_base_sptr &src,
01046                           outP /*dummy*/,
01047                           double rw=0.2125,
01048                           double gw=0.7154,
01049                           double bw=0.0721)
01050 {
01051   VXL_DEPRECATED( "vil_convert_to_grey_using_rgb_weighting<outP>("
01052                   "const vil_image_view_base_sptr &, outP)" );
01053 
01054   // Check output is scalar component image.
01055   assert (vil_pixel_format_num_components(vil_pixel_format_of(outP())) == 1);
01056 
01057   if (!src) return vil_image_view<outP>();
01058 
01059   // try to do it quickly
01060   if (vil_pixel_format_of(outP()) == src->pixel_format() && src->nplanes() == 1)
01061     return vil_image_view<outP>(src);
01062 
01063   // create output view
01064   vil_image_view<outP> dest;
01065 
01066   // convert via vil_image_view<double>
01067   switch (vil_pixel_format_component_format(src->pixel_format()))
01068   {
01069 #ifndef DOXYGEN_SHOULD_SKIP_THIS
01070 #define macro( F , T ) \
01071    case F: { \
01072     vil_image_view<T > src1 = src; \
01073     vil_image_view<double> dest1; \
01074     vil_convert_planes_to_grey(src1, dest1, rw, gw, bw); \
01075     vil_convert_round(dest1,dest); \
01076     break; }
01077    macro(VIL_PIXEL_FORMAT_BYTE, vxl_byte )
01078    macro(VIL_PIXEL_FORMAT_SBYTE , vxl_sbyte )
01079 #if VXL_HAS_INT_64
01080    macro(VIL_PIXEL_FORMAT_UINT_64 , vxl_uint_64 )
01081    macro(VIL_PIXEL_FORMAT_INT_64 , vxl_int_64 )
01082 #endif
01083    macro(VIL_PIXEL_FORMAT_UINT_32 , vxl_uint_32 )
01084    macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
01085    macro(VIL_PIXEL_FORMAT_UINT_16 , vxl_uint_16 )
01086    macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
01087    macro(VIL_PIXEL_FORMAT_FLOAT , float )
01088    macro(VIL_PIXEL_FORMAT_DOUBLE , double )
01089    // Don't even want to think about rgb<complex<float> >
01090 #undef macro
01091 #endif // DOXYGEN_SHOULD_SKIP_THIS
01092    default:
01093     dest.clear();
01094   }
01