vil_convert.h
Go to the documentation of this file.
1 // This is core/vil/vil_convert.h
2 #ifndef vil_convert_h_
3 #define vil_convert_h_
4 //:
5 // \file
6 // \brief Some standard conversion functions.
7 // \author Ian Scott.
8 //
9 // This file contains a large number of image to image conversion
10 // functions.
11 // They are in two basic function types (plus a few helper functions.)
12 // Some involve only explicit types and convert
13 // a vil_image_view<T> to a vil_image_view<T>,
14 // the others take an unknown pixel type, using a
15 // vil_image_view_base_sptr. The basic conversion
16 // operations (e.g. casting, rounding) are available in both types.
17 // All of the conversions attempt to find shortcuts, so the output
18 // may be a reconfigured, or shallow copy of the input.
19 //
20 // \par vil_convert with explicit pixel types
21 // These are useful when you have two vil_image_view objects you want
22 // to convert between. You can use them in templates where the pixel
23 // type is one of the template parameters. These functions
24 // may create a shallow copy of the input if the types match to save
25 // unnecessary work.
26 // - vil_convert_cast
27 // - vil_convert_round
28 // - vil_convert_rgb_to_grey
29 // - vil_convert_planes_to_grey
30 // - vil_convert_stretch_range
31 //
32 // \par vil_convert with unknown pixel types
33 // These functions are useful when taking an image from vil_load
34 // or vil_image_resource::get_view(), where you may not know the
35 // pixel type in advance, but want to force the image into a
36 // particular pixel type.
37 // - vil_convert_cast
38 // - vil_convert_round
39 // - vil_convert_rgb_to_grey
40 // - vil_convert_planes_to_grey
41 // - vil_convert_stretch_range
42 // - vil_convert_to_component_order
43 // - vil_convert_to_n_planes
44 //
45 // In general these functions expect to take scalar pixel images as
46 // inputs. Even though many of these functions could return a known
47 // pixel-typed image, they all return a vil_image_view_base_sptr,
48 // so that the functions can be strung along.
49 //
50 // Note that these vil_convert_..( vil_image_view_base_sptr ) functions
51 // are provided as a convenience for users of vil_load and
52 // vil_image_resource::get_view(). Their existence should not suggest
53 // that it is sensible to use a vil_image_view_base_sptr as storage,
54 // nor that it is a good idea to write functions that
55 // take or return a vil_image_view_base_sptr. If you need a
56 // pixel-type-agnostic image container then use a vil_image_resource_sptr
57 //
58 // It may be a good idea to provide vil_image_resource_sptr based
59 // vil_converts as well.
60 //
61 // The ITK project (in Code/IO/itkConvertPixelBuffer.hxx) has
62 // functionality similar to the RGB to grayscale conversion here. A
63 // change was made in ITK so the computation is
64 // (2125.0*r+7154.0*g+0721.0*b)/1000.0 instead of
65 // 0.2125*r+0.7154*g+0.0721*b. The reason is that the latter
66 // expression can produce different results between Intel and
67 // non-Intel platforms (even in cases where r==g && g==b), probably
68 // due to different floating point representations. This may not be
69 // too important, but it is worth noting here. In vil_convert.h we
70 // cannot make the same change without adding computation because
71 // vil_convert_rgb_to_grey() lets you pass in the weights. We'd have
72 // to multiply by 10000 to maintain the current API.
73 //
74 // \verbatim
75 // Modifications
76 // 23 Oct.2003 - Peter Vanroose - Added support for 64-bit int pixels
77 // 30 Mar.2007 - Peter Vanroose - Commented out deprecated versions of vil_convert_cast & vil_convert_to_grey_using_average
78 // \endverbatim
79 
80 #include <limits>
81 #include <cmath>
82 #include <cassert>
83 #include <vcl_compiler_detection.h>
84 #ifdef _MSC_VER
85 # include <vcl_msvc_warnings.h>
86 #endif
87 #include <vil/vil_transform.h>
88 #include <vil/vil_math.h>
89 #include <vil/vil_plane.h>
90 #include <vil/vil_copy.h>
91 #include <vil/vil_exception.h>
92 
93 
94 //: Performs conversion between different pixel types.
95 template <class In, class Out>
97 {
98  public:
99  void operator () (In v, Out &d) const;
100 };
101 
102 #ifndef DOXYGEN_SHOULD_SKIP_THIS
103 // deal with conversions from floating point types to/from some compounds
104 #define macro( in , out )\
105 template <> \
106 inline void vil_convert_cast_pixel<in, vil_rgb<out > >::operator () (in v, vil_rgb<out >& d) const \
107 { d.r = d.g = d.b = (out)v; } \
108 template <> \
109 inline void vil_convert_cast_pixel<vil_rgb<out >, in >::operator () (vil_rgb<out > v, in& d) const \
110 { d = (in)(0.2125*v.r+0.7154*v.g+0.0721*v.b); } \
111 template <> \
112 inline void vil_convert_cast_pixel<in, vil_rgba<out > >::operator () (in v, vil_rgba<out >& d) const \
113 { d.r = d.g = d.b = (out)v; d.a=1; } \
114 template <> \
115 inline void vil_convert_cast_pixel<vil_rgba<out >, in >::operator () (vil_rgba<out > v, in& d) const \
116 { d = (in)(0.2125*v.r+0.7154*v.g+0.0721*v.b); }
117 macro( vxl_byte , vxl_byte )
118 macro( vxl_int_16 , vxl_byte )
119 macro( vxl_uint_16 , vxl_byte )
120 macro( vxl_int_32 , vxl_byte )
121 macro( vxl_uint_32 , vxl_byte )
122 macro( float , vxl_byte )
123 macro( double , vxl_byte )
124 macro( vxl_byte , vxl_sbyte )
125 macro( vxl_int_16 , vxl_sbyte )
126 macro( vxl_uint_16 , vxl_sbyte )
127 macro( vxl_int_32 , vxl_sbyte )
128 macro( vxl_uint_32 , vxl_sbyte )
129 macro( float , vxl_sbyte )
130 macro( double , vxl_sbyte )
131 macro( vxl_int_16 , vxl_int_16 )
132 macro( float , vxl_int_16 )
133 macro( double , vxl_int_16 )
134 macro( vxl_uint_16 , vxl_uint_16 )
135 macro( float , vxl_uint_16 )
136 macro( double , vxl_uint_16 )
137 macro( vxl_int_32 , vxl_int_32 )
138 macro( float , vxl_int_32 )
139 macro( double , vxl_int_32 )
140 macro( vxl_uint_32 , vxl_uint_32 )
141 macro( float , vxl_uint_32 )
142 macro( double , vxl_uint_32 )
143 macro( double , float )
144 #if VXL_HAS_INT_64
145 macro( vxl_int_64 , vxl_byte )
146 macro( vxl_uint_64 , vxl_byte )
147 macro( vxl_int_64 , vxl_sbyte )
148 macro( vxl_uint_64 , vxl_sbyte )
149 macro( vxl_int_64 , vxl_int_64 )
150 macro( float , vxl_int_64 )
151 macro( double , vxl_int_64 )
152 macro( vxl_uint_64 , vxl_uint_64 )
153 macro( float , vxl_uint_64 )
154 macro( double , vxl_uint_64 )
155 #endif
156 #undef macro
157 #define macro( inout )\
158 template <> \
159 inline void vil_convert_cast_pixel<inout, inout >::operator () ( \
160  inout v, inout& d) const { d=v; }
161 macro( vxl_byte )
162 macro( vxl_sbyte )
163 macro( vxl_uint_16 )
164 macro( vxl_int_16 )
165 macro( vxl_uint_32 )
166 macro( vxl_int_32 )
167 #if VXL_HAS_INT_64
168 macro( vxl_uint_64 )
169 macro( vxl_int_64 )
170 #endif
171 macro( float )
172 macro( double )
173 #undef macro
174 template <>
176  vil_rgb<vxl_byte> v, vil_rgb<vxl_byte>& d) const { d.r=v.r, d.g=v.g, d.b=v.b; }
177 template <>
179  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; }
180 #define macro( in )\
181 template <> \
182 inline void vil_convert_cast_pixel<in,std::complex<double> >::operator () (in v, std::complex<double>& d) const \
183 { d = std::complex<double>(double(v),0.0); } \
184 template <> \
185 inline void vil_convert_cast_pixel<in,std::complex<float> >::operator () (in v, std::complex<float>& d) const \
186 { d = std::complex<float>(float(v),0.0f); }
187 macro( vxl_byte )
188 macro( vxl_sbyte )
189 macro( vxl_int_16 )
190 macro( vxl_uint_16 )
191 macro( vxl_int_32 )
192 macro( vxl_uint_32 )
193 #if VXL_HAS_INT_64
194 macro( vxl_int_64 )
195 macro( vxl_uint_64 )
196 #endif
197 #undef macro
198 #define macro( out )\
199 template <> \
200 inline void vil_convert_cast_pixel<std::complex<double>,out >::operator () (std::complex<double> d, out& v) const \
201 { v = (out)(d.real()); } \
202 template <> \
203 inline void vil_convert_cast_pixel<std::complex<float>,out >::operator () (std::complex<float> d, out& v) const \
204 { v = (out)(d.real()); }
205 macro( vxl_byte )
206 macro( vxl_sbyte )
207 macro( vxl_int_16 )
208 macro( vxl_uint_16 )
209 macro( vxl_int_32 )
210 macro( vxl_uint_32 )
211 #if VXL_HAS_INT_64
212 macro( vxl_int_64 )
213 macro( vxl_uint_64 )
214 #endif
215 #undef macro
216 #endif // DOXYGEN_SHOULD_SKIP_THIS
217 // declare general case in case anyone needs something weird.
218 
219 #if defined(_MSC_VER)
220 // Visual C++ intentionally warns when a non-bool is assigned or
221 // cast to a bool. Since the following cast is valid, we suppress the
222 // warning.
223 # pragma warning( push )
224 # pragma warning( disable : 4800 )
225 #endif
226 
227 template <class In, class Out>
228 inline void vil_convert_cast_pixel<In, Out>::operator () (In v, Out &d) const
229 {
230  d = static_cast<Out>(v);
231 }
232 
233 #if defined(_MSC_VER)
234 # pragma warning( pop )
235 #endif
236 
237 
238 //: Cast one pixel type to another.
239 // There must be a cast operator from inP to outP
240 //
241 // If the two pixel types are the same, the destination may only be a shallow
242 // copy of the source.
243 // \relatesalso vil_image_view
244 template <class inP, class outP>
247 {
248  if (vil_pixel_format_of(inP()) == vil_pixel_format_of(outP()))
249  dest = src;
250  else
252 }
253 
254 #if 0 // TODO ?
255 
256 //: Cast the unknown pixel type to the known one, if possible.
257 //
258 // Will call the other vil_convert_case to do the actual
259 // conversion. For template instantiation reasons, this will only
260 // convert to a scalar type, not an RGB or RGBA type.
261 // However, the destination image will have a plane step of 1 if the source
262 // image is RGB or RGBA, i.e., the pixel layout will still be RGBRGB...
263 //
264 // \relatesalso vil_image_view
265 //
266 template <class outP>
268 {
269 #define docase(T) \
270  case T: \
271  vil_convert_cast( vil_image_view< typename vil_pixel_format_type_of<T >::component_type >(src), dest );\
272  break
273 
274  switch ( src->pixel_format() )
275  {
285 
294 
303 
306 
307  default:
308  ;
309  }
310 #undef docase
311 }
312 
313 #endif // 0
314 
315 //: Performs rounding between different pixel types.
316 template <class In, class Out>
318 {
319  public:
320  void operator () (In v, Out &d) const;
321 };
322 
323 #ifndef DOXYGEN_SHOULD_SKIP_THIS
324 // deal with conversions from floating point types to some compounds
325 #define macro( in , out )\
326 template <> \
327 inline void vil_convert_round_pixel<in, out >::operator () ( \
328  in v, out& d) const { \
329  d.r = (out::value_type)(v.r+0.5); \
330  d.g = (out::value_type)(v.g+0.5); \
331  d.b = (out::value_type)(v.b+0.5); }
332 
345 #if VXL_HAS_INT_64
350 #endif
351 #undef macro
352 #define macro( in , out )\
353 template <> \
354 inline void vil_convert_round_pixel<in, out >::operator () (in v, out& d) \
355  const { \
356  d.r = (out::value_type)(v.r); \
357  d.g = (out::value_type)(v.g); \
358  d.b = (out::value_type)(v.b); }
361 #undef macro
362 #define macro( in , out )\
363 template <> \
364 inline void vil_convert_round_pixel<in, out >::operator () (in v, out& d) \
365  const { \
366  d.r = (out::value_type)(v.r+0.5); \
367  d.g = (out::value_type)(v.g+0.5); \
368  d.b = (out::value_type)(v.b+0.5); \
369  d.a = (out::value_type)(v.a+0.5); }
382 #if VXL_HAS_INT_64
387 #endif
388 #undef macro
389 #define macro( in , out )\
390 template <> \
391 inline void vil_convert_round_pixel<in, out >::operator () (in v, out& d) \
392  const { \
393  d.r = (out::value_type)(v.r); \
394  d.g = (out::value_type)(v.g); \
395  d.b = (out::value_type)(v.b); \
396  d.a = (out::value_type)(v.a); }
399 #undef macro
400 
401 #define macro( in , out )\
402 template <> \
403 inline void vil_convert_round_pixel<in, out >::operator () (in v, out& d) \
404 const { d = (out)(v > 0.0 ? v + 0.5 : v - 0.5); }
405 macro( float , vxl_byte )
406 macro( double , vxl_byte )
407 macro( float , vxl_sbyte )
408 macro( double , vxl_sbyte )
409 macro( float , vxl_int_16 )
410 macro( double , vxl_int_16 )
411 macro( float , vxl_uint_16 )
412 macro( double , vxl_uint_16 )
413 macro( float , vxl_int_32 )
414 macro( double , vxl_int_32 )
415 macro( float , vxl_uint_32 )
416 macro( double , vxl_uint_32 )
417 #if VXL_HAS_INT_64
418 macro( float , vxl_int_64 )
419 macro( double , vxl_int_64 )
420 macro( float , vxl_uint_64 )
421 macro( double , vxl_uint_64 )
422 #endif
423 #undef macro
424 #endif // DOXYGEN_SHOULD_SKIP_THIS
425 
426 // declare general case for scalars
427 template <class In, class Out>
428 inline void vil_convert_round_pixel<In, Out>::operator () (In v, Out &d) const
429 {
430  d = (Out)(v);
431 }
432 
433 
434 //: Convert one pixel type to another with rounding.
435 // This should only be used to convert scalar pixel types to other scalar
436 // pixel types, or RGBs to RGBs. This function only rounds in terms of the
437 // destination type.
438 //
439 // If the two pixel types are the same, the destination may only be a
440 // shallow copy of the source.
441 // \relatesalso vil_image_view
442 template <class inP, class outP>
445 {
446  if (vil_pixel_format_of(inP()) == vil_pixel_format_of(outP()))
447  dest = src;
448  else
450 }
451 
452 
453 //: Convert various rgb types to greyscale, using given weights
454 template <class inP, class outP>
456 {
457  double rw_, gw_, bw_;
458  public:
459  vil_convert_rgb_to_grey_pixel(double rw, double gw, double bw):
460  rw_(rw), gw_(gw), bw_(bw) {}
461 
462  void operator() (vil_rgb<inP> v, outP& d) const {
464  void operator() (vil_rgba<inP> v, outP& d) const {
466 };
467 
468 //: Convert images with alpha plane (variable or binary) to images without alpha plane
469 template <class inP, class outP>
471  vil_image_view<outP>& dest,
472  const unsigned nplanes)
473 {
474  assert(vil_pixel_format_num_components(src.pixel_format()) == 1);
475  assert(vil_pixel_format_num_components(dest.pixel_format()) == 1);
476 
477  assert((nplanes == 2) || (nplanes == 4));
478 
479  dest.set_size(src.ni(), src.nj(), nplanes-1);
480 
481  for (unsigned j = 0; j < src.nj(); ++j)
482  for (unsigned i = 0; i < src.ni(); ++i)
483  for (unsigned k = 0; k < nplanes-1; ++k)
484  { vil_convert_round_pixel<double,outP>()(src(i,j,nplanes-1)/255.0*src(i,j,k), dest(i,j,k)); }
485 }
486 
487 //: Convert single plane rgb (or rgba) images to greyscale.
488 // Component types can be different. Rounding will take place if appropriate.
489 //
490 // Default weights convert from linear RGB to CIE luminance assuming a
491 // modern monitor. See Charles Poynton's Colour FAQ
492 // http://www.poynton.com/ColorFAQ.html
493 template <class rgbP, class outP>
496  double rw=0.2125, double gw=0.7154, double bw=0.0721)
497 {
499  func(rw, gw, bw);
500  assert(src.nplanes() == 1);
501  vil_transform2(src, dest, func);
502 }
503 
504 
505 //: Convert first three planes of src image to grey, assuming rgb.
506 // Pixel types can be different. Rounding will take place if appropriate.
507 //
508 // Default weights convert from linear RGB to CIE luminance assuming a
509 // modern monitor. See Charles Poynton's Colour FAQ
510 // http://www.poynton.com/ColorFAQ.html
511 template <class inP, class outP>
514  double rw=0.2125, double gw=0.7154, double bw=0.0721)
515 {
516  assert(src.nplanes() >= 3);
517  assert(vil_pixel_format_num_components(src.pixel_format()) == 1);
518  assert(vil_pixel_format_num_components(dest.pixel_format()) == 1);
519  dest.set_size(src.ni(), src.nj(), 1);
520  for (unsigned j = 0; j < src.nj(); ++j)
521  for (unsigned i = 0; i < src.ni(); ++i)
523  src(i,j,0)*rw + src(i,j,1)*gw + src(i,j,2)*bw, dest(i,j));
524 }
525 
526 
527 //: Convert src to byte image dest by stretching to range [0,255]
528 // \relatesalso vil_image_view
529 template <class T>
532 {
533  T min_b,max_b;
534  vil_math_value_range(src,min_b,max_b);
535  double a = -1.0*double(min_b);
536  double b = 0.0;
537  if (max_b-min_b >0) b = 255.0/(max_b-min_b);
538  dest.set_size(src.ni(), src.nj(), src.nplanes());
539  for (unsigned p = 0; p < src.nplanes(); ++p)
540  for (unsigned j = 0; j < src.nj(); ++j)
541  for (unsigned i = 0; i < src.ni(); ++i)
542  dest(i,j,p) = static_cast<vxl_byte>( b*( src(i,j,p)+ a ) );
543 }
544 
545 
546 // It doesn't seem sensible to write a general stretch
547 // conversion function from any type to any type.
548 // The individual pixel transfer function has to perform
549 // multiplications which have to be done in double
550 // to provide both the range and precision. You may as well
551 // leave the image in double, and convert it again later.
552 
553 //: Convert src to double image dest by stretching to range [dest_lo,dest_hi]
554 template <class inP>
557  double dest_lo, double dest_hi)
558 {
559  inP min_b=0, max_b=0;
560  vil_math_value_range(src,min_b,max_b);
561  double b = 0.0;
562  if (max_b-min_b >0)
563  b = static_cast<double>(dest_hi-dest_lo)/static_cast<double>(max_b-min_b);
564  double a = -1.0*min_b*b + dest_lo;
565  dest.set_size(src.ni(), src.nj(), src.nplanes());
566  for (unsigned p = 0; p < src.nplanes(); ++p)
567  for (unsigned j = 0; j < src.nj(); ++j)
568  for (unsigned i = 0; i < src.ni(); ++i)
569  dest(i,j,p) = b*src(i,j,p) + a;
570 }
571 
572 //: Convert src to float image dest by stretching to range [dest_lo,dest_hi]
573 template <class inP>
575  vil_image_view<float>& dest,
576  float dest_lo, float dest_hi)
577 {
578  inP min_b=0, max_b=0;
579  vil_math_value_range(src,min_b,max_b);
580  float b = 0.0;
581  if (max_b-min_b >0)
582  b = (dest_hi-dest_lo)/static_cast<float>(max_b-min_b);
583  float a = -1.0f*min_b*b + dest_lo;
584  dest.set_size(src.ni(), src.nj(), src.nplanes());
585  for (unsigned p = 0; p < src.nplanes(); ++p)
586  for (unsigned j = 0; j < src.nj(); ++j)
587  for (unsigned i = 0; i < src.ni(); ++i)
588  dest(i,j,p) = b*src(i,j,p) + a;
589 }
590 
591 
592 //: Convert src image<inP> to dest image<double> by stretching input range [src_lo, src_hi] to output range [dest_lo, dest_hi].
593 // Inputs < src_lo are mapped to dest_lo, and inputs > src_hi to dest_hi.
594 template <class inP>
597  const inP src_lo,
598  const inP src_hi,
599  const double dest_lo,
600  const double dest_hi)
601 {
602  double ddest = dest_hi - dest_lo;
603  double dsrc = static_cast<double>(src_hi - src_lo);
604  double dds = ddest / dsrc;
605 
606  dest.set_size(src.ni(), src.nj(), src.nplanes());
607  for (unsigned p = 0; p < src.nplanes(); ++p)
608  for (unsigned j = 0; j < src.nj(); ++j)
609  for (unsigned i = 0; i < src.ni(); ++i)
610  {
611  inP s = src(i,j,p);
612  dest(i,j,p) = s<=src_lo ? dest_lo :
613  s>=src_hi ? dest_hi :
614  dest_lo + dds*static_cast<double>(s-src_lo);
615  }
616 }
617 
618 //: Convert src image<inP> to dest image<float> by stretching input range [src_lo, src_hi] to output range [dest_lo, dest_hi].
619 // Inputs < src_lo are mapped to dest_lo, and inputs > src_hi to dest_hi.
620 template <class inP>
622  vil_image_view<float>& dest,
623  const inP src_lo,
624  const inP src_hi,
625  const float dest_lo,
626  const float dest_hi)
627 {
628  float ddest = dest_hi - dest_lo;
629  float dsrc = static_cast<float>(src_hi - src_lo);
630  float dds = ddest / dsrc;
631 
632  dest.set_size(src.ni(), src.nj(), src.nplanes());
633  for (unsigned p = 0; p < src.nplanes(); ++p)
634  for (unsigned j = 0; j < src.nj(); ++j)
635  for (unsigned i = 0; i < src.ni(); ++i)
636  {
637  inP s = src(i,j,p);
638  dest(i,j,p) = s<=src_lo ? dest_lo :
639  s>=src_hi ? dest_hi :
640  dest_lo + dds*static_cast<float>(s-src_lo);
641  }
642 }
643 
644 //: Convert src image<inP> to dest image<ushort> by stretching input range [src_lo, src_hi] to output range [dest_lo, dest_hi].
645 // Inputs < src_lo are mapped to dest_lo, and inputs > src_hi to dest_hi.
646 template <class inP>
649  const inP src_lo,
650  const inP src_hi,
651  const unsigned short dest_lo,
652  const unsigned short dest_hi)
653 {
654  const double ddest = dest_hi - dest_lo;
655  const double dsrc = static_cast<double>(src_hi - src_lo);
656  const double dds = ddest / dsrc;
657 
658  dest.set_size(src.ni(), src.nj(), src.nplanes());
659  for (unsigned p = 0; p < src.nplanes(); ++p)
660  for (unsigned j = 0; j < src.nj(); ++j)
661  for (unsigned i = 0; i < src.ni(); ++i)
662  {
663  inP s = src(i,j,p);
664  dest(i,j,p) = s<=src_lo ? dest_lo :
665  s>=src_hi ? dest_hi :
666  static_cast<unsigned short>(dest_lo + dds*(s-src_lo)+0.5);
667  }
668 }
669 
670 //: Convert src image<inP> to dest image<ubyte> by stretching input range [src_lo, src_hi] to output range [dest_lo, dest_hi].
671 // Inputs < src_lo are mapped to dest_lo, and inputs > src_hi to dest_hi.
672 template <class inP>
675  const inP src_lo,
676  const inP src_hi,
677  const vxl_byte dest_lo,
678  const vxl_byte dest_hi)
679 {
680  const double ddest = dest_hi - dest_lo;
681  const double dsrc = static_cast<double>(src_hi - src_lo);
682  const double dds = ddest / dsrc;
683 
684  dest.set_size(src.ni(), src.nj(), src.nplanes());
685  for (unsigned p = 0; p < src.nplanes(); ++p)
686  for (unsigned j = 0; j < src.nj(); ++j)
687  for (unsigned i = 0; i < src.ni(); ++i)
688  {
689  inP s = src(i,j,p);
690  dest(i,j,p) = s<=src_lo ? dest_lo :
691  s>=src_hi ? dest_hi :
692  static_cast<vxl_byte>(dest_lo + dds*(s-src_lo)+0.5);
693  }
694 }
695 
696 //: Convert src image<inP> to dest image<vxl_byte> by stretching input range [src_lo, src_hi] to output range [0, 255].
697 // Inputs < src_lo are mapped to 0, and inputs > src_hi to 255.
698 template <class inP>
701  const inP src_lo,
702  const inP src_hi)
703 {
704  const double dsrc = static_cast<double>(src_hi - src_lo);
705  const double dds = 255.0 / dsrc;
706 
707  dest.set_size(src.ni(), src.nj(), src.nplanes());
708  for (unsigned p = 0; p < src.nplanes(); ++p)
709  for (unsigned j = 0; j < src.nj(); ++j)
710  for (unsigned i = 0; i < src.ni(); ++i)
711  {
712  inP s = src(i,j,p);
713  dest(i,j,p) = s<=src_lo ? 0 :
714  static_cast<vxl_byte>( s>=src_hi ? 255 : (dds*(s-src_lo)+0.5) );
715  }
716 }
717 
718 //: Cast the unknown pixel type to the known one.
719 //
720 // This function is designed to be used with vil_load or
721 // vil_image_resource::get_view()
722 // where you do not know the pixel type in advance.
723 // If you need a
724 // multi-component view, then call this to get the corresponding
725 // multi-planar view, and do a second (cheap) conversion.
726 // The input image's storage arrangement may not be preserved.
727 template <class outP>
729  const vil_image_view_base_sptr& src)
730 {
731  if (!src) return vil_image_view_base_sptr();
732 
734  vil_image_view<outP> & dest_ref = static_cast<vil_image_view<outP> &>(*dest);
735 
736  switch ( vil_pixel_format_component_format(src->pixel_format()) )
737  {
738 #ifndef DOXYGEN_SHOULD_SKIP_THIS
739 #define macro(F , T) \
740  case F: vil_convert_cast( vil_image_view<T >(*src), dest_ref ); break
741 
742 #if VXL_HAS_INT_64
743  macro( VIL_PIXEL_FORMAT_UINT_64, vxl_uint_64 );
744  macro( VIL_PIXEL_FORMAT_INT_64, vxl_int_64 );
745 #endif
746  macro( VIL_PIXEL_FORMAT_UINT_32, vxl_uint_32 );
747  macro( VIL_PIXEL_FORMAT_INT_32, vxl_int_32 );
748  macro( VIL_PIXEL_FORMAT_UINT_16, vxl_uint_16 );
749  macro( VIL_PIXEL_FORMAT_INT_16, vxl_int_16 );
750  macro( VIL_PIXEL_FORMAT_BYTE, vxl_byte );
751  macro( VIL_PIXEL_FORMAT_SBYTE, vxl_sbyte );
752  macro( VIL_PIXEL_FORMAT_FLOAT, float );
753  macro( VIL_PIXEL_FORMAT_DOUBLE, double );
754  macro( VIL_PIXEL_FORMAT_BOOL, bool );
755 #undef macro
756 #endif // DOXYGEN_SHOULD_SKIP_THIS
757  default:
759  src->pixel_format(), "vil_convert_cast") );
760  dest = nullptr;
761  }
762  return dest;
763 }
764 
765 #if 0 // deprecated
766 //: Cast the unknown pixel type to the known one, if possible.
767 //
768 // Will call the other vil_convert_cast to do the actual
769 // conversion. For template instantiation reasons, this will only
770 // convert to a scalar type, not a RGB or RGBA type. If you need a
771 // multi-component view, then call this to get the corresponding
772 // multi-planar view, and do a second (cheap) conversion.
773 //
774 // \deprecated Use other vil_convert_cast()
775 // Can be removed after VXL 1.1.1
776 template <class outP>
777 inline void vil_convert_cast(const vil_image_view_base_sptr& src,
779 {
780  VXL_DEPRECATED_MACRO( "void vil_convert_cast(const vil_image_view_base_sptr&,"
781  " vil_image_view<outP>&)" );
782 
783  switch ( src->pixel_format() )
784  {
785 #ifndef DOXYGEN_SHOULD_SKIP_THIS
786 #define macro(F , T) \
787  case F: vil_convert_cast( vil_image_view<T >(src), dest ); break;
788 
789 #if VXL_HAS_INT_64
790  macro( VIL_PIXEL_FORMAT_UINT_64, vxl_uint_64 )
791  macro( VIL_PIXEL_FORMAT_INT_64, vxl_int_64 )
792 #endif
793  macro( VIL_PIXEL_FORMAT_UINT_32, vxl_uint_32 )
794  macro( VIL_PIXEL_FORMAT_INT_32, vxl_int_32 )
795  macro( VIL_PIXEL_FORMAT_UINT_16, vxl_uint_16 )
796  macro( VIL_PIXEL_FORMAT_INT_16, vxl_int_16 )
797  macro( VIL_PIXEL_FORMAT_BYTE, vxl_byte )
798  macro( VIL_PIXEL_FORMAT_SBYTE, vxl_sbyte )
799  macro( VIL_PIXEL_FORMAT_FLOAT, float )
800  macro( VIL_PIXEL_FORMAT_DOUBLE, double )
802 #undef macro
803 #endif // DOXYGEN_SHOULD_SKIP_THIS
804 
805  // Skip the RGB type conversions because the vil_convert_cast are
806  // not complete. For example, a cast from vxl_uint_16 to
807  // vil_rgb<vxl_uint_32> is not defined.
808  default:
809  dest.clear();
810  }
811 }
812 #endif // 0
813 
814 //: Convert an image of any pixel type to another with rounding.
815 // This should only be used to convert to scalar
816 // pixel types. This function only rounds in terms of the
817 // destination type.
818 // This function is designed to be used with vil_load or
819 // vil_image_resource::get_view()
820 // where you do not know the pixel type in advance.
821 //
822 // If the input image already has outP as its pixel type, the destination
823 // may only be a shallow copy of the source.
824 // outP should be a scalar pixel type.
825 // The input image's storage arrangement may not be preserved.
826 template <class outP>
828  outP /*dummy*/, const vil_image_view_base_sptr &src)
829 {
831 
832  if (!src) return vil_image_view_base_sptr();
833 
834  if (vil_pixel_format_component_format(src->pixel_format()) ==
835  vil_pixel_format_of(outP()))
836  return src;
837 
839  vil_image_view<outP > &dest_ref = static_cast<vil_image_view<outP >&>(*dest);
840 
841  switch (vil_pixel_format_component_format(src->pixel_format()))
842  {
843 #ifndef DOXYGEN_SHOULD_SKIP_THIS
844 #define macro( F , T ) \
845  case F: { \
846  vil_image_view<T > src1 = src; \
847  vil_transform2(src1, dest_ref, vil_convert_round_pixel<T , outP>()); \
848  break; }
849 macro(VIL_PIXEL_FORMAT_BYTE, vxl_byte )
850 macro(VIL_PIXEL_FORMAT_SBYTE , vxl_sbyte )
851 #if VXL_HAS_INT_64
852 macro(VIL_PIXEL_FORMAT_UINT_64 , vxl_uint_64 )
853 macro(VIL_PIXEL_FORMAT_INT_64 , vxl_int_64 )
854 #endif
855 macro(VIL_PIXEL_FORMAT_UINT_32 , vxl_uint_32 )
856 macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
857 macro(VIL_PIXEL_FORMAT_UINT_16 , vxl_uint_16 )
858 macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
861 #undef macro
862 #endif // DOXYGEN_SHOULD_SKIP_THIS
863  default:
865  src->pixel_format(), "vil_convert_round") );
866  dest=nullptr;
867  }
868  return dest;
869 }
870 
871 
872 //: Force data to be suitable for viewing as multi component view.
873 // The output data will have values from different planes but the same
874 // pixel location stored in adjacent memory locations. After using this
875 // function on an input with 3 planes, an assignment to a
876 // vil_image_view<vil_rgb<T> > will always work.
877 // The input image's scalar pixel type will be preserved.
879  const vil_image_view_base_sptr& src)
880 {
881  if (!src) return vil_image_view_base_sptr();
882 
884 
885  switch (vil_pixel_format_component_format(src->pixel_format()))
886  {
887 #ifndef DOXYGEN_SHOULD_SKIP_THIS
888 #define macro( F , T )\
889  case F: { \
890  vil_image_view<T > src_ref(src); \
891  if (!src_ref) return vil_image_view_base_sptr(); \
892  if (src_ref.planestep()==1) return src; \
893  const unsigned ni=src->ni(), nj=src->nj(), nplanes=src->nplanes(); \
894  vil_memory_chunk_sptr chunk = new vil_memory_chunk(ni*nj*nplanes*sizeof(T), \
895  vil_pixel_format_component_format(F)); \
896  dest = new vil_image_view<T >(chunk, reinterpret_cast<T*>(chunk->data()), \
897  ni, nj, nplanes, nplanes, nplanes*ni, 1); \
898  vil_image_view<T > & dest_ref = static_cast<vil_image_view<T >&>(*dest); \
899  vil_copy_reformat(src_ref, dest_ref); \
900  break; }
901 macro(VIL_PIXEL_FORMAT_BYTE, vxl_byte )
902 macro(VIL_PIXEL_FORMAT_SBYTE , vxl_sbyte )
903 #if VXL_HAS_INT_64
904 macro(VIL_PIXEL_FORMAT_UINT_64 , vxl_uint_64 )
905 macro(VIL_PIXEL_FORMAT_INT_64 , vxl_int_64 )
906 #endif
907 macro(VIL_PIXEL_FORMAT_UINT_32 , vxl_uint_32 )
908 macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
909 macro(VIL_PIXEL_FORMAT_UINT_16 , vxl_uint_16 )
910 macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
913 #undef macro
914 #endif // DOXYGEN_SHOULD_SKIP_THIS
915 
916  default:
918  src->pixel_format(), "vil_convert_to_compound_order") );
919  dest=nullptr;
920  }
921  return dest;
922 }
923 
924 #if 0 // deprecated
925 //: Create a greyscale image from any image src.
926 // This function is designed to be used with vil_load or
927 // vil_image_resource::get_view()
928 // where you do not know the pixel type in advance. e.g.
929 // \code
930 // vil_image_view<float> input =
931 // vil_convert_to_grey_using_average(vil_load(filename), float());
932 // \endcode
933 // If you have an image_view of known pixel_type then you should use one of
934 // the other vil_convert functions.
935 // The output may be a reconfigured view of the input.
936 // \deprecated Use other vil_convert_to_grey_using_average()
937 template <class outP>
939  const vil_image_view_base_sptr &src, outP /*dummy*/)
940 {
941  VXL_DEPRECATED_MACRO( "vil_convert_to_grey_using_average<outP>("
942  "const vil_image_view_base_sptr &, outP)" );
943 
944  // Check output is scalar component image.
946 
947  if (!src) return vil_image_view<outP>();
948 
949  // try to do it quickly
950  if (vil_pixel_format_of(outP()) == src->pixel_format() && src->nplanes() == 1)
951  return vil_image_view<outP>(src);
952 
953  // create output view
955 
956  // convert via vil_image_view<double>
957  switch (vil_pixel_format_component_format(src->pixel_format()))
958  {
959 #ifndef DOXYGEN_SHOULD_SKIP_THIS
960 #define macro( F , T ) \
961  case F: { \
962  vil_image_view<T > src1 = *src; \
963  vil_math_mean_over_planes(src1, dest, double()); \
964  break; }
965  macro(VIL_PIXEL_FORMAT_BYTE, vxl_byte )
966  macro(VIL_PIXEL_FORMAT_SBYTE , vxl_sbyte )
967 #if VXL_HAS_INT_64
968  macro(VIL_PIXEL_FORMAT_UINT_64 , vxl_uint_64 )
969  macro(VIL_PIXEL_FORMAT_INT_64 , vxl_int_64 )
970 #endif
971  macro(VIL_PIXEL_FORMAT_UINT_32 , vxl_uint_32 )
972  macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
973  macro(VIL_PIXEL_FORMAT_UINT_16 , vxl_uint_16 )
974  macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
975  macro(VIL_PIXEL_FORMAT_FLOAT , float )
976  macro(VIL_PIXEL_FORMAT_DOUBLE , double )
977 #undef macro
978 #endif // DOXYGEN_SHOULD_SKIP_THIS
979  default:
980  dest.clear();
981  }
982  return dest;
983 }
984 #endif // 0
985 
986 //: Create a greyscale image of specified pixel type from any image src.
987 // This function is designed to be used with vil_load or
988 // vil_image_resource::get_view()
989 // where you do not know the pixel type in advance. e.g.
990 // \code
991 // vil_image_view<float> input = vil_convert_cast(
992 // convert_to_grey_using_average(vil_load(filename)), float());
993 // \endcode
994 // The output may be a reconfigured view of the input.
995 // The input image's pixel type and storage arrangement may not be preserved.
997  const vil_image_view_base_sptr &src)
998 {
999  if (!src) return vil_image_view_base_sptr();
1000 
1001  // convert via vil_image_view<double>
1002  switch (vil_pixel_format_component_format(src->pixel_format()))
1003  {
1004 #ifndef DOXYGEN_SHOULD_SKIP_THIS
1005 #define macro( F , T ) \
1006  case F: { \
1007  /* try to do it quickly */ \
1008  if (src->nplanes() == 1 && \
1009  vil_pixel_format_component_format(src->pixel_format())==1) \
1010  return src; \
1011  /* create output view */ \
1012  vil_image_view<T > dest; \
1013  vil_image_view<T > src1 = *src; \
1014  vil_math_mean_over_planes(src1, dest, double()); \
1015  return vil_image_view_base_sptr(new vil_image_view<T >(dest)); }
1016  macro(VIL_PIXEL_FORMAT_BYTE, vxl_byte )
1017  macro(VIL_PIXEL_FORMAT_SBYTE , vxl_sbyte )
1018 #if VXL_HAS_INT_64
1019  macro(VIL_PIXEL_FORMAT_UINT_64 , vxl_uint_64 )
1020  macro(VIL_PIXEL_FORMAT_INT_64 , vxl_int_64 )
1021 #endif
1022  macro(VIL_PIXEL_FORMAT_UINT_32 , vxl_uint_32 )
1023  macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
1024  macro(VIL_PIXEL_FORMAT_UINT_16 , vxl_uint_16 )
1025  macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
1026  macro(VIL_PIXEL_FORMAT_FLOAT , float )
1027  macro(VIL_PIXEL_FORMAT_DOUBLE , double )
1028 #undef macro
1029 #endif // DOXYGEN_SHOULD_SKIP_THIS
1030  default:
1032  src->pixel_format(), "vil_convert_to_grey_using_average") );
1033  return nullptr;
1034  }
1035 }
1036 
1037 
1038 //: Create a greyscale image from any image src.
1039 // This function is designed to be used with vil_load or
1040 // vil_image_resource::get_view()
1041 // where you do not know the pixel type in advance.
1042 // The output may be a reconfigured view of the input.
1043 // The input image's pixel type and storage arrangement may not be preserved.
1045  double rw, double gw, double bw, const vil_image_view_base_sptr &src)
1046 {
1047  if (!src)
1048  return vil_image_view_base_sptr();
1049 
1050  // convert via vil_image_view<double>
1051  switch (vil_pixel_format_component_format(src->pixel_format()))
1052  {
1053 #ifndef DOXYGEN_SHOULD_SKIP_THIS
1054 #define macro( F , T ) \
1055  case F: { \
1056  /* try to do it quickly */ \
1057  if (src->nplanes() == 1 && \
1058  vil_pixel_format_num_components(src->pixel_format()) == 1) \
1059  return vil_image_view_base_sptr(src); \
1060  vil_image_view<T > src1 = src; \
1061  vil_image_view<double> dest1; \
1062  vil_convert_planes_to_grey(src1, dest1, rw, gw, bw); \
1063  vil_image_view<T > dest; \
1064  vil_convert_round(dest1,dest); \
1065  return vil_image_view_base_sptr(new vil_image_view<T >(dest)); }
1066  macro(VIL_PIXEL_FORMAT_BYTE, vxl_byte )
1067  macro(VIL_PIXEL_FORMAT_SBYTE , vxl_sbyte )
1068 #if VXL_HAS_INT_64
1069  macro(VIL_PIXEL_FORMAT_UINT_64 , vxl_uint_64 )
1070  macro(VIL_PIXEL_FORMAT_INT_64 , vxl_int_64 )
1071 #endif
1072  macro(VIL_PIXEL_FORMAT_UINT_32 , vxl_uint_32 )
1073  macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
1074  macro(VIL_PIXEL_FORMAT_UINT_16 , vxl_uint_16 )
1075  macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
1076  macro(VIL_PIXEL_FORMAT_FLOAT , float )
1077  macro(VIL_PIXEL_FORMAT_DOUBLE , double )
1078 #undef macro
1079 #endif // DOXYGEN_SHOULD_SKIP_THIS
1080  default:
1082  src->pixel_format(), "vil_convert_to_grey_using_rgb_weighting") );
1083  return vil_image_view_base_sptr();
1084  }
1085 }
1086 
1087 //: Create a greyscale image from any image src using default weights.
1088 // This function is designed to be used with vil_load or
1089 // vil_image_resource::get_view()
1090 // where you do not know the pixel type in advance.
1091 // The output may be a reconfigured view of the input.
1092 // The input image's pixel type and storage arrangement may not be preserved.
1093 //
1094 // Default weights convert from linear RGB to CIE luminance assuming a
1095 // modern monitor. See Charles Poynton's Colour FAQ
1096 // http://www.poynton.com/ColorFAQ.html
1097 
1099  const vil_image_view_base_sptr &src)
1100 {
1101  return vil_convert_to_grey_using_rgb_weighting(0.2125, 0.7154, 0.0721, src);
1102 }
1103 
1104 #if 0 // deprecated version of this function now commented out
1105 //: Create a greyscale image of specified pixel type from any image src.
1106 // This function is designed to be used with vil_load or
1107 // vil_image_resource::get_view()
1108 // where you do not know the pixel type in advance.
1109 // The output may be a reconfigured view of the input.
1110 //
1111 // Default weights convert from linear RGB to CIE luminance assuming a
1112 // modern monitor. See Charles Poynton's Colour FAQ
1113 // http://www.poynton.com/ColorFAQ.html
1114 // \deprecated Use other version of vil_convert_to_grey_using_rgb_weighting
1115 template <class outP>
1117  const vil_image_view_base_sptr &src,
1118  outP /*dummy*/,
1119  double rw=0.2125,
1120  double gw=0.7154,
1121  double bw=0.0721)
1122 {
1123  VXL_DEPRECATED_MACRO( "vil_convert_to_grey_using_rgb_weighting<outP>("
1124  "const vil_image_view_base_sptr &, outP)" );
1125 
1126  // Check output is scalar component image.
1128 
1129  if (!src) return vil_image_view<outP>();
1130 
1131  // try to do it quickly
1132  if (vil_pixel_format_of(outP()) == src->pixel_format() && src->nplanes() == 1)
1133  return vil_image_view<outP>(src);
1134 
1135  // create output view
1136  vil_image_view<outP> dest;
1137 
1138  // convert via vil_image_view<double>
1139  switch (vil_pixel_format_component_format(src->pixel_format()))
1140  {
1141 #ifndef DOXYGEN_SHOULD_SKIP_THIS
1142 #define macro( F , T ) \
1143  case F: { \
1144  vil_image_view<T > src1 = src; \
1145  vil_image_view<double> dest1; \
1146  vil_convert_planes_to_grey(src1, dest1, rw, gw, bw); \
1147  vil_convert_round(dest1,dest); \
1148  break; }
1149  macro(VIL_PIXEL_FORMAT_BYTE, vxl_byte )
1150  macro(VIL_PIXEL_FORMAT_SBYTE , vxl_sbyte )
1151 #if VXL_HAS_INT_64
1152  macro(VIL_PIXEL_FORMAT_UINT_64 , vxl_uint_64 )
1153  macro(VIL_PIXEL_FORMAT_INT_64 , vxl_int_64 )
1154 #endif
1155  macro(VIL_PIXEL_FORMAT_UINT_32 , vxl_uint_32 )
1156  macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
1157  macro(VIL_PIXEL_FORMAT_UINT_16 , vxl_uint_16 )
1158  macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
1159  macro(VIL_PIXEL_FORMAT_FLOAT , float )
1160  macro(VIL_PIXEL_FORMAT_DOUBLE , double )
1161  // Don't even want to think about rgb<complex<float> >
1162 #undef macro
1163 #endif // DOXYGEN_SHOULD_SKIP_THIS
1164  default:
1165  dest.clear();
1166  }
1167  return dest;
1168 }
1169 #endif // 0
1170 
1171 //: Create an n plane image from any image src.
1172 // This function is designed to be used with vil_load or
1173 // vil_image_resource::get_view()
1174 // where you do not know the pixel type or number of planes in advance.
1175 // If the input images have too many planes, the higher planes will be
1176 // truncated. If the input image has too few planes, the new planes will be
1177 // copies of the first plane.
1178 //
1179 // The output may be a shallow copy of the input.
1180 // The input image's storage arrangement may not be preserved.
1181 //
1182 // This function works on scalar pixel types only, however it can be used to
1183 // produce an rgb image as in the following example
1184 // \code
1185 // vil_image_view<vil_rgb<float> > =
1186 // vil_convert_cast(
1187 // float(),
1188 // vil_convert_to_component_order(
1189 // vil_convert_to_n_planes(
1190 // 3,
1191 // vil_load(filename)
1192 // )
1193 // )
1194 // );
1195 // \endcode
1197  unsigned n_planes, const vil_image_view_base_sptr &src)
1198 {
1199  if (!src || n_planes == 0)
1200  return vil_image_view_base_sptr();
1201 
1202  switch (vil_pixel_format_component_format(src->pixel_format()))
1203  {
1204 #ifndef DOXYGEN_SHOULD_SKIP_THIS
1205  #define macro( F, T ) \
1206  case F: { \
1207  vil_image_view<T > src_ref = src; \
1208  if (!src_ref) return vil_image_view_base_sptr(); \
1209  /* try to do it quickly 1 */ \
1210  if (src_ref.nplanes() >= n_planes) /* reduce number of planes */ \
1211  return vil_image_view_base_sptr( new vil_image_view<T >( \
1212  vil_planes(vil_image_view<T > (src),0,1,n_planes) )); \
1213  else { /* expand number of planes with copying */ \
1214  vil_image_view_base_sptr dest = new vil_image_view<T >(src_ref.ni(), src_ref.nj(), n_planes); \
1215  vil_image_view<T > & dest_ref = static_cast<vil_image_view<T >&>(*dest); \
1216  vil_image_view<T > dest_slices = vil_planes(dest_ref, 0, 1, src_ref.nplanes()); \
1217  vil_copy_reformat(src_ref, dest_slices); \
1218  vil_image_view<T > src_slice(vil_plane(src_ref, 0)); \
1219  for (unsigned i=src_ref.nplanes(); i<n_planes; ++i) { \
1220  dest_slices = vil_plane(dest_ref, i); \
1221  vil_copy_reformat(src_slice, dest_slices); } \
1222  return dest; } }
1223  macro(VIL_PIXEL_FORMAT_BYTE, vxl_byte )
1224  macro(VIL_PIXEL_FORMAT_SBYTE , vxl_sbyte )
1225 #if VXL_HAS_INT_64
1226  macro(VIL_PIXEL_FORMAT_UINT_64 , vxl_uint_64 )
1227  macro(VIL_PIXEL_FORMAT_INT_64 , vxl_int_64 )
1228 #endif
1229  macro(VIL_PIXEL_FORMAT_UINT_32 , vxl_uint_32 )
1230  macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
1231  macro(VIL_PIXEL_FORMAT_UINT_16 , vxl_uint_16 )
1232  macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
1233  macro(VIL_PIXEL_FORMAT_FLOAT , float )
1234  macro(VIL_PIXEL_FORMAT_DOUBLE , double )
1235 #undef macro
1236 #endif // DOXYGEN_SHOULD_SKIP_THIS
1237  default:
1239  src->pixel_format(), "vil_convert_to_n_planes") );
1240 
1241  return vil_image_view_base_sptr();
1242  }
1243 }
1244 
1245 
1246 //: Create an image of the desired type by stretching the range to fit.
1247 // This function is designed to be used with vil_load or
1248 // vil_image_resource::get_view()
1249 // where you do not know the pixel type in advance.
1250 // In the case of floating point output pixels the range is set to [0,1]
1251 // The input image's storage arrangement may not be preserved.
1252 //
1253 // This function works on scalar pixel types only. You can convert the image
1254 // to rgb using a cheap assignment afterwards.
1255 template <class outP>
1257  outP /*dummy*/, const vil_image_view_base_sptr &src)
1258 {
1259  // Check that input isn't trying to produce multi-component pixels
1261 
1262  if (!src)
1263  return vil_image_view_base_sptr();
1264 
1265  double hi,lo;
1266 
1267  if (std::numeric_limits<outP>::is_integer)
1268  {
1269  hi = std::numeric_limits<outP>::max()+0.999;
1270  lo = std::numeric_limits<outP>::min();
1271  }
1272  else
1273  {
1274  hi=1.0;
1275  lo=0.0;
1276  }
1277 
1279  vil_image_view<outP> & dest_ref = static_cast<vil_image_view<outP> &>(*dest);
1280  vil_image_view<double> inter;
1281  switch (vil_pixel_format_component_format(src->pixel_format()))
1282  {
1283 #ifndef DOXYGEN_SHOULD_SKIP_THIS
1284 #define macro( F , T ) \
1285  case F: { \
1286  vil_image_view<T> src_ref = src; \
1287  if (!src_ref) return vil_image_view_base_sptr(); \
1288  vil_convert_stretch_range(src_ref, inter, lo, hi); \
1289  vil_convert_cast(inter, dest_ref); \
1290  break; }
1291  macro(VIL_PIXEL_FORMAT_BYTE, vxl_byte )
1292  macro(VIL_PIXEL_FORMAT_SBYTE , vxl_sbyte )
1293 #if VXL_HAS_INT_64
1294  macro(VIL_PIXEL_FORMAT_UINT_64 , vxl_uint_64 )
1295  macro(VIL_PIXEL_FORMAT_INT_64 , vxl_int_64 )
1296 #endif
1297  macro(VIL_PIXEL_FORMAT_UINT_32 , vxl_uint_32 )
1298  macro(VIL_PIXEL_FORMAT_INT_32 , vxl_int_32 )
1299  macro(VIL_PIXEL_FORMAT_UINT_16 , vxl_uint_16 )
1300  macro(VIL_PIXEL_FORMAT_INT_16 , vxl_int_16 )
1301  macro(VIL_PIXEL_FORMAT_FLOAT , float )
1302  macro(VIL_PIXEL_FORMAT_DOUBLE , double )
1303 #undef macro
1304 #endif // DOXYGEN_SHOULD_SKIP_THIS
1305  default:
1307  src->pixel_format(), "vil_convert_stretch_range") );
1308 
1309  dest_ref.clear();
1310  }
1311  return dest;
1312 }
1313 
1314 
1315 #endif // vil_convert_h_
vil_image_view_base_sptr vil_convert_to_n_planes(unsigned n_planes, const vil_image_view_base_sptr &src)
Create an n plane image from any image src.
Definition: vil_convert.h:1196
vil_pixel_format vil_pixel_format_component_format(enum vil_pixel_format f)
Return the number of components in pixel format f.
vil_smart_ptr< vil_image_view_base > vil_image_view_base_sptr
Definition: vil_fwd.h:18
Indicates that a function call failed because a pixel format could not be handled.
Definition: vil_exception.h:62
Performs conversion between different pixel types.
Definition: vil_convert.h:96
std::complex<float> is a scalar for vil's purposes.
A templated smart pointer class.
Definition: vil_fwd.h:16
Various mathematical manipulations of 2D images.
void vil_convert_stretch_range_limited(const vil_image_view< inP > &src, vil_image_view< double > &dest, const inP src_lo, const inP src_hi, const double dest_lo, const double dest_hi)
Convert src image<inP> to dest image<double> by stretching input range [src_lo, src_hi] to output ran...
Definition: vil_convert.h:595
Concrete view of image data of type T held in memory.
Definition: vil_fwd.h:13
vil_image_view_base_sptr vil_convert_to_grey_using_rgb_weighting(double rw, double gw, double bw, const vil_image_view_base_sptr &src)
Create a greyscale image from any image src.
Definition: vil_convert.h:1044
void vil_convert_rgb_to_grey(const vil_image_view< rgbP > &src, vil_image_view< outP > &dest, double rw=0.2125, double gw=0.7154, double bw=0.0721)
Convert single plane rgb (or rgba) images to greyscale.
Definition: vil_convert.h:494
Convert various rgb types to greyscale, using given weights.
Definition: vil_convert.h:455
void set_size(unsigned ni, unsigned nj) override
resize current planes to ni x nj.
Exceptions thrown by vil, and a mechanism for turning them off.
STL algorithm like methods.
void operator()(In v, Out &d) const
Definition: vil_convert.h:228
void vil_transform2(const vil_image_view< inP > &src, vil_image_view< outP > &dest, Op functor)
Apply a binary function to each pixel in src and dest that modifies dest.
unsigned ni() const
Width.
unsigned nj() const
Height.
#define v
Performs rounding between different pixel types.
Definition: vil_convert.h:317
vil_image_view_base_sptr vil_convert_to_grey_using_average(const vil_image_view_base_sptr &src)
Create a greyscale image of specified pixel type from any image src.
Definition: vil_convert.h:996
unsigned vil_pixel_format_num_components(enum vil_pixel_format f)
Return the number of components in pixel format f.
Various image copying functions.
void vil_convert_stretch_range(const vil_image_view< T > &src, vil_image_view< vxl_byte > &dest)
Convert src to byte image dest by stretching to range [0,255].
Definition: vil_convert.h:530
void vil_convert_cast(const vil_image_view< inP > &src, vil_image_view< outP > &dest)
Cast one pixel type to another.
Definition: vil_convert.h:245
void operator()(vil_rgb< inP > v, outP &d) const
Definition: vil_convert.h:462
#define docase(T)
This is the appropriate pixel type for RGBA colour images.
Definition: vil_fwd.h:15
vil_convert_rgb_to_grey_pixel(double rw, double gw, double bw)
Definition: vil_convert.h:459
unsigned nplanes() const
Number of planes.
void vil_convert_round(const vil_image_view< inP > &src, vil_image_view< outP > &dest)
Convert one pixel type to another with rounding.
Definition: vil_convert.h:443
vil_pixel_format pixel_format() const override
Return a description of the concrete data pixel type.
void vil_convert_planes_to_grey(const vil_image_view< inP > &src, vil_image_view< outP > &dest, double rw=0.2125, double gw=0.7154, double bw=0.0721)
Convert first three planes of src image to grey, assuming rgb.
Definition: vil_convert.h:512
vil_image_view_base_sptr vil_convert_to_component_order(const vil_image_view_base_sptr &src)
Force data to be suitable for viewing as multi component view.
Definition: vil_convert.h:878
void vil_exception_warning(T exception)
Throw an exception indicating a potential problem.
Definition: vil_exception.h:37
T r
Definition: vil_rgb.h:58
#define macro(F, T)
void operator()(In v, Out &d) const
Definition: vil_convert.h:428
vil_pixel_format vil_pixel_format_of(T)
The pixel format enumeration corresponding to the C++ type.
void vil_math_value_range(const vil_image_view< T > &view, T &min_value, T &max_value)
Compute minimum and maximum values over view.
Definition: vil_math.h:28
std::complex<double> is a scalar for vil's purposes.
This is the appropriate pixel type for 24-bit colour images.
Definition: vil_fwd.h:14
void vil_convert_merge_alpha(const vil_image_view< inP > &src, vil_image_view< outP > &dest, const unsigned nplanes)
Convert images with alpha plane (variable or binary) to images without alpha plane.
Definition: vil_convert.h:470
void clear()
Make empty.