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.
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 // \relatesalso 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 // \relatesalso 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 // \relatesalso 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 Poynton'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 // \relatesalso 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<ushort> 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<unsigned short>& dest,
00627                                               const inP src_lo,
00628                                               const inP src_hi,
00629                                               const unsigned short dest_lo,
00630                                               const unsigned short 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<unsigned short>(dest_lo + dds*(s-src_lo)+0.5);
00645       }
00646 }
00647 
00648 //: Convert src image<inP> to dest image<ubyte> by stretching input range [src_lo, src_hi] to output range [dest_lo, dest_hi].
00649 // Inputs < src_lo are mapped to dest_lo, and inputs > src_hi to dest_hi.
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                                               const vxl_byte dest_lo,
00656                                               const vxl_byte dest_hi)
00657 {
00658   const double ddest = dest_hi - dest_lo;
00659   const double dsrc = static_cast<double>(src_hi - src_lo);
00660   const double dds = ddest / dsrc;
00661 
00662   dest.set_size(src.ni(), src.nj(), src.nplanes());
00663   for (unsigned p = 0; p < src.nplanes(); ++p)
00664     for (unsigned j = 0; j < src.nj(); ++j)
00665       for (unsigned i = 0; i < src.ni(); ++i)
00666       {
00667         inP s = src(i,j,p);
00668         dest(i,j,p) = s<=src_lo ? dest_lo :
00669                       s>=src_hi ? dest_hi :
00670                                   static_cast<vxl_byte>(dest_lo + dds*(s-src_lo)+0.5);
00671       }
00672 }
00673 
00674 //: Convert src image<inP> to dest image<vxl_byte> by stretching input range [src_lo, src_hi] to output range [0, 255].
00675 // Inputs < src_lo are mapped to 0, and inputs > src_hi to 255.
00676 template <class inP>
00677 inline void vil_convert_stretch_range_limited(const vil_image_view<inP>& src,
00678                                               vil_image_view<vxl_byte>& dest,
00679                                               const inP src_lo,
00680                                               const inP src_hi)
00681 {
00682   const double dsrc = static_cast<double>(src_hi - src_lo);
00683   const double dds = 255.0 / dsrc;
00684 
00685   dest.set_size(src.ni(), src.nj(), src.nplanes());
00686   for (unsigned p = 0; p < src.nplanes(); ++p)
00687     for (unsigned j = 0; j < src.nj(); ++j)
00688       for (unsigned i = 0; i < src.ni(); ++i)
00689       {
00690         inP s = src(i,j,p);
00691         dest(i,j,p) = s<=src_lo ? 0 :
00692                       static_cast<vxl_byte>( s>=src_hi ? 255 : (dds*(s-src_lo)+0.5) );
00693       }
00694 }
00695 
00696 //: Cast the unknown pixel type to the known one.
00697 //
00698 // This function is designed to be used with vil_load or
00699 // vil_image_resource::get_view()
00700 // where you do not know the pixel type in advance.
00701 // If you need a
00702 // multi-component view, then call this to get the corresponding
00703 // multi-planar view, and do a second (cheap) conversion.
00704 // The input image's storage arrangement may not be preserved.
00705 template <class outP>
00706 inline vil_image_view_base_sptr vil_convert_cast(outP /*dummy*/,
00707                                                  const vil_image_view_base_sptr& src)
00708 {
00709   if (!src) return vil_image_view_base_sptr();
00710 
00711   vil_image_view_base_sptr dest = new vil_image_view<outP>;
00712   vil_image_view<outP> & dest_ref = static_cast<vil_image_view<outP> &>(*dest);
00713 
00714   switch ( vil_pixel_format_component_format(src->pixel_format()) )
00715   {
00716 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00717 #define macro(F , T) \
00718     case F: vil_convert_cast( vil_image_view<T >(*src), dest_ref ); break
00719 
00720 #if VXL_HAS_INT_64
00721     macro( VIL_PIXEL_FORMAT_UINT_64, vxl_uint_64 );
00722     macro( VIL_PIXEL_FORMAT_INT_64, vxl_int_64 );
00723 #endif
00724     macro( VIL_PIXEL_FORMAT_UINT_32, vxl_uint_32 );
00725     macro( VIL_PIXEL_FORMAT_INT_32, vxl_int_32 );
00726     macro( VIL_PIXEL_FORMAT_UINT_16, vxl_uint_16 );
00727     macro( VIL_PIXEL_FORMAT_INT_16, vxl_int_16 );
00728     macro( VIL_PIXEL_FORMAT_BYTE, vxl_byte );
00729     macro( VIL_PIXEL_FORMAT_SBYTE, vxl_sbyte );
00730     macro( VIL_PIXEL_FORMAT_FLOAT, float );
00731     macro( VIL_PIXEL_FORMAT_DOUBLE, double );
00732     macro( VIL_PIXEL_FORMAT_BOOL, bool );
00733 #undef macro
00734 #endif // DOXYGEN_SHOULD_SKIP_THIS
00735     default:
00736       vil_exception_warning(vil_exception_unsupported_pixel_format(
00737         src->pixel_format(), "vil_convert_cast") );
00738       dest = 0;
00739   }
00740   return dest;
00741 }
00742 
00743 #if 0 // deprecated
00744 //: Cast the unknown pixel type to the known one, if possible.
00745 //
00746 // Will call the other vil_convert_cast to do the actual
00747 // conversion. For template instantiation reasons, this will only
00748 // convert to a scalar type, not a RGB or RGBA type. If you need a
00749 // multi-component view, then call this to get the corresponding
00750 // multi-planar view, and do a second (cheap) conversion.
00751 //
00752 // \deprecated Use other vil_convert_cast()
00753 // Can be removed after VXL 1.1.1
00754 template <class outP>
00755 inline void vil_convert_cast(const vil_image_view_base_sptr& src,
00756                              vil_image_view<outP >&dest)
00757 {
00758   VXL_DEPRECATED( "void vil_convert_cast(const vil_image_view_base_sptr&,"
00759                   " vil_image_view<outP>&)" );
00760 
00761   switch ( src->pixel_format() )
00762   {
00763 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00764 #define macro(F , T) \
00765     case F: vil_convert_cast( vil_image_view<T >(src), dest ); break;
00766 
00767 #if VXL_HAS_INT_64
00768     macro( VIL_PIXEL_FORMAT_UINT_64, vxl_uint_64 )
00769     macro( VIL_PIXEL_FORMAT_INT_64, vxl_int_64 )
00770 #endif
00771     macro( VIL_PIXEL_FORMAT_UINT_32, vxl_uint_32 )
00772     macro( VIL_PIXEL_FORMAT_INT_32, vxl_int_32 )
00773     macro( VIL_PIXEL_FORMAT_UINT_16, vxl_uint_16 )
00774     macro( VIL_PIXEL_FORMAT_INT_16, vxl_int_16 )
00775     macro( VIL_PIXEL_FORMAT_BYTE, vxl_byte )
00776     macro( VIL_PIXEL_FORMAT_SBYTE, vxl_sbyte )
00777     macro( VIL_PIXEL_FORMAT_FLOAT, float )
00778     macro( VIL_PIXEL_FORMAT_DOUBLE, double )
00779     macro( VIL_PIXEL_FORMAT_BOOL, bool )
00780 #undef macro
00781 #endif // DOXYGEN_SHOULD_SKIP_THIS
00782 
00783     // Skip the RGB type conversions because the vil_convert_cast are
00784     // not complete. For example, a cast from vxl_uint_16 to
00785     // vil_rgb<vxl_uint_32> is not defined.
00786     default:
00787       dest.clear();
00788   }
00789 }
00790 #endif // 0
00791 
00792 //: Convert an image of any pixel type to another with rounding.
00793 // This should only be used to convert to scalar
00794 // pixel types. This function only rounds in terms of the
00795 // destination type.
00796 // This function is designed to be used with vil_load or
00797 // vil_image_resource::get_view()
00798 // where you do not know the pixel type in advance.
00799 //
00800 // If the input image already has outP as its pixel type, the destination
00801 // may only be a shallow copy of the source.
00802 // outP should be a scalar pixel type.
00803 // The input image's storage arrangement may not be preserved.
00804 template <class outP>
00805 inline vil_image_view_base_sptr vil_convert_round(
00806   outP /*dummy*/, const vil_image_view_base_sptr &src)
00807 {
00808   assert(vil_pixel_format_num_components(vil_pixel_format_of(outP()))==1);
00809 
00810   if (!src) return vil_image_view_base_sptr();
00811 
00812   if (vil_pixel_format_component_format(src->pixel_format()) ==
00813       vil_pixel_format_of(outP()))
00814     return src;
00815 
00816   vil_image_view_base_sptr dest = new vil_image_view<outP >;
00817   vil_image_view<outP > &dest_ref = static_cast<vil_image_view<outP >&>(*dest);
00818 
00819   switch (vil_pixel_format_component_format(src->pixel_format()))
00820   {
00821 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00822 #define macro( F , T ) \
00823    case F: { \
00824     vil_image_view<T > src1 = src; \
00825     vil_transform2(src1, dest_ref, vil_convert_round_pixel<T , outP>()); \
00826     break; }
00827 macro(VIL_PIXEL_FORMAT_BYTE, vxl_byte )
00828 macro(VIL_PIXEL_FORMAT_SBYTE , vxl_sbyte )
00829 #if VXL_HAS_INT_64
00830 macro(VIL_PIXEL_FORMAT_UINT_64 , vxl_uint_64 )
00831 macro(VIL_PIXEL_FORMAT_INT_64 , vxl_int_64 )
00832 #endif
00833 macro(VIL_PIXEL_FORMAT_UINT_32 , vxl_uint_32 )
00834 macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
00835 macro(VIL_PIXEL_FORMAT_UINT_16 , vxl_uint_16 )
00836 macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
00837 macro(VIL_PIXEL_FORMAT_FLOAT , float )
00838 macro(VIL_PIXEL_FORMAT_DOUBLE , double )
00839 #undef macro
00840 #endif // DOXYGEN_SHOULD_SKIP_THIS
00841   default:
00842     vil_exception_warning(vil_exception_unsupported_pixel_format(
00843       src->pixel_format(), "vil_convert_round") );
00844     dest=0;
00845   }
00846   return dest;
00847 }
00848 
00849 
00850 //: Force data to be suitable for viewing as multi component view.
00851 // The output data will have values from different planes but the same
00852 // pixel location stored in adjacent memory locations. After using this
00853 // function on an input with 3 planes, an assignment to a
00854 // vil_image_view<vil_rgb<T> > will always work.
00855 // The input image's scalar pixel type will be preserved.
00856 inline vil_image_view_base_sptr vil_convert_to_component_order(
00857   const vil_image_view_base_sptr& src)
00858 {
00859   if (!src) return vil_image_view_base_sptr();
00860 
00861   vil_image_view_base_sptr dest;
00862 
00863   switch (vil_pixel_format_component_format(src->pixel_format()))
00864   {
00865 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00866 #define macro( F , T )\
00867    case F: { \
00868     vil_image_view<T > src_ref(src); \
00869     if (!src_ref) return vil_image_view_base_sptr(); \
00870     if (src_ref.planestep()==1) return src; \
00871     const unsigned ni=src->ni(), nj=src->nj(), nplanes=src->nplanes(); \
00872     vil_memory_chunk_sptr chunk = new vil_memory_chunk(ni*nj*nplanes*sizeof(T), \
00873                                                        vil_pixel_format_component_format(F)); \
00874     dest = new vil_image_view<T >(chunk, reinterpret_cast<T*>(chunk->data()), \
00875                                   ni, nj, nplanes, nplanes, nplanes*ni, 1); \
00876     vil_image_view<T > & dest_ref = static_cast<vil_image_view<T >&>(*dest); \
00877     vil_copy_reformat(src_ref, dest_ref); \
00878     break; }
00879 macro(VIL_PIXEL_FORMAT_BYTE, vxl_byte )
00880 macro(VIL_PIXEL_FORMAT_SBYTE , vxl_sbyte )
00881 #if VXL_HAS_INT_64
00882 macro(VIL_PIXEL_FORMAT_UINT_64 , vxl_uint_64 )
00883 macro(VIL_PIXEL_FORMAT_INT_64 , vxl_int_64 )
00884 #endif
00885 macro(VIL_PIXEL_FORMAT_UINT_32 , vxl_uint_32 )
00886 macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
00887 macro(VIL_PIXEL_FORMAT_UINT_16 , vxl_uint_16 )
00888 macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
00889 macro(VIL_PIXEL_FORMAT_FLOAT , float )
00890 macro(VIL_PIXEL_FORMAT_DOUBLE , double )
00891 #undef macro
00892 #endif // DOXYGEN_SHOULD_SKIP_THIS
00893 
00894     default:
00895       vil_exception_warning(vil_exception_unsupported_pixel_format(
00896         src->pixel_format(), "vil_convert_to_compound_order") );
00897       dest=0;
00898   }
00899   return dest;
00900 }
00901 
00902 #if 0 // deprecated
00903 //: Create a greyscale image from any image src.
00904 // This function is designed to be used with vil_load or
00905 // vil_image_resource::get_view()
00906 // where you do not know the pixel type in advance. e.g.
00907 // \code
00908 // vil_image_view<float> input =
00909 //   vil_convert_to_grey_using_average(vil_load(filename), float());
00910 // \endcode
00911 // If you have an image_view of known pixel_type then you should use one of
00912 // the other vil_convert functions.
00913 // The output may be a reconfigured view of the input.
00914 // \deprecated Use other vil_convert_to_grey_using_average()
00915 template <class outP>
00916 inline vil_image_view<outP> vil_convert_to_grey_using_average(
00917   const vil_image_view_base_sptr &src, outP /*dummy*/)
00918 {
00919   VXL_DEPRECATED( "vil_convert_to_grey_using_average<outP>("
00920                   "const vil_image_view_base_sptr &, outP)" );
00921 
00922   // Check output is scalar component image.
00923   assert (vil_pixel_format_num_components(vil_pixel_format_of(outP())) == 1);
00924 
00925   if (!src) return vil_image_view<outP>();
00926 
00927   // try to do it quickly
00928   if (vil_pixel_format_of(outP()) == src->pixel_format() && src->nplanes() == 1)
00929     return vil_image_view<outP>(src);
00930 
00931   // create output view
00932   vil_image_view<outP> dest;
00933 
00934   // convert via vil_image_view<double>
00935   switch (vil_pixel_format_component_format(src->pixel_format()))
00936   {
00937 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00938 #define macro( F , T ) \
00939    case F: { \
00940     vil_image_view<T > src1 = *src; \
00941     vil_math_mean_over_planes(src1, dest, double()); \
00942     break; }
00943    macro(VIL_PIXEL_FORMAT_BYTE, vxl_byte )
00944    macro(VIL_PIXEL_FORMAT_SBYTE , vxl_sbyte )
00945 #if VXL_HAS_INT_64
00946    macro(VIL_PIXEL_FORMAT_UINT_64 , vxl_uint_64 )
00947    macro(VIL_PIXEL_FORMAT_INT_64 , vxl_int_64 )
00948 #endif
00949    macro(VIL_PIXEL_FORMAT_UINT_32 , vxl_uint_32 )
00950    macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
00951    macro(VIL_PIXEL_FORMAT_UINT_16 , vxl_uint_16 )
00952    macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
00953    macro(VIL_PIXEL_FORMAT_FLOAT , float )
00954    macro(VIL_PIXEL_FORMAT_DOUBLE , double )
00955 #undef macro
00956 #endif // DOXYGEN_SHOULD_SKIP_THIS
00957    default:
00958     dest.clear();
00959   }
00960   return dest;
00961 }
00962 #endif // 0
00963 
00964 //: Create a greyscale image of specified pixel type from any image src.
00965 // This function is designed to be used with vil_load or
00966 // vil_image_resource::get_view()
00967 // where you do not know the pixel type in advance. e.g.
00968 // \code
00969 // vil_image_view<float> input = vil_convert_cast(
00970 //   convert_to_grey_using_average(vil_load(filename)), float());
00971 // \endcode
00972 // The output may be a reconfigured view of the input.
00973 // The input image's pixel type and storage arrangement may not be preserved.
00974 inline vil_image_view_base_sptr vil_convert_to_grey_using_average(
00975   const vil_image_view_base_sptr &src)
00976 {
00977   if (!src) return vil_image_view_base_sptr();
00978 
00979   // convert via vil_image_view<double>
00980   switch (vil_pixel_format_component_format(src->pixel_format()))
00981   {
00982 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00983 #define macro( F , T ) \
00984   case F: { \
00985     /* try to do it quickly */ \
00986     if (src->nplanes() == 1 && \
00987         vil_pixel_format_component_format(src->pixel_format())==1) \
00988       return src; \
00989     /* create output view */ \
00990     vil_image_view<T > dest; \
00991     vil_image_view<T > src1 = *src; \
00992     vil_math_mean_over_planes(src1, dest, double()); \
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_average") );
01011     return 0;
01012   }
01013 }
01014 
01015 
01016 //: Create a greyscale image from any image src.
01017 // This function is designed to be used with vil_load or
01018 // vil_image_resource::get_view()
01019 // where you do not know the pixel type in advance.
01020 // The output may be a reconfigured view of the input.
01021 // The input image's pixel type and storage arrangement may not be preserved.
01022 inline vil_image_view_base_sptr vil_convert_to_grey_using_rgb_weighting(
01023   double rw, double gw, double bw, const vil_image_view_base_sptr &src)
01024 {
01025   if (!src)
01026     return vil_image_view_base_sptr();
01027 
01028   // convert via vil_image_view<double>
01029   switch (vil_pixel_format_component_format(src->pixel_format()))
01030   {
01031 #ifndef DOXYGEN_SHOULD_SKIP_THIS
01032 #define macro( F , T ) \
01033   case F: { \
01034     /* try to do it quickly */ \
01035     if (src->nplanes() == 1 && \
01036         vil_pixel_format_num_components(src->pixel_format()) == 1) \
01037       return vil_image_view_base_sptr(src); \
01038     vil_image_view<T > src1 = src; \
01039     vil_image_view<double> dest1; \
01040     vil_convert_planes_to_grey(src1, dest1, rw, gw, bw); \
01041     vil_image_view<T > dest; \
01042     vil_convert_round(dest1,dest); \
01043     return vil_image_view_base_sptr(new vil_image_view<T >(dest)); }
01044   macro(VIL_PIXEL_FORMAT_BYTE, vxl_byte )
01045   macro(VIL_PIXEL_FORMAT_SBYTE , vxl_sbyte )
01046 #if VXL_HAS_INT_64 && !defined(VCL_VC_6)
01047   macro(VIL_PIXEL_FORMAT_UINT_64 , vxl_uint_64 )
01048   macro(VIL_PIXEL_FORMAT_INT_64 , vxl_int_64 )
01049 #endif
01050   macro(VIL_PIXEL_FORMAT_UINT_32 , vxl_uint_32 )
01051   macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
01052   macro(VIL_PIXEL_FORMAT_UINT_16 , vxl_uint_16 )
01053   macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
01054   macro(VIL_PIXEL_FORMAT_FLOAT , float )
01055   macro(VIL_PIXEL_FORMAT_DOUBLE , double )
01056 #undef macro
01057 #endif // DOXYGEN_SHOULD_SKIP_THIS
01058   default:
01059       vil_exception_warning(vil_exception_unsupported_pixel_format(
01060         src->pixel_format(), "vil_convert_to_grey_using_rgb_weighting") );
01061     return vil_image_view_base_sptr();
01062   }
01063 }
01064 
01065 //: Create a greyscale image from any image src using default weights.
01066 // This function is designed to be used with vil_load or
01067 // vil_image_resource::get_view()
01068 // where you do not know the pixel type in advance.
01069 // The output may be a reconfigured view of the input.
01070 // The input image's pixel type and storage arrangement may not be preserved.
01071 //
01072 // Default weights convert from linear RGB to CIE luminance assuming a
01073 // modern monitor.  See Charles Poynton's Colour FAQ
01074 // http://www.poynton.com/ColorFAQ.html
01075 
01076 inline vil_image_view_base_sptr vil_convert_to_grey_using_rgb_weighting(
01077   const vil_image_view_base_sptr &src)
01078 {
01079   return vil_convert_to_grey_using_rgb_weighting(0.2125, 0.7154, 0.0721, src);
01080 }
01081 
01082 #if 0 // deprecated version of this function now commented out
01083 //: Create a greyscale image of specified pixel type from any image src.
01084 // This function is designed to be used with vil_load or
01085 // vil_image_resource::get_view()
01086 // where you do not know the pixel type in advance.
01087 // The output may be a reconfigured view of the input.
01088 //
01089 // Default weights convert from linear RGB to CIE luminance assuming a
01090 // modern monitor.  See Charles Poynton's Colour FAQ
01091 // http://www.poynton.com/ColorFAQ.html
01092 // \deprecated Use other version of vil_convert_to_grey_using_rgb_weighting
01093 template <class outP>
01094 inline vil_image_view<outP> vil_convert_to_grey_using_rgb_weighting(
01095                           const vil_image_view_base_sptr &src,
01096                           outP /*dummy*/,
01097                           double rw=0.2125,
01098                           double gw=0.7154,
01099                           double bw=0.0721)
01100 {
01101   VXL_DEPRECATED( "vil_convert_to_grey_using_rgb_weighting<outP>("
01102                   "const vil_image_view_base_sptr &, outP)" );
01103 
01104   // Check output is scalar component image.
01105   assert (vil_pixel_format_num_components(vil_pixel_format_of(outP())) == 1);
01106 
01107   if (!src) return vil_image_view<outP>();
01108 
01109   // try to do it quickly
01110   if (vil_pixel_format_of(outP()) == src->pixel_format() && src->nplanes() == 1)
01111     return vil_image_view<outP>(src);
01112 
01113   // create output view
01114   vil_image_view<outP> dest;
01115 
01116   // convert via vil_image_view<double>
01117   switch (vil_pixel_format_component_format(src->pixel_format()))
01118   {
01119 #ifndef DOXYGEN_SHOULD_SKIP_THIS
01120 #define macro( F , T ) \
01121    case F: { \
01122     vil_image_view<T > src1 = src; \
01123     vil_image_view<double> dest1; \
01124     vil_convert_planes_to_grey(src1, dest1, rw, gw, bw); \
01125     vil_convert_round(dest1,dest); \
01126     break; }
01127    macro(VIL_PIXEL_FORMAT_BYTE, vxl_byte )
01128    macro(VIL_PIXEL_FORMAT_SBYTE , vxl_sbyte )
01129 #if VXL_HAS_INT_64
01130    macro(VIL_PIXEL_FORMAT_UINT_64 , vxl_uint_64 )
01131    macro(VIL_PIXEL_FORMAT_INT_64 , vxl_int_64 )
01132 #endif
01133    macro(VIL_PIXEL_FORMAT_UINT_32 , vxl_uint_32 )
01134    macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
01135    macro(VIL_PIXEL_FORMAT_UINT_16 , vxl_uint_16 )
01136    macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
01137    macro(VIL_PIXEL_FORMAT_FLOAT , float )
01138    macro(VIL_PIXEL_FORMAT_DOUBLE , double )
01139    // Don't even want to think about rgb<complex<float> >
01140 #undef macro
01141 #endif // DOXYGEN_SHOULD_SKIP_THIS
01142    default:
01143     dest.clear();
01144   }
01145   return dest;
01146 }
01147 #endif // 0
01148 
01149 //: Create an n plane image from any image src.
01150 // This function is designed to be used with vil_load or
01151 // vil_image_resource::get_view()
01152 // where you do not know the pixel type or number of planes in advance.
01153 // If the input images have too many planes, the higher planes will be
01154 // truncated. If the input image has too few planes, the new planes will be
01155 // copies of the first plane.
01156 //
01157 // The output may be a shallow copy of the input.
01158 // The input image's storage arrangement may not be preserved.
01159 //
01160 // This function works on scalar pixel types only, however it can be used to
01161 // produce an rgb image as in the following example
01162 // \code
01163 // vil_image_view<vil_rgb<float> > =
01164 //   vil_convert_cast(
01165 //     vil_convert_to_component_order(
01166 //       vil_convert_to_n_planes(
01167 //         vil_load(filename),
01168 //       3),
01169 //     ),
01170 //   float());
01171 // \endcode
01172 inline vil_image_view_base_sptr vil_convert_to_n_planes(
01173   unsigned n_planes, const vil_image_view_base_sptr &src)
01174 {
01175   if (!src || n_planes == 0)
01176     return vil_image_view_base_sptr();
01177 
01178   switch (vil_pixel_format_component_format(src->pixel_format()))
01179   {
01180 #ifndef DOXYGEN_SHOULD_SKIP_THIS
01181  #define macro( F, T ) \
01182    case F: { \
01183     vil_image_view<T > src_ref = src; \
01184     if (!src_ref) return vil_image_view_base_sptr(); \
01185     /* try to do it quickly 1 */ \
01186     if (src_ref.nplanes() >= n_planes) /* reduce number of planes */ \
01187       return vil_image_view_base_sptr( new vil_image_view<T >( \
01188           vil_planes(vil_image_view<T > (src),0,1,n_planes) )); \
01189     else { /* expand number of planes with copying */ \
01190       vil_image_view_base_sptr dest = new vil_image_view<T >(src_ref.ni(), src_ref.nj(), n_planes); \
01191       vil_image_view<T > & dest_ref = static_cast<vil_image_view<T >&>(*dest); \
01192       vil_image_view<T > dest_slices = vil_planes(dest_ref, 0, 1, src_ref.nplanes()); \
01193       vil_copy_reformat(src_ref, dest_slices); \
01194       vil_image_view<T > src_slice(vil_plane(src_ref, 0)); \
01195       for (unsigned i=src_ref.nplanes(); i<n_planes; ++i) { \
01196         dest_slices = vil_plane(dest_ref, i); \
01197         vil_copy_reformat(src_slice,  dest_slices); } \
01198       return dest; } }
01199    macro(VIL_PIXEL_FORMAT_BYTE, vxl_byte )
01200    macro(VIL_PIXEL_FORMAT_SBYTE , vxl_sbyte )
01201 #if VXL_HAS_INT_64
01202    macro(VIL_PIXEL_FORMAT_UINT_64 , vxl_uint_64 )
01203    macro(VIL_PIXEL_FORMAT_INT_64 , vxl_int_64 )
01204 #endif
01205    macro(VIL_PIXEL_FORMAT_UINT_32 , vxl_uint_32 )
01206    macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
01207    macro(VIL_PIXEL_FORMAT_UINT_16 , vxl_uint_16 )
01208    macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
01209    macro(VIL_PIXEL_FORMAT_FLOAT , float )
01210    macro(VIL_PIXEL_FORMAT_DOUBLE , double )
01211 #undef macro
01212 #endif // DOXYGEN_SHOULD_SKIP_THIS
01213    default:
01214      vil_exception_warning(vil_exception_unsupported_pixel_format(
01215         src->pixel_format(), "vil_convert_to_n_planes") );
01216 
01217     return vil_image_view_base_sptr();
01218   }
01219 }
01220 
01221 
01222 //: Create an image of the desired type by stretching the range to fit.
01223 // This function is designed to be used with vil_load or
01224 // vil_image_resource::get_view()
01225 // where you do not know the pixel type in advance.
01226 // In the case of floating point output pixels the range is set to [0,1]
01227 // The input image's storage arrangement may not be preserved.
01228 //
01229 // This function works on scalar pixel types only. You can convert the image
01230 // to rgb using a cheap assignment afterwards.
01231 template <class outP>
01232 inline vil_image_view_base_sptr vil_convert_stretch_range(
01233   outP /*dummy*/, const vil_image_view_base_sptr &src)
01234 {
01235   // Check that input isn't trying to produce multi-component pixels
01236   assert (vil_pixel_format_num_components(vil_pixel_format_of(outP())) == 1);
01237 
01238   if (!src)
01239     return vil_image_view_base_sptr();
01240 
01241   double hi,lo;
01242 
01243   if (vcl_numeric_limits<outP>::is_integer)
01244   {
01245     hi = vcl_numeric_limits<outP>::max()+0.999;
01246     lo = vcl_numeric_limits<outP>::min();
01247   }
01248   else
01249   {
01250     hi=1.0;
01251     lo=0.0;
01252   }
01253 
01254   vil_image_view_base_sptr dest = new vil_image_view<outP>;
01255   vil_image_view<outP> & dest_ref = static_cast<vil_image_view<outP> &>(*dest);
01256   vil_image_view<double> inter;
01257   switch (vil_pixel_format_component_format(src->pixel_format()))
01258   {
01259 #ifndef DOXYGEN_SHOULD_SKIP_THIS
01260 #define macro( F , T ) \
01261    case F: { \
01262     vil_image_view<T> src_ref = src; \
01263     if (!src_ref) return vil_image_view_base_sptr(); \
01264     vil_convert_stretch_range(src_ref, inter, lo, hi); \
01265     vil_convert_cast(inter, dest_ref); \
01266     break; }
01267    macro(VIL_PIXEL_FORMAT_BYTE, vxl_byte )
01268    macro(VIL_PIXEL_FORMAT_SBYTE , vxl_sbyte )
01269 #if VXL_HAS_INT_64 && !defined(VCL_VC_6)
01270    macro(VIL_PIXEL_FORMAT_UINT_64 , vxl_uint_64 )
01271    macro(VIL_PIXEL_FORMAT_INT_64 , vxl_int_64 )
01272 #endif
01273    macro(VIL_PIXEL_FORMAT_UINT_32 , vxl_uint_32 )
01274    macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
01275    macro(VIL_PIXEL_FORMAT_UINT_16 , vxl_uint_16 )
01276    macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
01277    macro(VIL_PIXEL_FORMAT_FLOAT , float )
01278    macro(VIL_PIXEL_FORMAT_DOUBLE , double )
01279 #undef macro
01280 #endif // DOXYGEN_SHOULD_SKIP_THIS
01281   default:
01282     vil_exception_warning(vil_exception_unsupported_pixel_format(
01283       src->pixel_format(), "vil_convert_stretch_range") );
01284 
01285     dest_ref.clear();
01286   }
01287   return dest;
01288 }
01289 
01290 
01291 #endif // vil_convert_h_