contrib/mul/vil3d/vil3d_convert.h

Go to the documentation of this file.
00001 // This is mul/vil3d/vil3d_convert.h
00002 #ifndef vil3d_convert_h_
00003 #define vil3d_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 vil3d_image_view<T> to a vil3d_image_view<T>,
00017 // the others take an inknown pixel type, using a
00018 // vil3d_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 vil3d_convert with explicit pixel types
00024 // These are useful when you have two vil3d_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 too save
00028 // unnecessary work.
00029 // - vil3d_convert_cast
00030 // - vil3d_convert_round
00031 // - vil3d_convert_stretch_range
00032 //
00033 // \par vil3d_convert with unknown pixel types
00034 // These functions are useful when taking an image from vil3d_load
00035 // of vil3d_image_resource::get_view(), where you may not know the
00036 // pixel type in advance, but want to force the image into a
00037 // particular pixel type.
00038 // - vil3d_convert_cast
00039 // - vil3d_convert_round
00040 // - vil3d_convert_stretch_range
00041 // - vil3d_convert_to_n_planes
00042 // In general these functions expect to take scalar pixel images as
00043 // inputs. Even though many of these functions could return a known
00044 // pixel-typed image, they all return a vil3d_image_view_base_sptr,
00045 // so that the functions can be strung along
00046 //
00047 // Note that these vil3d_convert_..( vil3d_image_view_base_sptr ) functions
00048 // are provided as a convenience for users of vil3d_load and
00049 // vil3d_image_resource::get_view(). Their existence should not suggest
00050 // that it is sensible to use a vil3d_image_view_base_sptr as storage,
00051 // nor that it is a good idea to write a functions that
00052 // take or return a vil3d_image_view_base_sptr. If you need a
00053 // pixel-type-agnostic image container then use a vil3d_image_resource_sptr
00054 //
00055 // It may be a good idea to provide vil3d_image_resource_sptr based
00056 // vil3d_converts as well.
00057 
00058 #include <vcl_cassert.h>
00059 #include <vcl_limits.h>
00060 #include <vil/vil_convert.h>
00061 #include <vil3d/vil3d_transform.h>
00062 #include <vil3d/vil3d_math.h>
00063 #include <vil3d/vil3d_plane.h>
00064 #include <vil3d/vil3d_copy.h>
00065 
00066 
00067 //: Cast one pixel type to another (with rounding).
00068 // There must be a cast operator from inP to outP
00069 //
00070 // If the two pixel types are the same, the destination may only be a shallow
00071 // copy of the source.
00072 // \relates vil3d_image_view
00073 template <class inP, class outP>
00074 inline void vil3d_convert_cast(const vil3d_image_view<inP >&src,
00075                                vil3d_image_view<outP >&dest)
00076 {
00077   if (vil_pixel_format_of(inP()) == vil_pixel_format_of(outP()))
00078     dest = src;
00079   else
00080     vil3d_transform2(src, dest, vil_convert_cast_pixel<inP, outP>());
00081 }
00082 
00083 
00084 //: Convert one pixel type to another with rounding.
00085 // This should only be used to convert scalar pixel types to other scalar
00086 // pixel types, or RGBs to RGBs. This function only rounds in terms of the
00087 // destination type.
00088 //
00089 // If the two pixel types are the same, the destination may only be a
00090 // shallow copy of the source.
00091 // \relates vil3d_image_view
00092 template <class inP, class outP>
00093 inline void vil3d_convert_round(const vil3d_image_view<inP >&src,
00094                                 vil3d_image_view<outP >&dest)
00095 {
00096   if (vil_pixel_format_of(inP()) == vil_pixel_format_of(outP()))
00097     dest = src;
00098   else
00099     vil3d_transform2(src, dest, vil_convert_round_pixel<inP, outP>());
00100 }
00101 
00102 
00103 //: Convert src to byte image dest by stretching to range [0,255]
00104 // \relates vil3d_image_view
00105 template <class T>
00106 inline void vil3d_convert_stretch_range(const vil3d_image_view<T>& src,
00107                                         vil3d_image_view<vxl_byte>& dest)
00108 {
00109   T min_b,max_b;
00110   vil3d_math_value_range(src,min_b,max_b);
00111   double a = -1.0*double(min_b);
00112   double b = 0.0;
00113   if (max_b-min_b >0) b = 255.0/(max_b-min_b);
00114   dest.set_size(src.ni(), src.nj(), src.nk(), src.nplanes());
00115   for (unsigned p = 0; p < src.nplanes(); ++p)
00116     for (unsigned k = 0; k < src.nk(); ++k)
00117       for (unsigned j = 0; j < src.nj(); ++j)
00118         for (unsigned i = 0; i < src.ni(); ++i)
00119            dest(i,j,k,p) = static_cast<vxl_byte>( b*( src(i,j,k,p)+ a ) );
00120 }
00121 
00122 
00123 // It doesn't seem sensible to write a general stretch
00124 // conversion function from any type to any type.
00125 // The individual pixel transfer function has to perform
00126 // multiplications which have to be done in double
00127 // to provide both the range and precision. You may as well
00128 // leave the image in double, and convert it again later.
00129 
00130 //: Convert src to double image dest by stretching to range [lo,hi]
00131 template <class inP>
00132 inline void vil3d_convert_stretch_range(const vil3d_image_view<inP>& src,
00133                                         vil3d_image_view<double>& dest,
00134                                         double lo, double hi)
00135 {
00136   inP min_b=0, max_b=0;
00137   vil3d_math_value_range(src,min_b,max_b);
00138   double b = 0.0;
00139   if (max_b-min_b >0)
00140     b = (hi-lo)/static_cast<double>(max_b-min_b);
00141   double a = -1.0*min_b*b + lo;
00142   dest.set_size(src.ni(), src.nj(), src.nk(), src.nplanes());
00143   for (unsigned p = 0; p < src.nplanes(); ++p)
00144     for (unsigned k = 0; k < src.nk(); ++k)
00145       for (unsigned j = 0; j < src.nj(); ++j)
00146         for (unsigned i = 0; i < src.ni(); ++i)
00147           dest(i,j,k,p) =  b*src(i,j,k,p) + a;
00148 }
00149 
00150 
00151 //: Convert src image<inP> to dest image<double> by stretching input range [src_lo, src_hi] to output range [dest_lo, dest_hi].
00152 // Inputs < src_lo are mapped to dest_lo, and inputs > src_hi to dest_hi.
00153 template <class inP>
00154 inline void vil3d_convert_stretch_range_limited(const vil3d_image_view<inP>& src,
00155                                                 vil3d_image_view<double>& dest,
00156                                                 const inP src_lo,
00157                                                 const inP src_hi,
00158                                                 const double dest_lo,
00159                                                 const double dest_hi)
00160 {
00161   double b = 0.0;
00162 
00163   double ddest = dest_hi - dest_lo;
00164   double dsrc = static_cast<double>(src_hi - src_lo);
00165   double dds = ddest / dsrc;
00166 
00167   dest.set_size(src.ni(), src.nj(), src.nk(), src.nplanes());
00168   for (unsigned p = 0; p < src.nplanes(); ++p)
00169     for (unsigned k = 0; k < src.nk(); ++k)
00170       for (unsigned j = 0; j < src.nj(); ++j)
00171         for (unsigned i = 0; i < src.ni(); ++i)
00172         {
00173           inP s = src(i,j,k,p);
00174           dest(i,j,k,p) = s<=src_lo ? dest_lo :
00175                           s>=src_hi ? dest_hi :
00176                                       dest_lo + dds*static_cast<double>(s-src_lo);
00177         }
00178 }
00179 
00180 
00181 //: Cast the unknown pixel type to the known one.
00182 //
00183 // This function is designed to be used with vil3d_load or
00184 // vil3d_image_resource::get_view()
00185 // where you do not know the pixel type in advance.
00186 // If you need a multi-component view, then call this to get the corresponding
00187 // multi-planar view, and do a second (cheap) conversion.
00188 // The input image's storage arrangement may not be preserved.
00189 template <class outP>
00190 inline vil3d_image_view_base_sptr vil3d_convert_cast(outP /*dummy*/,
00191                                                      const vil3d_image_view_base_sptr& src)
00192 {
00193   if (!src) return vil3d_image_view_base_sptr();
00194 
00195   vil3d_image_view_base_sptr dest = new vil3d_image_view<outP>;
00196   vil3d_image_view<outP> & dest_ref = static_cast<vil3d_image_view<outP> &>(*dest);
00197 
00198   switch ( vil_pixel_format_component_format(src->pixel_format()) )
00199   {
00200 #define macro(F , T) \
00201    case F: \
00202     vil3d_convert_cast( vil3d_image_view<T >( src ), dest_ref );\
00203     break;
00204 
00205     macro( VIL_PIXEL_FORMAT_UINT_32, vxl_uint_32 )
00206     macro( VIL_PIXEL_FORMAT_INT_32, vxl_int_32 )
00207     macro( VIL_PIXEL_FORMAT_UINT_16, vxl_uint_16 )
00208     macro( VIL_PIXEL_FORMAT_INT_16, vxl_int_16 )
00209     macro( VIL_PIXEL_FORMAT_BYTE, vxl_byte )
00210     macro( VIL_PIXEL_FORMAT_SBYTE, vxl_sbyte )
00211     macro( VIL_PIXEL_FORMAT_FLOAT, float )
00212     macro( VIL_PIXEL_FORMAT_DOUBLE, double )
00213     macro( VIL_PIXEL_FORMAT_BOOL, bool )
00214 #undef macro
00215     default: dest=0;
00216   }
00217   return dest;
00218 }
00219 
00220 
00221 //: Convert an image of any pixel type to another with rounding.
00222 // This should only be used to convert to scalar
00223 // pixel types. This function only rounds in terms of the
00224 // destination type.
00225 // This function is designed to be used with vil3d_load or
00226 // vil3d_image_resource::get_view()
00227 // where you do not know the pixel type in advance.
00228 //
00229 // If the input image already has outP as its pixel type, the destination
00230 // may only be a shallow copy of the source.
00231 // outP should be a scalar pixel type.
00232 // The input image's storage arrangement may not be preserved.
00233 template <class outP>
00234 inline vil3d_image_view_base_sptr vil3d_convert_round(
00235   outP /*dummy*/, const vil3d_image_view_base_sptr &src)
00236 {
00237   assert(vil_pixel_format_num_components(vil_pixel_format_of(outP()))==1);
00238 
00239   if (!src) return vil3d_image_view_base_sptr();
00240 
00241   if (vil_pixel_format_component_format(src->pixel_format()) ==
00242       vil_pixel_format_of(outP()))
00243     return src;
00244 
00245   vil3d_image_view_base_sptr dest = new vil3d_image_view<outP >;
00246   vil3d_image_view<outP > &dest_ref = static_cast<vil3d_image_view<outP >&>(*dest);
00247 
00248   switch (vil_pixel_format_component_format(src->pixel_format()))
00249   {
00250 #define macro( F , T ) \
00251    case F: { \
00252     vil3d_image_view<T > src1 = src; \
00253     vil3d_transform2(src1, dest_ref, vil_convert_round_pixel<T , outP>()); \
00254     break; }
00255 
00256     macro(VIL_PIXEL_FORMAT_BYTE, vxl_byte )
00257     macro(VIL_PIXEL_FORMAT_SBYTE , vxl_sbyte )
00258     macro(VIL_PIXEL_FORMAT_UINT_32 , vxl_uint_32 )
00259     macro(VIL_PIXEL_FORMAT_UINT_16 , vxl_uint_16 )
00260     macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
00261     macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
00262     macro(VIL_PIXEL_FORMAT_FLOAT , float )
00263     macro(VIL_PIXEL_FORMAT_DOUBLE , double )
00264 #undef macro
00265    default: dest=0;
00266   }
00267   return dest;
00268 }
00269 
00270 
00271 //: Create a greyscale image of specified pixel type from any image src.
00272 // This function is designed to be used with vil3d_load or
00273 // vil3d_image_resource::get_view()
00274 // where you do not know the pixel type in advance. e.g.
00275 // \verbatim
00276 // vil3d_image_view<float> input = vil3d_convert_cast(
00277 //   convert_to_grey_using_average(vil3d_load(filename)), float());
00278 // \endverbatim
00279 // The output may be a reconfigured view of the input.
00280 // The input image's pixel type and storage arrangement may not be preserved.
00281 inline vil3d_image_view_base_sptr vil3d_convert_to_grey_using_average(
00282   const vil3d_image_view_base_sptr &src)
00283 {
00284   if (!src) return vil3d_image_view_base_sptr();
00285 
00286   // convert via vil3d_image_view<double>
00287   switch (vil_pixel_format_component_format(src->pixel_format()))
00288   {
00289 #define macro( F , T ) \
00290    case F: { \
00291     /* try to do it quickly */ \
00292     if (src->nplanes() == 1 && \
00293         vil_pixel_format_component_format(src->pixel_format())==1) \
00294       return src; \
00295     /* create output view */ \
00296     vil3d_image_view<T > dest; \
00297     vil3d_image_view<T > src1 = *src; \
00298     vil3d_math_mean_over_planes(src1, dest, double()); \
00299     return vil3d_image_view_base_sptr(new vil3d_image_view<T >(dest)); }
00300 
00301     macro(VIL_PIXEL_FORMAT_BYTE, vxl_byte )
00302     macro(VIL_PIXEL_FORMAT_SBYTE , vxl_sbyte )
00303     macro(VIL_PIXEL_FORMAT_UINT_32 , vxl_uint_32 )
00304     macro(VIL_PIXEL_FORMAT_UINT_16 , vxl_uint_16 )
00305     macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
00306     macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
00307     macro(VIL_PIXEL_FORMAT_FLOAT , float )
00308     macro(VIL_PIXEL_FORMAT_DOUBLE , double )
00309 #undef macro
00310    default:
00311     return vil3d_image_view_base_sptr();
00312   }
00313 }
00314 
00315 
00316 //: Create an n plane image from any image src.
00317 // This function is designed to be used with vil3d_load or
00318 // vil3d_image_resource::get_view()
00319 // where you do not know the pixel type or number of planes in advance.
00320 // If the input images have too many planes, the higher planes will be
00321 // truncated. If the input image has too few planes, the new planes will be
00322 // copies of the first plane.
00323 //
00324 // The output may be a shallow copy of the input.
00325 // The input image's storage arrangement may not be preserved.
00326 // \endverbatim
00327 inline vil3d_image_view_base_sptr vil3d_convert_to_n_planes(
00328   unsigned n_planes, const vil3d_image_view_base_sptr &src)
00329 {
00330   if (!src || n_planes == 0)
00331     return vil3d_image_view_base_sptr();
00332 
00333 
00334   switch (vil_pixel_format_component_format(src->pixel_format()))
00335   {
00336  #define macro( F, T ) \
00337    case F: { \
00338     vil3d_image_view<T > src_ref = src; \
00339     if (!src_ref) return vil3d_image_view_base_sptr(); \
00340     /* try to do it quickly 1 */ \
00341     if (src_ref.nplanes() >= n_planes)  /* reduce number of planes */ \
00342       return vil3d_image_view_base_sptr( new vil3d_image_view<T >( \
00343           vil3d_planes(vil3d_image_view<T > (src),0,1,n_planes) )); \
00344     else { /* expand number of planes with copying */ \
00345       vil3d_image_view_base_sptr dest = new vil3d_image_view<T >( \
00346         src_ref.ni(), src_ref.nj(), src_ref.nk(), n_planes); \
00347       vil3d_image_view<T > & dest_ref = \
00348         static_cast<vil3d_image_view<T > &>(*dest); \
00349       vil3d_image_view<T > dest_slices = \
00350         vil3d_planes(dest_ref, 0, 1, src_ref.nplanes()); \
00351       vil3d_copy_reformat(src_ref, dest_slices); \
00352       vil3d_image_view<T > src_slice(vil3d_plane(src_ref, 0)); \
00353       for (unsigned i=src_ref.nplanes(); i<n_planes; ++i) { \
00354         dest_slices = vil3d_plane(dest_ref, i); \
00355         vil3d_copy_reformat(src_slice,  dest_slices); } \
00356       return dest;  } } \
00357 
00358     macro(VIL_PIXEL_FORMAT_BYTE, vxl_byte )
00359     macro(VIL_PIXEL_FORMAT_SBYTE , vxl_sbyte )
00360     macro(VIL_PIXEL_FORMAT_UINT_32 , vxl_uint_32 )
00361     macro(VIL_PIXEL_FORMAT_UINT_16 , vxl_uint_16 )
00362     macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
00363     macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
00364     macro(VIL_PIXEL_FORMAT_FLOAT , float )
00365     macro(VIL_PIXEL_FORMAT_DOUBLE , double )
00366 #undef macro
00367 
00368    default:
00369     return vil3d_image_view_base_sptr();
00370   }
00371 }
00372 
00373 
00374 //: Create an image of the desired type by stretching the range to fit.
00375 // This function is designed to be used with vil3d_load or
00376 // vil3d_image_resource::get_view()
00377 // where you do not know the pixel type in advance.
00378 // In the case of floating point output pixels the range is set to [0,1]
00379 // The input image's storage arrangement may not be preserved.
00380 //
00381 // This function works on scalar pixel types only. You can convert the image
00382 // to rgb using a cheap assignment afterwards.
00383 template <class outP>
00384 inline vil3d_image_view_base_sptr vil3d_convert_stretch_range(
00385   outP /*dummy*/, const vil3d_image_view_base_sptr &src)
00386 {
00387   // Check that input isn't trying to produce multi-component pixels
00388   assert (vil_pixel_format_num_components(vil_pixel_format_of(outP())) == 1);
00389 
00390   if (!src)
00391     return vil3d_image_view_base_sptr();
00392 
00393   double hi,lo;
00394 
00395   if (vcl_numeric_limits<outP>::is_integer)
00396   {
00397     hi = vcl_numeric_limits<outP>::max()+0.999;
00398     lo = vcl_numeric_limits<outP>::min();
00399   }
00400   else
00401   {
00402     hi=1.0;
00403     lo=0.0;
00404   }
00405 
00406   vil3d_image_view_base_sptr dest = new vil3d_image_view<outP>;
00407   vil3d_image_view<outP> & dest_ref = static_cast<vil3d_image_view<outP> &>(*dest);
00408   vil3d_image_view<double> inter;
00409   switch (vil_pixel_format_component_format(src->pixel_format()))
00410   {
00411 #define macro( F , T ) \
00412    case F: { \
00413     vil3d_image_view<T> src_ref = src; \
00414     if (!src_ref) return vil3d_image_view_base_sptr(); \
00415     vil3d_convert_stretch_range(src_ref, inter, lo, hi); \
00416     vil3d_convert_cast(inter, dest_ref); \
00417     break; }
00418 
00419     macro(VIL_PIXEL_FORMAT_BYTE, vxl_byte )
00420     macro(VIL_PIXEL_FORMAT_SBYTE , vxl_sbyte )
00421     macro(VIL_PIXEL_FORMAT_UINT_32 , vxl_uint_32 )
00422     macro(VIL_PIXEL_FORMAT_UINT_16 , vxl_uint_16 )
00423     macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
00424     macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
00425     macro(VIL_PIXEL_FORMAT_FLOAT , float )
00426     macro(VIL_PIXEL_FORMAT_DOUBLE , double )
00427 #undef macro
00428    default:
00429     dest_ref.clear();
00430   }
00431   return dest;
00432 }
00433 
00434 
00435 #endif // vil3d_convert_h_

Generated on Mon Nov 23 05:15:07 2009 for contrib/mul/vil3d by  doxygen 1.5.1