58 #include <pcl/Diagnostics.h>
71 #ifndef __PCL_IMAGE_NO_BITMAP
72 # ifdef __PCL_BUILDING_PIXINSIGHT_APPLICATION
73 # ifndef __PI_Bitmap_h
74 # include <API/Bitmap.h>
78 # ifndef __PCL_Bitmap_h
82 # ifndef __PCL_Color_h
87 #ifdef __PCL_BUILDING_PIXINSIGHT_APPLICATION
176 return op >= Add && op <= Dif;
185 return op >= Or && op <= Xnor;
194 return op == Mov || op == Min || op == Max;
203 return op >= ColorBurn && op <= Exclusion;
214 #define m_pixelData m_data->data
215 #define m_channelData( c ) reinterpret_cast<sample*>( PCL_ASSUME_ALIGNED_32( m_pixelData[c] ) )
216 #define m_allocator m_data->allocator
218 #define m_width m_geometry->width
219 #define m_height m_geometry->height
220 #define m_numberOfChannels m_geometry->numberOfChannels
222 #define m_colorSpace m_color->colorSpace
223 #define m_RGBWS m_color->RGBWS
225 #define m_channel m_selected.channel
226 #define m_lastChannel m_selected.lastChannel
227 #define m_point m_selected.point
228 #define m_rectangle m_selected.rectangle
229 #define m_clipLow m_selected.clipLow
230 #define m_clipHigh m_selected.clipHigh
231 #define m_clippedLow m_selected.clippedLow
232 #define m_clippedHigh m_selected.clippedHigh
305 using sample =
typename pixel_traits::sample;
312 using color_space = AbstractImage::color_space;
325 using image_op = ImageOp::value_type;
394 m_image->EnsureUnique();
395 if ( m_image->ParseChannel( channel ) )
397 m_iterator = (*m_image)[channel];
398 m_end = m_iterator + m_image->NumberOfPixels();
441 return m_image !=
nullptr && m_iterator !=
nullptr;
467 operator bool() const noexcept
469 return m_iterator < m_end;
595 return i.m_iterator - j.m_iterator;
604 return i.m_iterator - j;
613 return i - j.m_iterator;
622 return i.m_iterator == j.m_iterator;
631 return i.m_iterator == j;
640 return i == j.m_iterator;
649 return i.m_iterator < j.m_iterator;
657 return i.m_iterator < j;
665 return i < j.m_iterator;
670 image_type* m_image =
nullptr;
671 sample* __restrict__ m_iterator =
nullptr;
672 const sample* __restrict__ m_end =
nullptr;
728 if ( m_image->ParseChannel( channel ) )
730 m_iterator = (*m_image)[channel];
731 m_end = m_iterator + m_image->NumberOfPixels();
766 : m_image( i.m_image )
767 , m_iterator( i.m_iterator )
784 m_iterator = i.m_iterator;
800 return m_image !=
nullptr && m_iterator !=
nullptr;
828 operator bool() const noexcept
830 return m_iterator < m_end;
956 return i.m_iterator - j.m_iterator;
965 return i.m_iterator - j;
974 return i - j.m_iterator;
983 return i.m_iterator == j.m_iterator;
992 return i.m_iterator == j;
1001 return i == j.m_iterator;
1010 return i.m_iterator < j.m_iterator;
1018 return i.m_iterator < j;
1026 return i < j.m_iterator;
1031 const image_type* m_image =
nullptr;
1032 const sample* __restrict__ m_iterator =
nullptr;
1033 const sample* __restrict__ m_end =
nullptr;
1038 template <
class image_type,
class sample_po
inter>
1039 class roi_sample_iterator_base
1043 image_type* m_image =
nullptr;
1044 sample_pointer m_iterator =
nullptr;
1045 sample_pointer m_rowBegin =
nullptr;
1046 sample_pointer m_rowEnd =
nullptr;
1047 sample_pointer m_end =
nullptr;
1049 roi_sample_iterator_base() =
default;
1051 roi_sample_iterator_base( image_type& image,
const Rect& rect,
int channel )
1055 if ( m_image->ParseRect( r ) )
1057 if ( m_image->ParseChannel( channel ) )
1059 m_iterator = m_rowBegin = m_image->PixelAddress( r.
x0, r.
y0, channel );
1060 m_rowEnd = m_rowBegin + r.
Width();
1061 m_end = m_rowEnd + ((r.
Height() - 1)*m_image->Width());
1066 roi_sample_iterator_base( image_type& image, sample_pointer i, sample_pointer j )
1071 m_iterator = m_rowBegin = i;
1072 m_rowEnd = m_rowBegin + (j - i)%m_image->Width();
1076 roi_sample_iterator_base(
const roi_sample_iterator_base& i ) =
default;
1078 roi_sample_iterator_base& operator =(
const roi_sample_iterator_base& ) =
default;
1080 void Increment() noexcept
1082 if ( ++m_iterator == m_rowEnd )
1084 m_rowBegin += m_image->Width();
1085 m_rowEnd += m_image->Width();
1086 m_iterator = m_rowBegin;
1090 void Decrement() noexcept
1092 if ( m_iterator == m_rowBegin )
1094 m_rowBegin -= m_image->Width();
1095 m_rowEnd -= m_image->Width();
1096 m_iterator = m_rowEnd;
1101 void MoveBy(
int cols,
int rows ) noexcept
1103 cols += m_iterator - m_rowBegin;
1106 int w = m_rowEnd - m_rowBegin;
1113 int dy = rows * m_image->Width();
1116 m_iterator = m_rowBegin + cols;
1151 using iterator_base = roi_sample_iterator_base<GenericImage<P>,
sample*>;
1181 : iterator_base( image.EnsureUnique(), rect, channel )
1202 : iterator_base( image, i, j )
1222 return this->m_image !=
nullptr && this->m_iterator !=
nullptr;
1230 return *this->m_image;
1238 return this->m_iterator;
1247 operator bool() const noexcept
1249 return this->m_iterator < this->m_end;
1258 return *this->m_iterator;
1318 int w = this->m_rowEnd - this->m_rowBegin;
1319 iterator_base::MoveBy( delta%w, delta/w );
1334 int w = this->m_rowEnd - this->m_rowBegin;
1335 iterator_base::MoveBy( -delta%w, -delta/w );
1349 iterator_base::MoveBy( dx, dy );
1392 return i.m_iterator == j.m_iterator;
1401 return i.m_iterator == j;
1410 return i == j.m_iterator;
1419 return i.m_iterator < j.m_iterator;
1427 return i.m_iterator < j;
1435 return i < j.m_iterator;
1472 using iterator_base = roi_sample_iterator_base<const GenericImage<P>,
const sample*>;
1502 : iterator_base( image, rect, channel )
1523 : iterator_base( image, i, j )
1536 : iterator_base( i.m_image, i.m_rowBegin, i.m_end )
1551 this->m_image = i.m_image;
1552 this->m_iterator = i.m_iterator;
1553 this->m_rowBegin = i.m_rowBegin;
1554 this->m_rowEnd = i.m_rowEnd;
1555 this->m_end = i.m_end;
1570 return this->m_image !=
nullptr && this->m_iterator !=
nullptr;
1579 return *this->m_image;
1588 return this->m_iterator;
1597 operator bool() const noexcept
1599 return this->m_iterator < this->m_end;
1608 return *this->m_iterator;
1668 int w = this->m_rowEnd - this->m_rowBegin;
1669 iterator_base::MoveBy( delta%w, delta/w );
1684 int w = this->m_rowEnd - this->m_rowBegin;
1685 iterator_base::MoveBy( -delta%w, -delta/w );
1699 iterator_base::MoveBy( dx, dy );
1742 return i.m_iterator == j.m_iterator;
1751 return i.m_iterator == j;
1760 return i == j.m_iterator;
1769 return i.m_iterator < j.m_iterator;
1777 return i.m_iterator < j;
1785 return i < j.m_iterator;
1791 template <
class image_type,
class iterator_base,
class sample_po
inter,
class filter_type>
1792 class filter_sample_iterator_base :
public iterator_base
1796 filter_type m_filter;
1797 sample_pointer m_begin =
nullptr;
1799 filter_sample_iterator_base() =
default;
1801 filter_sample_iterator_base( image_type& image,
const filter_type& filter,
int channel )
1802 : iterator_base( image, channel )
1803 , m_filter( filter )
1804 , m_begin( iterator_base::m_iterator )
1806 JumpToNextValidSample();
1809 filter_sample_iterator_base( image_type& image,
const filter_type& filter, sample_pointer i, sample_pointer j )
1810 : iterator_base( image, i, j )
1811 , m_filter( filter )
1812 , m_begin( iterator_base::m_iterator )
1814 JumpToNextValidSample();
1817 filter_sample_iterator_base(
const iterator_base& i,
const filter_type& filter )
1818 : iterator_base( i )
1819 , m_filter( filter )
1820 , m_begin( iterator_base::m_iterator )
1822 JumpToNextValidSample();
1825 filter_sample_iterator_base(
const filter_sample_iterator_base& ) =
default;
1827 filter_sample_iterator_base& operator =(
const filter_sample_iterator_base& ) =
default;
1829 filter_sample_iterator_base& operator =(
const iterator_base& i ) noexcept
1831 (void)iterator_base::operator =( i );
1832 JumpToNextValidSample();
1836 void JumpToNextValidSample() noexcept
1838 while ( this->m_iterator < this->m_end && !this->m_filter( *this->m_iterator ) )
1842 void JumpToPrevValidSample() noexcept
1844 while ( this->m_iterator > this->m_begin && !this->m_filter( *this->m_iterator ) )
1886 public filter_sample_iterator_base<GenericImage<P>, sample_iterator, sample*, F>
1935 : iterator_base( image.EnsureUnique(), filter, channel )
1958 : iterator_base( image, filter, i, j )
1967 : iterator_base( i, filter )
1987 (void)iterator_base::operator =( i );
1997 return this->m_image !=
nullptr && this->m_iterator !=
nullptr;
2005 return *this->m_image;
2014 return this->m_filter;
2023 return this->m_filter;
2031 return this->m_iterator;
2041 operator bool() const noexcept
2043 return this->m_iterator < this->m_end;
2052 return *this->m_iterator;
2063 this->JumpToNextValidSample();
2074 sample* __restrict__ i0 = this->m_iterator++;
2075 this->JumpToNextValidSample();
2087 this->JumpToPrevValidSample();
2098 sample* __restrict__ i0 = this->m_iterator--;
2099 this->JumpToPrevValidSample();
2112 this->m_iterator += delta;
2113 this->JumpToNextValidSample();
2126 this->m_iterator -= delta;
2127 this->JumpToPrevValidSample();
2141 this->m_iterator += d;
2143 this->JumpToNextValidSample();
2145 this->JumpToPrevValidSample();
2182 return i.m_iterator - j.m_iterator;
2191 return i.m_iterator == j.m_iterator;
2200 return i.m_iterator == j;
2209 return i == j.m_iterator;
2218 return i.m_iterator < j.m_iterator;
2226 return i.m_iterator < j;
2234 return i < j.m_iterator;
2275 public filter_sample_iterator_base<const GenericImage<P>, const_sample_iterator, const sample*, F>
2324 : iterator_base( image, filter, channel )
2347 : iterator_base( image, filter, i, j )
2356 : iterator_base( i.m_image, filter, i.m_iterator, i.m_end )
2365 : iterator_base( i, filter )
2374 : iterator_base( i )
2394 (void)const_sample_iterator::operator =( i );
2395 this->JumpToNextValidSample();
2405 (void)iterator_base::operator =( i );
2415 return this->m_image !=
nullptr && this->m_iterator !=
nullptr;
2424 return *this->m_image;
2433 return this->m_filter;
2442 return this->m_filter;
2451 return this->m_iterator;
2461 operator bool() const noexcept
2463 return this->m_iterator < this->m_end;
2472 return *this->m_iterator;
2483 this->JumpToNextValidSample();
2494 sample* __restrict__ i0 = this->m_iterator++;
2495 this->JumpToNextValidSample();
2507 this->JumpToPrevValidSample();
2518 sample* __restrict__ i0 = this->m_iterator--;
2519 this->JumpToPrevValidSample();
2532 this->m_iterator += delta;
2533 this->JumpToNextValidSample();
2546 this->m_iterator -= delta;
2547 this->JumpToPrevValidSample();
2561 this->m_iterator += d;
2563 this->JumpToNextValidSample();
2565 this->JumpToPrevValidSample();
2602 return i.m_iterator - j.m_iterator;
2611 return i.m_iterator == j.m_iterator;
2620 return i.m_iterator == j;
2629 return i == j.m_iterator;
2638 return i.m_iterator < j.m_iterator;
2646 return i.m_iterator < j;
2654 return i < j.m_iterator;
2660 template <
class image_type,
class sample_po
inter,
class filter_type>
2661 class roi_filter_sample_iterator_base :
public roi_sample_iterator_base<image_type, sample_pointer>
2665 using roi_iterator_base = roi_sample_iterator_base<image_type, sample_pointer>;
2667 filter_type m_filter;
2668 sample_pointer m_begin =
nullptr;
2670 roi_filter_sample_iterator_base() =
default;
2672 roi_filter_sample_iterator_base( image_type& image,
const filter_type& filter,
const Rect& rect,
int channel )
2673 : roi_iterator_base( image, rect, channel )
2674 , m_filter( filter )
2675 , m_begin( roi_iterator_base::m_iterator )
2677 JumpToNextValidSample();
2680 roi_filter_sample_iterator_base( image_type& image,
const filter_type& filter, sample_pointer i, sample_pointer j )
2681 : roi_iterator_base( image, i, j )
2682 , m_filter( filter )
2683 , m_begin( roi_iterator_base::m_iterator )
2685 JumpToNextValidSample();
2688 roi_filter_sample_iterator_base(
const roi_iterator_base& i,
const filter_type& filter )
2689 : roi_iterator_base( i )
2690 , m_filter( filter )
2691 , m_begin( roi_iterator_base::m_iterator )
2693 JumpToNextValidSample();
2696 roi_filter_sample_iterator_base(
const roi_filter_sample_iterator_base& ) =
default;
2698 roi_filter_sample_iterator_base& operator =(
const roi_filter_sample_iterator_base& i ) =
default;
2700 roi_filter_sample_iterator_base& operator =(
const roi_iterator_base& i ) noexcept
2702 (void)roi_iterator_base::operator =( i );
2703 JumpToNextValidSample();
2707 void JumpToNextValidSample() noexcept
2709 while ( this->m_iterator < this->m_end && !this->m_filter( *this->m_iterator ) )
2710 roi_iterator_base::Increment();
2713 void JumpToPrevValidSample() noexcept
2715 while ( this->m_iterator > this->m_begin && !this->m_filter( *this->m_iterator ) )
2716 roi_iterator_base::Decrement();
2758 using iterator_base = roi_filter_sample_iterator_base<GenericImage<P>,
sample*, F>;
2791 : iterator_base( image.EnsureUnique(), filter, rect, channel )
2814 : iterator_base( image, filter, i, j )
2823 : iterator_base( i, filter )
2843 (void)iterator_base::operator =( i );
2853 return this->m_image !=
nullptr && this->m_iterator !=
nullptr;
2861 return *this->m_image;
2870 return this->m_filter;
2879 return this->m_filter;
2887 return this->m_iterator;
2896 operator bool() const noexcept
2898 return this->m_iterator < this->m_end;
2907 return *this->m_iterator;
2918 this->JumpToNextValidSample();
2931 this->JumpToNextValidSample();
2943 this->JumpToPrevValidSample();
2956 this->JumpToPrevValidSample();
2971 int w = this->m_rowEnd - this->m_rowBegin;
2972 return MoveBy( delta%w, delta/w );
2986 int w = this->m_rowEnd - this->m_rowBegin;
2987 return MoveBy( -delta%w, -delta/w );
3000 sample* __restrict__ i0 = this->m_iterator;
3001 iterator_base::MoveBy( dx, dy );
3002 if ( this->m_iterator >= i0 )
3003 this->JumpToNextValidSample();
3005 this->JumpToPrevValidSample();
3048 return i.m_iterator == j.m_iterator;
3057 return i.m_iterator == j;
3066 return i == j.m_iterator;
3075 return i.m_iterator < j.m_iterator;
3083 return i.m_iterator < j;
3091 return i < j.m_iterator;
3133 using iterator_base = roi_filter_sample_iterator_base<const GenericImage<P>,
const sample*, F>;
3166 : iterator_base( image, filter, rect, channel )
3189 : iterator_base( image, filter, i, j )
3198 : iterator_base( i, filter )
3218 (void)iterator_base::operator =( i );
3228 return this->m_image !=
nullptr && this->m_iterator !=
nullptr;
3237 return *this->m_image;
3246 return this->m_filter;
3255 return this->m_filter;
3264 return this->m_iterator;
3273 operator bool() const noexcept
3275 return this->m_iterator < this->m_end;
3284 return *this->m_iterator;
3295 this->JumpToNextValidSample();
3308 this->JumpToNextValidSample();
3320 this->JumpToPrevValidSample();
3333 this->JumpToPrevValidSample();
3348 int w = this->m_rowEnd - this->m_rowBegin;
3349 return MoveBy( delta%w, delta/w );
3363 int w = this->m_rowEnd - this->m_rowBegin;
3364 return MoveBy( -delta%w, -delta/w );
3377 const sample* __restrict__ i0 = this->m_iterator;
3378 iterator_base::MoveBy( dx, dy );
3379 if ( this->m_iterator >= i0 )
3380 this->JumpToNextValidSample();
3382 this->JumpToPrevValidSample();
3425 return i.m_iterator == j.m_iterator;
3434 return i.m_iterator == j;
3443 return i == j.m_iterator;
3452 return i.m_iterator < j.m_iterator;
3460 return i.m_iterator < j;
3468 return i < j.m_iterator;
3515 m_image->EnsureUnique();
3516 if ( !m_image->IsEmpty() )
3519 for (
int i = 0; i < m_iterator.Length(); ++i )
3520 m_iterator[i] = (*m_image)[i];
3521 m_end = m_iterator[0] + m_image->NumberOfPixels();
3541 return m_image !=
nullptr && !m_iterator.IsEmpty();
3558 return m_iterator[channel];
3566 operator bool() const noexcept
3568 return m_iterator[0] < m_end;
3575 sample& operator [](
int channel )
const noexcept
3577 return *m_iterator[channel];
3586 for (
int i = 0; i < m_iterator.Length(); ++i )
3599 for (
int i = 0; i < m_iterator.Length(); ++i )
3610 for (
int i = 0; i < m_iterator.Length(); ++i )
3623 for (
int i = 0; i < m_iterator.Length(); ++i )
3637 for (
int i = 0; i < m_iterator.Length(); ++i )
3638 m_iterator[i] += delta;
3651 for (
int i = 0; i < m_iterator.Length(); ++i )
3652 m_iterator[i] -= delta;
3707 return i.m_iterator[0] - j.m_iterator[0];
3716 return i.m_iterator[0] == j.m_iterator[0];
3725 return i.m_iterator[0] < j.m_iterator[0];
3730 image_type* m_image =
nullptr;
3731 iterator_type m_iterator;
3732 const sample* __restrict__ m_end =
nullptr;
3778 if ( !m_image->IsEmpty() )
3781 for (
int i = 0; i < m_iterator.Length(); ++i )
3782 m_iterator[i] = (*m_image)[i];
3783 m_end = m_iterator[0] + m_image->NumberOfPixels();
3803 return m_image !=
nullptr && !m_iterator.IsEmpty();
3821 return m_iterator[channel];
3829 operator bool() const noexcept
3831 return m_iterator[0] < m_end;
3838 const sample& operator [](
int channel )
const noexcept
3840 return *m_iterator[channel];
3849 for (
int i = 0; i < m_iterator.Length(); ++i )
3862 for (
int i = 0; i < m_iterator.Length(); ++i )
3873 for (
int i = 0; i < m_iterator.Length(); ++i )
3886 for (
int i = 0; i < m_iterator.Length(); ++i )
3900 for (
int i = 0; i < m_iterator.Length(); ++i )
3901 m_iterator[i] += delta;
3914 for (
int i = 0; i < m_iterator.Length(); ++i )
3915 m_iterator[i] -= delta;
3970 return i.m_iterator[0] - j.m_iterator[0];
3979 return i.m_iterator[0] == j.m_iterator[0];
3988 return i.m_iterator[0] < j.m_iterator[0];
3993 const image_type* m_image =
nullptr;
3994 iterator_type m_iterator;
3995 const sample* __restrict__ m_end =
nullptr;
4000 template <
class image_type,
class sample_po
inter>
4001 class roi_pixel_iterator_base
4007 image_type* m_image =
nullptr;
4008 iterator_type m_iterator;
4009 sample_pointer m_rowBegin =
nullptr;
4010 sample_pointer m_rowEnd =
nullptr;
4011 sample_pointer m_end =
nullptr;
4013 roi_pixel_iterator_base() =
default;
4015 roi_pixel_iterator_base( image_type& image,
const Rect& rect )
4019 if ( m_image->ParseRect( r ) )
4021 m_iterator = iterator_type( m_image->NumberOfChannels() );
4022 for (
int i = 0; i < m_iterator.Length(); ++i )
4023 m_iterator[i] = m_image->PixelAddress( r.
x0, r.
y0, i );
4024 m_rowBegin = m_iterator[0];
4025 m_rowEnd = m_rowBegin + r.
Width();
4026 m_end = m_rowEnd + ((r.
Height() - 1)*m_image->Width());
4030 roi_pixel_iterator_base(
const roi_pixel_iterator_base& ) =
default;
4032 roi_pixel_iterator_base& operator =(
const roi_pixel_iterator_base& ) =
default;
4034 void Increment() noexcept
4036 for (
int i = 0; i < m_iterator.Length(); ++i )
4038 if ( m_iterator[0] == m_rowEnd )
4040 int w = m_rowEnd - m_rowBegin;
4041 for (
int i = 0; i < m_iterator.Length(); ++i )
4042 m_iterator[i] += m_image->Width() - w;
4043 m_rowBegin += m_image->Width();
4044 m_rowEnd += m_image->Width();
4048 void Decrement() noexcept
4050 if ( m_iterator[0] == m_rowBegin )
4052 int w = m_rowEnd - m_rowBegin;
4053 for (
int i = 0; i < m_iterator.Length(); ++i )
4054 m_iterator[i] -= m_image->Width() - w;
4055 m_rowBegin -= m_image->Width();
4056 m_rowEnd -= m_image->Width();
4058 for (
int i = 0; i < m_iterator.Length(); ++i )
4062 void MoveBy(
int cols,
int rows ) noexcept
4064 int dx = m_iterator[0] - m_rowBegin;
4065 for (
int i = 0; i < m_iterator.Length(); ++i )
4066 m_iterator[i] -= dx;
4070 int w = m_rowEnd - m_rowBegin;
4077 int dy = rows * m_image->Width();
4078 for (
int i = 0; i < m_iterator.Length(); ++i )
4079 m_iterator[i] += dy + cols;
4115 using iterator_base = roi_pixel_iterator_base<GenericImage<P>,
sample*>;
4137 : iterator_base( image.EnsureUnique(), rect )
4157 return this->m_image !=
nullptr && !this->m_iterator.IsEmpty();
4165 return *this->m_image;
4174 return this->m_iterator[channel];
4183 operator bool() const noexcept
4185 return this->m_iterator[0] < this->m_end;
4192 sample& operator [](
int channel )
const noexcept
4194 return *this->m_iterator[channel];
4254 int w = this->m_rowEnd - this->m_rowBegin;
4255 iterator_base::MoveBy( delta%w, delta/w );
4270 int w = this->m_rowEnd - this->m_rowBegin;
4271 iterator_base::MoveBy( -delta%w, -delta/w );
4285 iterator_base::MoveBy( dx, dy );
4328 return i.m_iterator[0] == j.m_iterator[0];
4337 return i.m_iterator[0] < j.m_iterator[0];
4371 using iterator_base = roi_pixel_iterator_base<const GenericImage<P>,
const sample*>;
4393 : iterator_base( image, rect )
4413 return this->m_image !=
nullptr && !this->m_iterator.IsEmpty();
4422 return *this->m_image;
4431 return this->m_iterator[channel];
4440 operator bool() const noexcept
4442 return this->m_iterator[0] < this->m_end;
4449 const sample& operator [](
int channel )
const noexcept
4451 return *this->m_iterator[channel];
4511 int w = this->m_rowEnd - this->m_rowBegin;
4512 iterator_base::MoveBy( delta%w, delta/w );
4527 int w = this->m_rowEnd - this->m_rowBegin;
4528 iterator_base::MoveBy( -delta%w, -delta/w );
4542 iterator_base::MoveBy( dx, dy );
4585 return i.m_iterator[0] == j.m_iterator[0];
4594 return i.m_iterator[0] < j.m_iterator[0];
4600 template <
class image_type,
class iterator_base,
class sample_po
inter,
class filter_type>
4601 class filter_pixel_iterator_base :
public iterator_base
4605 filter_type m_filter;
4606 sample_pointer m_begin =
nullptr;
4608 filter_pixel_iterator_base() =
default;
4610 filter_pixel_iterator_base( image_type& image,
const filter_type& filter )
4611 : iterator_base( image )
4612 , m_filter( filter )
4613 , m_begin( iterator_base::m_iterator )
4615 JumpToNextValidSample();
4618 filter_pixel_iterator_base(
const iterator_base& i,
const filter_type& filter )
4619 : iterator_base( i )
4620 , m_filter( filter )
4621 , m_begin( iterator_base::m_iterator )
4623 JumpToNextValidSample();
4626 filter_pixel_iterator_base(
const filter_pixel_iterator_base& ) =
default;
4628 filter_pixel_iterator_base& operator =(
const filter_pixel_iterator_base& ) =
default;
4630 filter_pixel_iterator_base& operator =(
const iterator_base& i ) noexcept
4632 (void)iterator_base::operator =( i );
4633 JumpToNextValidSample();
4636 void JumpToNextValidSample() noexcept
4638 while ( this->m_iterator[0] < this->m_end && !this->m_filter( this->m_iterator ) )
4639 for (
int i = 0; i < this->m_iterator.Length(); ++i )
4640 ++this->m_iterator[i];
4643 void JumpToPrevValidSample() noexcept
4645 while ( this->m_iterator[0] > this->m_begin && !this->m_filter( this->m_iterator ) )
4646 for (
int i = 0; i < this->m_iterator.Length(); ++i )
4647 --this->m_iterator[i];
4690 public filter_pixel_iterator_base<GenericImage<P>, pixel_iterator, sample*, F>
4731 : iterator_base( image.EnsureUnique(), filter )
4740 : iterator_base( i, filter )
4760 (void)iterator_base::operator =( i );
4770 return this->m_image !=
nullptr && !this->m_iterator.IsEmpty();
4778 return *this->m_image;
4787 return this->m_filter;
4796 return this->m_filter;
4805 return this->m_iterator[channel];
4813 operator bool() const noexcept
4815 return this->m_iterator[0] < this->m_end;
4822 sample& operator [](
int channel )
const noexcept
4824 return *this->m_iterator[channel];
4834 for (
int i = 0; i < this->m_iterator.Length(); ++i )
4835 ++this->m_iterator[i];
4836 this->JumpToNextValidSample();
4848 for (
int i = 0; i < this->m_iterator.Length(); ++i )
4849 ++this->m_iterator[i];
4850 this->JumpToNextValidSample();
4861 for (
int i = 0; i < this->m_iterator.Length(); ++i )
4862 --this->m_iterator[i];
4863 this->JumpToPrevValidSample();
4875 for (
int i = 0; i < this->m_iterator.Length(); ++i )
4876 --this->m_iterator[i];
4877 this->JumpToPrevValidSample();
4890 for (
int i = 0; i < this->m_iterator.Length(); ++i )
4891 this->m_iterator[i] += delta;
4892 this->JumpToNextValidSample();
4905 for (
int i = 0; i < this->m_iterator.Length(); ++i )
4906 this->m_iterator[i] -= delta;
4907 this->JumpToPrevValidSample();
4921 for (
int i = 0; i < this->m_iterator.Length(); ++i )
4922 this->m_iterator[i] += d;
4924 this->JumpToNextValidSample();
4926 this->JumpToPrevValidSample();
4969 return i.m_iterator[0] == j.m_iterator[0];
4978 return i.m_iterator[0] < j.m_iterator[0];
5021 public filter_pixel_iterator_base<const GenericImage<P>, const_pixel_iterator, const sample*, F>
5062 : iterator_base( image, filter )
5071 : iterator_base( i, filter )
5091 (void)iterator_base::operator =( i );
5101 return this->m_image !=
nullptr && !this->m_iterator.IsEmpty();
5110 return *this->m_image;
5119 return this->m_filter;
5128 return this->m_filter;
5137 return this->m_iterator[channel];
5145 operator bool() const noexcept
5147 return this->m_iterator[0] < this->m_end;
5154 const sample& operator [](
int channel )
const noexcept
5156 return *this->m_iterator[channel];
5166 for (
int i = 0; i < this->m_iterator.Length(); ++i )
5167 ++this->m_iterator[i];
5168 this->JumpToNextValidSample();
5180 for (
int i = 0; i < this->m_iterator.Length(); ++i )
5181 ++this->m_iterator[i];
5182 this->JumpToNextValidSample();
5193 for (
int i = 0; i < this->m_iterator.Length(); ++i )
5194 --this->m_iterator[i];
5195 this->JumpToPrevValidSample();
5207 for (
int i = 0; i < this->m_iterator.Length(); ++i )
5208 --this->m_iterator[i];
5209 this->JumpToPrevValidSample();
5222 for (
int i = 0; i < this->m_iterator.Length(); ++i )
5223 this->m_iterator[i] += delta;
5224 this->JumpToNextValidSample();
5237 for (
int i = 0; i < this->m_iterator.Length(); ++i )
5238 this->m_iterator[i] -= delta;
5239 this->JumpToPrevValidSample();
5253 for (
int i = 0; i < this->m_iterator.Length(); ++i )
5254 this->m_iterator[i] += d;
5256 this->JumpToNextValidSample();
5258 this->JumpToPrevValidSample();
5301 return i.m_iterator[0] == j.m_iterator[0];
5310 return i.m_iterator[0] < j.m_iterator[0];
5316 template <
class image_type,
class sample_po
inter,
class filter_type>
5317 class roi_filter_pixel_iterator_base :
public roi_pixel_iterator_base<image_type, sample_pointer>
5321 using roi_iterator_base = roi_pixel_iterator_base<image_type, sample_pointer>;
5323 filter_type m_filter;
5324 sample_pointer m_begin =
nullptr;
5326 roi_filter_pixel_iterator_base() =
default;
5328 roi_filter_pixel_iterator_base( image_type& image,
const filter_type& filter,
const Rect& rect )
5329 : roi_iterator_base( image, rect )
5330 , m_filter( filter )
5331 , m_begin( roi_iterator_base::m_iterator )
5333 JumpToNextValidSample();
5336 roi_filter_pixel_iterator_base(
const roi_iterator_base& i,
const filter_type& filter )
5337 : roi_iterator_base( i )
5338 , m_filter( filter )
5339 , m_begin( roi_iterator_base::m_iterator )
5341 JumpToNextValidSample();
5344 roi_filter_pixel_iterator_base(
const roi_filter_pixel_iterator_base& ) =
default;
5346 roi_filter_pixel_iterator_base& operator =(
const roi_filter_pixel_iterator_base& ) =
default;
5348 roi_filter_pixel_iterator_base& operator =(
const roi_iterator_base& i ) noexcept
5350 (void)roi_iterator_base::operator =( i );
5351 JumpToNextValidSample();
5355 void JumpToNextValidSample() noexcept
5357 while ( this->m_iterator[0] < this->m_end && !this->m_filter( this->m_iterator ) )
5358 roi_iterator_base::Increment();
5361 void JumpToPrevValidSample() noexcept
5363 while ( this->m_iterator[0] > this->m_begin && !this->m_filter( this->m_iterator ) )
5364 roi_iterator_base::Decrement();
5406 using iterator_base = roi_filter_pixel_iterator_base<GenericImage<P>,
sample*, F>;
5431 : iterator_base( image.EnsureUnique(), filter, rect )
5440 : iterator_base( i, filter )
5459 (void)iterator_base::operator =( i );
5469 return this->m_image !=
nullptr && !this->m_iterator.IsEmpty();
5477 return *this->m_image;
5486 return this->m_filter;
5495 return this->m_filter;
5504 return this->m_iterator[channel];
5513 operator bool() const noexcept
5515 return this->m_iterator[0] < this->m_end;
5522 sample& operator [](
int channel )
const noexcept
5524 return *this->m_iterator[channel];
5535 this->JumpToNextValidSample();
5548 this->JumpToNextValidSample();
5560 this->JumpToPrevValidSample();
5573 this->JumpToPrevValidSample();
5588 int w = this->m_rowEnd - this->m_rowBegin;
5589 return MoveBy( delta%w, delta/w );
5603 int w = this->m_rowEnd - this->m_rowBegin;
5604 return MoveBy( -delta%w, -delta/w );
5617 sample* __restrict__ i0 = this->m_iterator[0];
5618 iterator_base::MoveBy( dx, dy );
5619 if ( this->m_iterator[0] >= i0 )
5620 this->JumpToNextValidSample();
5622 this->JumpToPrevValidSample();
5665 return i.m_iterator[0] == j.m_iterator[0];
5674 return i.m_iterator[0] < j.m_iterator[0];
5716 using iterator_base = roi_filter_pixel_iterator_base<const GenericImage<P>,
const sample*, F>;
5742 : iterator_base( image, filter, rect )
5751 : iterator_base( i, filter )
5771 (void)iterator_base::operator =( i );
5781 return this->m_image !=
nullptr && !this->m_iterator.IsEmpty();
5790 return *this->m_image;
5799 return this->m_filter;
5808 return this->m_filter;
5817 return this->m_iterator[channel];
5826 operator bool() const noexcept
5828 return this->m_iterator[0] < this->m_end;
5835 const sample& operator [](
int channel )
const noexcept
5837 return *this->m_iterator[channel];
5848 this->JumpToNextValidSample();
5861 this->JumpToNextValidSample();
5873 this->JumpToPrevValidSample();
5886 this->JumpToPrevValidSample();
5901 int w = this->m_rowEnd - this->m_rowBegin;
5902 return MoveBy( delta%w, delta/w );
5916 int w = this->m_rowEnd - this->m_rowBegin;
5917 return MoveBy( -delta%w, -delta/w );
5930 const sample* __restrict__ i0 = this->m_iterator[0];
5931 iterator_base::MoveBy( dx, dy );
5932 if ( this->m_iterator[0] >= i0 )
5933 this->JumpToNextValidSample();
5935 this->JumpToPrevValidSample();
5978 return i.m_iterator[0] == j.m_iterator[0];
5987 return i.m_iterator[0] < j.m_iterator[0];
5999 return pixel_traits::IsFloatSample();
6008 return pixel_traits::IsComplexSample();
6017 return P::BytesPerSample();
6026 return P::BitsPerSample();
6039 return image.BitsPerSample() == BitsPerSample() &&
6040 image.IsFloatSample() == IsFloatSample() &&
6041 image.IsComplexSample() == IsComplexSample();
6062 m_data =
new Data(
this );
6099 image.m_data->Attach(
this );
6100 m_data = image.m_data;
6101 m_status = image.m_status;
6106 m_data =
new Data(
this );
6107 (void)Assign( image );
6115 , m_data( image.m_data )
6117 image.m_data =
nullptr;
6135 m_data =
new Data(
this );
6136 (void)Assign( image );
6182 m_data =
new Data(
this );
6183 (void)Assign( image, rect, firstChannel, lastChannel );
6204 GenericImage(
int width,
int height, color_space colorSpace = ColorSpace::Gray )
6206 m_data =
new Data(
this );
6227 m_data =
new Data(
this );
6252 m_data =
new Data(
this, handle );
6283 GenericImage(
void*,
int width,
int height, color_space colorSpace = ColorSpace::Gray )
6308 if ( m_data !=
nullptr )
6335 return m_data->IsShared();
6350 return m_data->IsUnique();
6367 if ( m_data->IsShared() )
6371 local->m_data->Allocate( m_width, m_height, m_numberOfChannels, m_colorSpace );
6372 local->m_RGBWS = m_RGBWS;
6373 local->m_selected = m_selected;
6374 local->m_savedSelections = m_savedSelections;
6375 local->m_status = m_status;
6376 for (
int c = 0; c < m_numberOfChannels; ++c )
6377 P::Copy( (*local)[c], m_channelData( c ), NumberOfPixels() );
6379 local->m_data->Attach(
this );
6381 m_data = local->m_data;
6403 if ( !m_data->IsUnique() )
6405 Data* newData = m_data->Clone(
this );
6446 m_data->SynchronizeWithSharedImage();
6485 int numberOfChannels = 1,
6486 color_space colorSpace = ColorSpace::Gray )
6488 if ( !m_data->IsUnique() )
6490 Data* newData =
new Data(
this );
6494 m_data->Allocate( width, height, numberOfChannels, colorSpace );
6510 int numberOfChannels = 1,
6511 color_space colorSpace = ColorSpace::Gray )
6513 return AllocateData( rect.
Width(), rect.
Height(), numberOfChannels, colorSpace );
6529 if ( !m_data->IsEmpty() )
6530 if ( m_data->IsUnique() )
6531 m_data->Deallocate();
6534 Data* newData =
new Data(
this );
6598 int numberOfChannels = 1, color_space colorSpace = ColorSpace::Gray )
6600 if ( !m_data->IsUnique() )
6602 if ( m_data->IsShared() )
6603 throw Error(
"GenericImage::ImportData(): Invalid operation for an aliased shared image" );
6604 Data* newData =
new Data(
this );
6608 m_data->Import( data, width, height, numberOfChannels, colorSpace );
6649 if ( !m_data->IsUnique() )
6650 throw Error(
"GenericImage::ReleaseData(): Invalid operation for an aliased image" );
6651 sample** data = m_data->Release();
6664 return BytesPerSample() *
size_type( m_width );
6673 return BytesPerSample() * NumberOfPixels();
6684 return ChannelSize() *
size_type( m_numberOfChannels );
6704 return ChannelSize() * NumberOfAlphaChannels();
6723 PCL_PRECONDITION( 0 <= channel && channel < m_numberOfChannels )
6725 return m_channelData( channel );
6736 PCL_PRECONDITION( 0 <= channel && channel < m_numberOfChannels )
6737 return m_channelData( channel );
6743 operator bool() const noexcept
6745 return m_data !=
nullptr && !m_data->IsEmpty();
6760 PCL_PRECONDITION( 0 <= channel && channel < m_numberOfChannels )
6761 return PixelData( channel );
6770 const sample* operator [](
int channel )
const noexcept
6772 PCL_PRECONDITION( 0 <= channel && channel < m_numberOfChannels )
6773 return PixelData( channel );
6785 PCL_PRECONDITION( 0 < m_numberOfChannels )
6786 return PixelData( 0 );
6797 PCL_PRECONDITION( 0 < m_numberOfChannels )
6798 return PixelData( 0 );
6822 PCL_PRECONDITION( 0 <= channel && channel < m_numberOfChannels )
6823 PCL_PRECONDITION( 0 <= y && y < m_height )
6825 return m_channelData( channel ) + RowOffset( y );
6836 PCL_PRECONDITION( 0 <= channel && channel < m_numberOfChannels )
6837 PCL_PRECONDITION( 0 <= y && y < m_height )
6838 return m_channelData( channel ) + RowOffset( y );
6866 PCL_PRECONDITION( 0 <= channel && channel < m_numberOfChannels )
6867 PCL_PRECONDITION( 0 <= x && x < m_width )
6868 PCL_PRECONDITION( 0 <= y && y < m_height )
6870 return m_channelData( channel ) + PixelOffset( x, y );
6881 PCL_PRECONDITION( 0 <= channel && channel < m_numberOfChannels )
6882 PCL_PRECONDITION( 0 <= x && x < m_width )
6883 PCL_PRECONDITION( 0 <= y && y < m_height )
6884 return m_channelData( channel ) + PixelOffset( x, y );
6909 return PixelAddress( p.
x, p.
y, channel );
6921 return PixelAddress( p.
x, p.
y, channel );
6944 sample& operator ()(
int x,
int y,
int channel = 0 )
6946 return *PixelAddress( x, y, channel );
6965 sample operator ()(
int x,
int y,
int channel = 0 ) const noexcept
6967 return *PixelAddress( x, y, channel );
6989 return *PixelAddress( p, channel );
7007 return *PixelAddress( p, channel );
7019 return operator()( x, y, channel );
7031 return operator()( x, y, channel );
7043 return operator()( p, channel );
7056 return operator()( p, channel );
7151 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
7153 m_status = image.
Status();
7162 int n = 1 + lastChannel - firstChannel;
7171 if ( r == image.
Bounds() )
7172 for (
int c = 0; firstChannel <= lastChannel; ++c, ++firstChannel )
7173 P::Copy( m_channelData( c ), image[firstChannel], NumberOfPixels() );
7175 for (
int c = 0; firstChannel <= lastChannel; ++c, ++firstChannel )
7177 sample* f = m_channelData( c );
7179 for (
int y = 0; y < m_height; ++y, f += m_width, g += image.
Width() )
7180 P::Copy( f, g, m_width );
7187 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
7189 m_status = image.
Status();
7198 #define completeSelection (firstChannel == 0 && lastChannel == image.m_numberOfChannels-1 && r == image.Bounds())
7200 if ( m_data == image.m_data )
7203 if ( !completeSelection )
7205 GenericImage result( image, r, firstChannel, lastChannel );
7206 result.m_data->Attach(
this );
7208 m_data = result.m_data;
7216 if ( completeSelection )
7218 image.m_data->Attach(
this );
7220 m_data = image.m_data;
7225 #undef completeSelection
7227 int n = 1 + lastChannel - firstChannel;
7232 m_RGBWS = image.m_RGBWS;
7236 if ( r == image.
Bounds() )
7237 for (
int c = 0; firstChannel <= lastChannel; ++c, ++firstChannel )
7238 P::Copy( m_channelData( c ), image[firstChannel], NumberOfPixels() );
7240 for (
int c = 0; firstChannel <= lastChannel; ++c, ++firstChannel )
7242 sample* f = m_channelData( c );
7244 for (
int y = 0; y < m_height; ++y, f += m_width, g += image.m_width )
7245 P::Copy( f, g, m_width );
7260 return Assign( image );
7275 return Assign( image );
7278 #define TRANSFER_BODY() \
7279 if ( m_data != image.m_data ) \
7282 m_data = image.m_data; \
7283 (void)AbstractImage::operator =( image ); \
7284 image.m_data = nullptr; \
7320 #undef TRANSFER_BODY
7329 return Transfer( image );
7340 return Fill( scalar );
7348 x1.AbstractImage::Swap( x2 );
7354 #ifndef __PCL_NO_VECTOR_IMAGE_CONVERSION
7377 channel = m_channel;
7378 if ( y < 0 || y >= m_height || channel < 0 || channel >= m_numberOfChannels )
7381 P::Get( row.
Begin(), ScanLine( y, channel ), m_width );
7406 channel = m_channel;
7407 if ( x < 0 || x >= m_width || channel < 0 || channel >= m_numberOfChannels )
7410 const sample* v = PixelAddress( x, 0, channel );
7411 for (
int y = 0; y < m_height; ++y, v += m_width )
7421 return ColumnVector( x, channel );
7447 template <
typename T>
7448 void GetRow( T* buffer,
int y,
int channel = -1 )
const
7450 PCL_PRECONDITION( buffer != 0 )
7452 channel = m_channel;
7453 if ( y >= 0 && y < m_height && channel >= 0 && channel < m_numberOfChannels )
7454 P::Get( buffer, ScanLine( y, channel ), m_width );
7478 template <
typename T>
7481 PCL_PRECONDITION( buffer != 0 )
7483 channel = m_channel;
7484 if ( x >= 0 && x < m_width && channel >= 0 && channel < m_numberOfChannels )
7486 const sample* v = PixelAddress( x, 0, channel );
7487 for (
int y = 0; y < m_height; ++y, ++buffer, v += m_width )
7488 P::FromSample( *buffer, *v );
7513 template <
typename T>
7516 PCL_PRECONDITION( buffer != 0 )
7518 channel = m_channel;
7519 if ( y >= 0 && y < m_height && channel >= 0 && channel < m_numberOfChannels )
7520 P::Copy( ScanLine( y, channel ), buffer, m_width );
7545 template <
typename T>
7548 PCL_PRECONDITION( buffer != 0 )
7550 channel = m_channel;
7551 if ( x >= 0 && x < m_width && channel >= 0 && channel < m_numberOfChannels )
7553 sample* v = PixelAddress( x, 0, channel );
7554 for (
int y = 0; y < m_height; ++y, ++buffer, v += m_width )
7555 *v = P::ToSample( *buffer );
7573 if ( n > 0 && m_numberOfChannels > 0 )
7576 sample** oldData = m_pixelData;
7577 sample** newData =
nullptr;
7580 newData = m_allocator.AllocateChannelSlots( m_numberOfChannels+n );
7581 for (
int i = 0; i < m_numberOfChannels; ++i )
7582 newData[i] = oldData[i];
7583 for (
int i = 0; i < n; ++i )
7584 newData[m_numberOfChannels+i] = m_allocator.AllocatePixels( m_width, m_height );
7588 if ( newData !=
nullptr )
7590 for (
int i = 0; i < n; ++i )
7591 if ( newData[m_numberOfChannels+i] !=
nullptr )
7592 m_allocator.Deallocate( newData[m_numberOfChannels+i] );
7593 m_allocator.Deallocate( newData );
7598 m_allocator.SetSharedData( m_pixelData = newData );
7599 m_allocator.SetSharedGeometry( m_width, m_height, m_numberOfChannels += n );
7600 m_allocator.Deallocate( oldData );
7628 if ( data ==
nullptr )
7629 CreateAlphaChannels( 1 );
7630 else if ( m_numberOfChannels > 0 )
7633 sample** oldData = m_pixelData;
7634 sample** newData =
nullptr;
7637 newData = m_allocator.AllocateChannelSlots( m_numberOfChannels+1 );
7638 for (
int i = 0; i < m_numberOfChannels; ++i )
7639 newData[i] = oldData[i];
7640 newData[m_numberOfChannels] = data;
7644 if ( newData !=
nullptr )
7645 m_allocator.Deallocate( newData );
7649 m_allocator.SetSharedData( m_pixelData = newData );
7650 m_allocator.SetSharedGeometry( m_width, m_height, ++m_numberOfChannels );
7651 m_allocator.Deallocate( oldData );
7681 if ( IsShared() != image.
IsShared() )
7682 throw Error(
"GenericImage::ReleaseAlphaChannel(): Cannot release pixel data between local and shared images" );
7684 if ( channel < 0 || channel >= NumberOfAlphaChannels() )
7692 sample** newData =
nullptr;
7695 newData = image.m_allocator.AllocateChannelSlots( 1 );
7696 *newData = m_pixelData[c];
7700 if ( newData !=
nullptr )
7701 image.m_allocator.Deallocate( newData );
7707 image.m_pixelData = newData;
7708 image.m_width = m_width;
7709 image.m_height = m_height;
7710 image.m_numberOfChannels = 1;
7711 image.m_colorSpace = ColorSpace::Gray;
7712 image.m_data->UpdateSharedImage();
7715 m_pixelData[c] =
nullptr;
7716 ForgetAlphaChannel( channel );
7734 if ( channel >= 0 && channel < NumberOfAlphaChannels() )
7738 m_allocator.Deallocate( m_pixelData[c] );
7739 m_pixelData[c] =
nullptr;
7740 ForgetAlphaChannel( channel );
7764 if ( channel >= 0 && channel < NumberOfAlphaChannels() )
7767 sample** oldData = m_pixelData;
7768 sample** newData = m_allocator.AllocateChannelSlots( m_numberOfChannels-1 );
7771 int c = n0 + channel;
7773 for (
int i = 0; i < c; ++i )
7774 newData[i] = oldData[i];
7775 for (
int i = c, j = c; ++j < m_numberOfChannels; ++i )
7776 newData[i] = oldData[j];
7778 m_allocator.SetSharedData( m_pixelData = newData );
7779 m_allocator.SetSharedGeometry( m_width, m_height, --m_numberOfChannels );
7781 if ( m_channel >= n0 || m_lastChannel >= n0 )
7782 ResetChannelRange();
7784 m_allocator.Deallocate( oldData );
7797 int n = m_numberOfChannels;
7802 m_allocator.Deallocate( m_pixelData[--n] ), m_pixelData[n] =
nullptr;
7804 ForgetAlphaChannels();
7821 if ( m_numberOfChannels > n0 )
7824 sample** oldData = m_pixelData;
7825 sample** newData = m_allocator.AllocateChannelSlots( n0 );
7827 for (
int i = 0; i < n0; ++i )
7828 newData[i] = oldData[i];
7830 m_allocator.SetSharedData( m_pixelData = newData );
7831 m_allocator.SetSharedGeometry( m_width, m_height, m_numberOfChannels = n0 );
7833 if ( m_channel >= n0 || m_lastChannel >= n0 )
7834 ResetChannelRange();
7836 m_allocator.Deallocate( oldData );
7880 template <
typename T>
7884 if ( !ParseSelection( r, firstChannel, lastChannel ) )
7890 if ( m_status.IsInitializationEnabled() )
7891 m_status.Initialize(
"Filling image", N*(1 + lastChannel - firstChannel) );
7893 sample v = P::ToSample( scalar );
7895 if ( r == Bounds() )
7896 for (
int i = firstChannel; i <= lastChannel; ++i, m_status += N )
7897 P::Fill( m_pixelData[i], v, N );
7899 for (
int i = firstChannel, w = r.
Width(), h = r.
Height(); i <= lastChannel; ++i, m_status += N )
7903 for (
int j = 0; j < h; ++j, f += m_width )
7927 template <
typename T>
7929 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
7932 if ( !ParseSelection( r, firstChannel, lastChannel ) )
7938 if ( m_status.IsInitializationEnabled() )
7939 m_status.Initialize(
"Filling image", N*(1 + lastChannel - firstChannel) );
7941 if ( r == Bounds() )
7942 for (
int i = firstChannel, c = 0; i <= lastChannel; ++i, ++c, m_status += N )
7944 sample v = (c < values.
Length()) ? P::ToSample( values[c] ) : P::MinSampleValue();
7945 P::Fill( m_pixelData[i], v, N );
7948 for (
int i = firstChannel, c = 0, w = r.
Width(), h = r.
Height(); i <= lastChannel; ++i, ++c, m_status += N )
7951 sample v = (c < values.
Length()) ? P::ToSample( values[c] ) : P::MinSampleValue();
7953 for (
int j = 0; j < h; ++j, f += m_width )
7970 template <
typename T>
7973 GenericImage result( *
this, rect, firstChannel, lastChannel );
7974 (void)result.
Fill( scalar );
7989 template <
typename T>
7991 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
const
7993 GenericImage result( *
this, rect, firstChannel, lastChannel );
7994 (void)result.
Fill( values );
8014 return Fill( P::ToSample( 0.0 ), rect, firstChannel, lastChannel );
8033 return Fill( P::ToSample( 1.0 ), rect, firstChannel, lastChannel );
8051 return Fill( P::MinSampleValue(), rect, firstChannel, lastChannel );
8069 return Fill( P::MaxSampleValue(), rect, firstChannel, lastChannel );
8088 template <
typename T>
8092 if ( !ParseSelection( r, firstChannel, lastChannel ) )
8098 if ( m_status.IsInitializationEnabled() )
8099 m_status.Initialize(
"Inverting pixel samples", N*(1 + lastChannel - firstChannel) );
8101 sample v = P::ToSample( scalar );
8102 if ( r == Bounds() )
8103 for (
int i = firstChannel; i <= lastChannel; ++i, m_status += N )
8105 sample* __restrict__ f = m_pixelData[i];
8107 for (
size_type j = 0; j < N; ++j, ++f )
8111 for (
int i = firstChannel, w = r.
Width(), h = r.
Height(); i <= lastChannel; ++i, m_status += N )
8115 for (
int j = 0; j < h; ++j, f += m_width-w )
8118 for (
int k = 0; k < w; ++k, ++f )
8136 template <
typename T>
8139 GenericImage result( *
this, rect, firstChannel, lastChannel );
8140 (void)result.
Invert( scalar );
8163 return Invert( P::MaxSampleValue(), rect, firstChannel, lastChannel );
8179 GenericImage result( *
this, rect, firstChannel, lastChannel );
8212 if ( !ParseSelection( r, firstChannel, lastChannel ) )
8218 if ( m_status.IsInitializationEnabled() )
8219 m_status.Initialize(
"Bitwise Not", N*(1 + lastChannel - firstChannel) );
8221 if ( r == Bounds() )
8222 for (
int i = firstChannel; i <= lastChannel; ++i, m_status += N )
8224 sample* __restrict__ f = m_pixelData[i];
8226 for (
size_type j = 0; j < N; ++j, ++f )
8230 for (
int i = firstChannel, w = r.
Width(), h = r.
Height(); i <= lastChannel; ++i, m_status += N )
8234 for (
int j = 0; j < h; ++j, f += m_width-w )
8237 for (
int k = 0; k < w; ++k, ++f )
8261 template <
typename T>
8263 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
8266 if ( !ParseSelection( r, firstChannel, lastChannel ) )
8272 if ( m_status.IsInitializationEnabled() )
8273 m_status.Initialize(
"Truncating pixel samples", N*(1 + lastChannel - firstChannel) );
8275 sample b0 = P::ToSample( lowerBound );
8276 sample b1 = P::ToSample( upperBound );
8280 if ( r == Bounds() )
8281 for (
int i = firstChannel; i <= lastChannel; ++i, m_status += N )
8283 sample* __restrict__ f = m_pixelData[i];
8285 for (
size_type j = 0; j < N; ++j, ++f )
8292 for (
int i = firstChannel, w = r.
Width(), h = r.
Height(); i <= lastChannel; ++i, m_status += N )
8296 for (
int j = 0; j < h; ++j, f += m_width-w )
8299 for (
int k = 0; k < w; ++k, ++f )
8323 template <
typename T>
8325 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
const
8327 GenericImage result( *
this, rect, firstChannel, lastChannel );
8328 (void)result.
Truncate( lowerBound, upperBound );
8355 return Truncate( P::MinSampleValue(), P::MaxSampleValue(), rect, firstChannel, lastChannel );
8370 GenericImage result( *
this, rect, firstChannel, lastChannel );
8403 template <
typename T>
8405 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
8408 if ( !ParseSelection( r, firstChannel, lastChannel ) )
8412 size_type Ns = N*(1 + lastChannel - firstChannel);
8413 if ( m_status.IsInitializationEnabled() )
8414 m_status.Initialize(
"Rescaling pixel samples", Ns );
8416 sample b0 = P::ToSample( lowerBound );
8417 sample b1 = P::ToSample( upperBound );
8422 GetExtremePixelValues( v0, v1, r, firstChannel, lastChannel );
8423 if ( v0 == b0 && v1 == b1 )
8434 d = (double( b1 ) - double( b0 ))/(
double( v1 ) - double( v0 ));
8436 if ( r == Bounds() )
8437 for (
int i = firstChannel; i <= lastChannel; ++i, m_status += N )
8439 sample* __restrict__ f = m_pixelData[i];
8448 for (
size_type j = 0; j < N; ++j, ++f )
8449 *f = P::FloatToSample( d*(*f - v0) );
8454 for (
size_type j = 0; j < N; ++j, ++f )
8455 *f = P::FloatToSample( d*(*f - v0) + b0 );
8459 P::Fill( f, b0, N );
8465 for (
int i = firstChannel, w = r.
Width(), h = r.
Height(); i <= lastChannel; ++i, m_status += N )
8476 for (
int j = 0; j < h; ++j, f += m_width-w )
8479 for (
int k = 0; k < w; ++k, ++f )
8480 *f = P::FloatToSample( d*(*f - v0) );
8486 for (
int j = 0; j < h; ++j, f += m_width-w )
8489 for (
int k = 0; k < w; ++k, ++f )
8490 *f = P::FloatToSample( d*(*f - v0) + b0 );
8497 for (
int j = 0; j < h; ++j, f += m_width )
8498 P::Fill( f, b0, w );
8505 for (
int j = 0; j < h; ++j, f += m_width )
8526 template <
typename T>
8528 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
const
8530 GenericImage result( *
this, rect, firstChannel, lastChannel );
8531 (void)result.
Rescale( lowerBound, upperBound );
8553 return Rescale( P::MinSampleValue(), P::MaxSampleValue(), rect, firstChannel, lastChannel );
8568 GenericImage result( *
this, rect, firstChannel, lastChannel );
8607 template <
typename T>
8609 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
8612 if ( !ParseSelection( r, firstChannel, lastChannel ) )
8616 size_type Ns = N*(1 + lastChannel - firstChannel);
8617 if ( m_status.IsInitializationEnabled() )
8618 m_status.Initialize(
"Normalizing pixel samples", Ns );
8620 sample b0 = P::ToSample( lowerBound );
8621 sample b1 = P::ToSample( upperBound );
8626 GetExtremePixelValues( v0, v1, r, firstChannel, lastChannel );
8628 if ( v0 >= b0 && v1 <= b1 )
8639 d = (double( b1 ) - double( b0 ))/(
double( v1 ) - double( v0 ));
8641 if ( r == Bounds() )
8642 for (
int i = firstChannel; i <= lastChannel; ++i, m_status += N )
8644 sample* __restrict__ f = m_pixelData[i];
8653 for (
size_type j = 0; j < N; ++j, ++f )
8654 *f = P::FloatToSample( d*(*f - v0) );
8659 for (
size_type j = 0; j < N; ++j, ++f )
8660 *f = P::FloatToSample( d*(*f - v0) + b0 );
8664 P::Fill( f, b0, N );
8670 for (
int i = firstChannel, w = r.
Width(), h = r.
Height(); i <= lastChannel; ++i, m_status += N )
8681 for (
int j = 0; j < h; ++j, f += m_width-w )
8684 for (
int k = 0; k < w; ++k, ++f )
8685 *f = P::FloatToSample( d*(*f - v0) );
8691 for (
int j = 0; j < h; ++j, f += m_width-w )
8694 for (
int k = 0; k < w; ++k, ++f )
8695 *f = P::FloatToSample( d*(*f - v0) + b0 );
8702 for (
int j = 0; j < h; ++j, f += m_width )
8703 P::Fill( f, b0, w );
8710 for (
int j = 0; j < h; ++j, f += m_width )
8731 template <
typename T>
8733 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
const
8735 GenericImage result( *
this, rect, firstChannel, lastChannel );
8736 (void)result.
Normalize( lowerBound, upperBound );
8758 return Normalize( P::MinSampleValue(), P::MaxSampleValue(), rect, firstChannel, lastChannel );
8773 GenericImage result( *
this, rect, firstChannel, lastChannel );
8807 template <
typename T>
8809 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
8812 if ( !ParseSelection( r, firstChannel, lastChannel ) )
8818 if ( m_status.IsInitializationEnabled() )
8819 m_status.Initialize(
"Binarizing pixel samples", N*(1 + lastChannel - firstChannel) );
8821 sample t = P::ToSample( threshold );
8823 if ( r == Bounds() )
8824 for (
int i = firstChannel; i <= lastChannel; ++i, m_status += N )
8826 sample* __restrict__ f = m_pixelData[i];
8828 for (
size_type j = 0; j < N; ++j, ++f )
8829 *f = (*f < t) ? P::MinSampleValue() : P::MaxSampleValue();
8832 for (
int c = firstChannel, w = r.
Width(), h = r.
Height(); c <= lastChannel; ++c, m_status += N )
8836 for (
int j = 0; j < h; ++j, f += m_width-w )
8839 for (
int k = 0; k < w; ++k, ++f )
8840 *f = (*f < t) ? P::MinSampleValue() : P::MaxSampleValue();
8857 template <
typename T>
8859 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
const
8861 GenericImage result( *
this, rect, firstChannel, lastChannel );
8862 (void)result.
Binarize( threshold );
8884 return Binarize( (P::MinSampleValue() + P::MaxSampleValue())/2, rect, firstChannel, lastChannel );
8900 GenericImage result( *
this, rect, firstChannel, lastChannel );
8921 if ( !ParseSelection( r, firstChannel, lastChannel ) )
8927 if ( m_status.IsInitializationEnabled() )
8928 m_status.Initialize(
"Computing absolute value", N*(1 + lastChannel - firstChannel) );
8930 if ( r == Bounds() )
8931 for (
int i = firstChannel; i <= lastChannel; ++i, m_status += N )
8933 sample* __restrict__ f = m_pixelData[i];
8935 for (
size_type j = 0; j < N; ++j, ++f )
8939 for (
int i = firstChannel, w = r.
Width(), h = r.
Height(); i <= lastChannel; ++i, m_status += N )
8943 for (
int j = 0; j < h; ++j, f += m_width-w )
8946 for (
int k = 0; k < w; ++k, ++f )
8959 return SetAbsoluteValue( rect, firstChannel, lastChannel );
8974 GenericImage result( *
this, rect, firstChannel, lastChannel );
8986 template <
typename T>
8987 GenericImage& ApplyScalar( T scalar, image_op op = ImageOp::Mov,
8988 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
8990 if ( op == ImageOp::Div )
8991 if ( 1 + scalar == 1 )
8992 throw Error(
"Division by zero or insignificant scalar" );
8995 if ( !ParseSelection( r, firstChannel, lastChannel ) )
9001 if ( m_status.IsInitializationEnabled() )
9002 m_status.Initialize(
"Applying scalar: "
9004 +
' ' +
String( scalar ), N*(1 + lastChannel - firstChannel) );
9006 if ( r == Bounds() )
9007 for (
int i = firstChannel; i <= lastChannel; ++i, m_status += N )
9009 sample* __restrict__ f = m_pixelData[i];
9010 #define ITERATE( Op ) \
9012 for ( size_type j = 0; j < N; ++j, ++f ) \
9016 case ImageOp::Mov: ITERATE( Mov );
break;
9017 case ImageOp::Add: ITERATE( Add );
break;
9018 case ImageOp::Sub: ITERATE( Sub );
break;
9019 case ImageOp::Mul: ITERATE( Mul );
break;
9020 case ImageOp::Div: ITERATE( Div );
break;
9021 case ImageOp::Pow: ITERATE( Pow );
break;
9022 case ImageOp::Dif: ITERATE( Dif );
break;
9023 case ImageOp::Min: ITERATE( Min );
break;
9024 case ImageOp::Max: ITERATE( Max );
break;
9025 case ImageOp::Not: ITERATE( Not );
break;
9026 case ImageOp::Or: ITERATE( Or );
break;
9027 case ImageOp::Nor: ITERATE( Nor );
break;
9028 case ImageOp::And: ITERATE( And );
break;
9029 case ImageOp::Nand: ITERATE( Nand );
break;
9030 case ImageOp::Xor: ITERATE( Xor );
break;
9031 case ImageOp::Xnor: ITERATE( Xnor );
break;
9032 case ImageOp::ColorBurn: ITERATE( ColorBurn );
break;
9033 case ImageOp::LinearBurn: ITERATE( LinearBurn );
break;
9034 case ImageOp::Screen: ITERATE( Screen );
break;
9035 case ImageOp::ColorDodge: ITERATE( ColorDodge );
break;
9036 case ImageOp::Overlay: ITERATE( Overlay );
break;
9037 case ImageOp::SoftLight: ITERATE( SoftLight );
break;
9038 case ImageOp::HardLight: ITERATE( HardLight );
break;
9039 case ImageOp::VividLight: ITERATE( VividLight );
break;
9040 case ImageOp::LinearLight: ITERATE( LinearLight );
break;
9041 case ImageOp::PinLight: ITERATE( PinLight );
break;
9042 case ImageOp::Exclusion: ITERATE( Exclusion );
break;
9048 for (
int i = firstChannel, w = r.
Width(), h = r.
Height(); i <= lastChannel; ++i, m_status += N )
9050 sample* __restrict__ f = PixelAddress( r.
LeftTop(), i );
9051 #define ITERATE( Op ) \
9053 for ( int j = 0; j < h; ++j, f += m_width-w ) \
9056 for ( int k = 0; k < w; ++k, ++f ) \
9057 P::Op( *f, scalar ); \
9061 case ImageOp::Mov: ITERATE( Mov );
break;
9062 case ImageOp::Add: ITERATE( Add );
break;
9063 case ImageOp::Sub: ITERATE( Sub );
break;
9064 case ImageOp::Mul: ITERATE( Mul );
break;
9065 case ImageOp::Div: ITERATE( Div );
break;
9066 case ImageOp::Pow: ITERATE( Pow );
break;
9067 case ImageOp::Dif: ITERATE( Dif );
break;
9068 case ImageOp::Min: ITERATE( Min );
break;
9069 case ImageOp::Max: ITERATE( Max );
break;
9070 case ImageOp::Not: ITERATE( Not );
break;
9071 case ImageOp::Or: ITERATE( Or );
break;
9072 case ImageOp::Nor: ITERATE( Nor );
break;
9073 case ImageOp::And: ITERATE( And );
break;
9074 case ImageOp::Nand: ITERATE( Nand );
break;
9075 case ImageOp::Xor: ITERATE( Xor );
break;
9076 case ImageOp::Xnor: ITERATE( Xnor );
break;
9077 case ImageOp::ColorBurn: ITERATE( ColorBurn );
break;
9078 case ImageOp::LinearBurn: ITERATE( LinearBurn );
break;
9079 case ImageOp::Screen: ITERATE( Screen );
break;
9080 case ImageOp::ColorDodge: ITERATE( ColorDodge );
break;
9081 case ImageOp::Overlay: ITERATE( Overlay );
break;
9082 case ImageOp::SoftLight: ITERATE( SoftLight );
break;
9083 case ImageOp::HardLight: ITERATE( HardLight );
break;
9084 case ImageOp::VividLight: ITERATE( VividLight );
break;
9085 case ImageOp::LinearLight: ITERATE( LinearLight );
break;
9086 case ImageOp::PinLight: ITERATE( PinLight );
break;
9087 case ImageOp::Exclusion: ITERATE( Exclusion );
break;
9118 template <
typename T>
9120 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
9122 return ApplyScalar( scalar, op, rect, firstChannel, lastChannel );
9126 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
9129 return ApplyScalar( scalar, op, rect, firstChannel, lastChannel );
9130 return ApplyScalar( P::ToSample( scalar ), op, rect, firstChannel, lastChannel );
9133 GenericImage&
Apply(
double scalar, image_op op = ImageOp::Mov,
9134 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
9137 return ApplyScalar( scalar, op, rect, firstChannel, lastChannel );
9138 return ApplyScalar( P::ToSample( scalar ), op, rect, firstChannel, lastChannel );
9142 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
9145 return ApplyScalar( scalar, op, rect, firstChannel, lastChannel );
9146 return ApplyScalar( P::ToSample( scalar ), op, rect, firstChannel, lastChannel );
9150 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
9153 return ApplyScalar( scalar, op, rect, firstChannel, lastChannel );
9154 return ApplyScalar( P::ToSample( scalar ), op, rect, firstChannel, lastChannel );
9175 template <
typename T>
9177 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
const
9179 GenericImage result( *
this, rect, firstChannel, lastChannel );
9180 (void)result.
Apply( scalar, op );
9232 const Point& point =
Point( int_max ),
int channel = -1,
9233 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
9239 if ( !ParseChannel( channel ) )
9243 if ( p.
x == int_max || p.
y == int_max )
9248 if ( (r.
x0 -= p.
x) >= r.
x1 )
9252 else if ( p.
x >= m_width )
9257 if ( (r.
y0 -= p.
y) >= r.
y1 )
9261 else if ( p.
y >= m_height )
9267 lastChannel =
pcl::Min( lastChannel, firstChannel + m_numberOfChannels - channel - 1 );
9272 if ( m_status.IsInitializationEnabled() )
9273 m_status.Initialize(
"Applying image, op=" +
ImageOp::Id( op ), N*(1 + lastChannel - firstChannel) );
9275 if ( r == Bounds() && r == image.
Bounds() )
9276 for (
int i = channel, j = firstChannel; j <= lastChannel; ++i, ++j, m_status += N )
9278 sample* __restrict__ f = m_pixelData[i];
9279 const typename P1::sample* __restrict__ g = image[j];
9281 #define ITERATE( Op ) \
9283 for ( size_type k = 0; k < N; ++k, ++f, ++g ) \
9291 P::CopyMin( f, g, N );
9294 P::CopyMax( f, g, N );
9299 case ImageOp::Add: ITERATE( Add );
break;
9300 case ImageOp::Sub: ITERATE( Sub );
break;
9301 case ImageOp::Mul: ITERATE( Mul );
break;
9303 for (
size_type j = 0; j < N; ++j, ++f, ++g )
9307 *f = P::MaxSampleValue();
9309 case ImageOp::Pow: ITERATE( Pow );
break;
9310 case ImageOp::Dif: ITERATE( Dif );
break;
9311 case ImageOp::Not: ITERATE( Not );
break;
9312 case ImageOp::Or: ITERATE( Or );
break;
9313 case ImageOp::Nor: ITERATE( Nor );
break;
9314 case ImageOp::And: ITERATE( And );
break;
9315 case ImageOp::Nand: ITERATE( Nand );
break;
9316 case ImageOp::Xor: ITERATE( Xor );
break;
9317 case ImageOp::Xnor: ITERATE( Xnor );
break;
9318 case ImageOp::ColorBurn: ITERATE( ColorBurn );
break;
9319 case ImageOp::LinearBurn: ITERATE( LinearBurn );
break;
9320 case ImageOp::Screen: ITERATE( Screen );
break;
9321 case ImageOp::ColorDodge: ITERATE( ColorDodge );
break;
9322 case ImageOp::Overlay: ITERATE( Overlay );
break;
9323 case ImageOp::SoftLight: ITERATE( SoftLight );
break;
9324 case ImageOp::HardLight: ITERATE( HardLight );
break;
9325 case ImageOp::VividLight: ITERATE( VividLight );
break;
9326 case ImageOp::LinearLight: ITERATE( LinearLight );
break;
9327 case ImageOp::PinLight: ITERATE( PinLight );
break;
9328 case ImageOp::Exclusion: ITERATE( Exclusion );
break;
9336 for (
int i = channel, j = firstChannel, w = r.
Width(), h = r.
Height(); j <= lastChannel; ++i, ++j, m_status += N )
9338 sample* __restrict__ f = PixelAddress( p, i );
9341 #define ITERATE( Op ) \
9343 for ( int k = 0; k < h; ++k, f += m_width-w, g += image.Width()-w ) \
9346 for ( int l = 0; l < w; ++l, ++f, ++g ) \
9352 for (
int k = 0; k < h; ++k, f += m_width, g += image.
Width() )
9356 for (
int k = 0; k < h; ++k, f += m_width, g += image.
Width() )
9357 P::CopyMin( f, g, w );
9360 for (
int k = 0; k < h; ++k, f += m_width, g += image.
Width() )
9361 P::CopyMax( f, g, w );
9363 case ImageOp::Add: ITERATE( Add );
break;
9364 case ImageOp::Sub: ITERATE( Sub );
break;
9365 case ImageOp::Mul: ITERATE( Mul );
break;
9368 for (
int k = 0; k < h; ++k, f += m_width-w, g += image.
Width()-w )
9371 for (
int l = 0; l < w; ++l, ++f, ++g )
9375 *f = P::MaxSampleValue();
9378 case ImageOp::Pow: ITERATE( Pow );
break;
9379 case ImageOp::Dif: ITERATE( Dif );
break;
9380 case ImageOp::Not: ITERATE( Not );
break;
9381 case ImageOp::Or: ITERATE( Or );
break;
9382 case ImageOp::Nor: ITERATE( Nor );
break;
9383 case ImageOp::And: ITERATE( And );
break;
9384 case ImageOp::Nand: ITERATE( Nand );
break;
9385 case ImageOp::Xor: ITERATE( Xor );
break;
9386 case ImageOp::Xnor: ITERATE( Xnor );
break;
9387 case ImageOp::ColorBurn: ITERATE( ColorBurn );
break;
9388 case ImageOp::LinearBurn: ITERATE( LinearBurn );
break;
9389 case ImageOp::Screen: ITERATE( Screen );
break;
9390 case ImageOp::ColorDodge: ITERATE( ColorDodge );
break;
9391 case ImageOp::Overlay: ITERATE( Overlay );
break;
9392 case ImageOp::SoftLight: ITERATE( SoftLight );
break;
9393 case ImageOp::HardLight: ITERATE( HardLight );
break;
9394 case ImageOp::VividLight: ITERATE( VividLight );
break;
9395 case ImageOp::LinearLight: ITERATE( LinearLight );
break;
9396 case ImageOp::PinLight: ITERATE( PinLight );
break;
9397 case ImageOp::Exclusion: ITERATE( Exclusion );
break;
9421 const Point& point =
Point( int_max ),
int channel = -1,
9422 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
const
9424 int c0 = (channel < 0) ? m_channel : channel;
9428 (void)result.Apply( image, op,
Point( 0 ), 0, rect, firstChannel, lastChannel );
9468 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 );
9490 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
const
9492 GenericImage result( *
this, rect, firstChannel, lastChannel );
9493 (void)result.
Apply( transformation );
9519 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
const;
9524 #ifndef __PCL_IMAGE_NO_BITMAP
9579 if ( p.
x == int_max || p.
y == int_max )
9584 if ( (r.
x0 -= p.
x) >= r.
x1 )
9588 else if ( p.
x >= m_width )
9593 if ( (r.
y0 -= p.
y) >= r.
y1 )
9597 else if ( p.
y >= m_height )
9603 bool hasAlpha = HasAlphaChannels();
9611 if ( m_status.IsInitializationEnabled() )
9614 sample* __restrict__ fR =
nullptr;
9615 sample* __restrict__ fG =
nullptr;
9616 sample* __restrict__ fB =
nullptr;
9617 sample* __restrict__ fA =
nullptr;
9619 for (
int i = 0; i < h; ++i, ++p.
y, m_status += w )
9621 fR = PixelAddress( p, 0 );
9622 fG = PixelAddress( p, 1 );
9623 fB = PixelAddress( p, 2 );
9625 fA = PixelAddress( p, 3 );
9629 for (
int j = 0; j < w; ++j, ++fR, ++fG, ++fB, ++fA, ++g )
9633 uint8 A = Alpha( rgba );
9637 P::Mov( *fR, Red( rgba ) );
9638 P::Mov( *fG, Green( rgba ) );
9639 P::Mov( *fB, Blue( rgba ) );
9646 P::Mov( *fR, Red( rgba ) );
9647 P::Mov( *fG, Green( rgba ) );
9648 P::Mov( *fB, Blue( rgba ) );
9652 double k = PTLUT->pDLUTA[A];
9653 double k1 = PTLUT->p1DLUT8[A];
9655 P::FromSample( v, *fR ), P::Mov( *fR, k*Red( rgba ) + k1*v );
9656 P::FromSample( v, *fG ), P::Mov( *fG, k*Green( rgba ) + k1*v );
9657 P::FromSample( v, *fB ), P::Mov( *fB, k*Blue( rgba ) + k1*v );
9665 if ( m_status.IsInitializationEnabled() )
9668 sample* __restrict__ fK =
nullptr;
9669 sample* __restrict__ fA =
nullptr;
9671 for (
int i = 0; i < h; ++i, ++p.
y, m_status += w )
9673 fK = PixelAddress( p, 0 );
9675 fA = PixelAddress( p, 1 );
9679 for (
int j = 0; j < w; ++j, ++fK, ++fA, ++g )
9682 uint8 R = Red( rgba );
9683 uint8 G = Green( rgba );
9684 uint8 B = Blue( rgba );
9685 uint8 A = Alpha( rgba );
9692 P::Mov( *fK, K/255 );
9698 P::Mov( *fK, K/255 );
9702 P::FromSample( v, *fK );
9703 P::Mov( *fK, PTLUT->pDLUTA[A]*K + PTLUT->p1DLUT8[A]*v );
9727 GenericImage result( *
this, Bounds(), 0, m_numberOfChannels-1 );
9728 (void)result.
Blend( bitmap, point, rect );
9746 template <
typename T>
9749 return Apply( scalar, ImageOp::Mov, rect, firstChannel, lastChannel );
9755 template <
typename T>
9758 return Move( scalar, rect, firstChannel, lastChannel );
9771 template <
typename T>
9774 return Apply( scalar, ImageOp::Add, rect, firstChannel, lastChannel );
9780 template <
typename T>
9783 return Add( scalar );
9796 template <
typename T>
9799 GenericImage result( *
this, rect, firstChannel, lastChannel );
9800 (void)result.
Add( scalar );
9814 template <
typename T>
9817 return Apply( scalar, ImageOp::Sub, rect, firstChannel, lastChannel );
9823 template <
typename T>
9826 return Subtract( scalar, rect, firstChannel, lastChannel );
9832 template <
typename T>
9835 return Subtract( scalar );
9848 template <
typename T>
9851 GenericImage result( *
this, rect, firstChannel, lastChannel );
9866 template <
typename T>
9869 return Apply( scalar, ImageOp::Mul, rect, firstChannel, lastChannel );
9875 template <
typename T>
9878 return Multiply( scalar, rect, firstChannel, lastChannel );
9884 template <
typename T>
9887 return Multiply( scalar );
9900 template <
typename T>
9903 GenericImage result( *
this, rect, firstChannel, lastChannel );
9921 template <
typename T>
9924 return Apply( scalar, ImageOp::Div, rect, firstChannel, lastChannel );
9930 template <
typename T>
9933 return Divide( scalar, rect, firstChannel, lastChannel );
9939 template <
typename T>
9942 return Divide( scalar );
9958 template <
typename T>
9961 GenericImage result( *
this, rect, firstChannel, lastChannel );
9962 (void)result.
Divide( scalar );
9976 template <
typename T>
9979 return Apply( scalar, ImageOp::Pow, rect, firstChannel, lastChannel );
9985 template <
typename T>
9988 return Raise( scalar, rect, firstChannel, lastChannel );
9994 template <
typename T>
9997 return Raise( scalar );
10010 template <
typename T>
10013 GenericImage result( *
this, rect, firstChannel, lastChannel );
10014 (void)result.
Raise( scalar );
10029 template <
typename T>
10032 return Apply( scalar, ImageOp::Dif, rect, firstChannel, lastChannel );
10038 template <
typename T>
10041 return SetAbsoluteDifference( scalar, rect, firstChannel, lastChannel );
10055 template <
typename T>
10058 GenericImage result( *
this, rect, firstChannel, lastChannel );
10073 template <
typename T>
10076 return Apply( scalar, ImageOp::Min, rect, firstChannel, lastChannel );
10082 template <
typename T>
10085 return SetMinimum( scalar, rect, firstChannel, lastChannel );
10099 template <
typename T>
10102 GenericImage result( *
this, rect, firstChannel, lastChannel );
10117 template <
typename T>
10120 return Apply( scalar, ImageOp::Max, rect, firstChannel, lastChannel );
10126 template <
typename T>
10129 return SetMaximum( scalar, rect, firstChannel, lastChannel );
10143 template <
typename T>
10146 GenericImage result( *
this, rect, firstChannel, lastChannel );
10162 template <
typename T>
10165 return Apply( scalar, ImageOp::Or, rect, firstChannel, lastChannel );
10179 template <
typename T>
10182 return Apply( scalar, ImageOp::And, rect, firstChannel, lastChannel );
10196 template <
typename T>
10199 return Apply( scalar, ImageOp::Xor, rect, firstChannel, lastChannel );
10213 template <
typename T>
10216 return Apply( scalar, ImageOp::Nor, rect, firstChannel, lastChannel );
10230 template <
typename T>
10233 return Apply( scalar, ImageOp::Nand, rect, firstChannel, lastChannel );
10247 template <
typename T>
10250 return Apply( scalar, ImageOp::Xnor, rect, firstChannel, lastChannel );
10265 template <
class P1>
10267 const Point& point =
Point( int_max ),
int channel = -1,
10268 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10270 return Apply( image, ImageOp::Mov, point, channel, rect, firstChannel, lastChannel );
10276 template <
class P1>
10278 const Point& point =
Point( int_max ),
int channel = -1,
10279 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10281 return Move( image, point, channel, rect, firstChannel, lastChannel );
10294 template <
class P1>
10296 const Point& point =
Point( int_max ),
int channel = -1,
10297 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10299 return Apply( image, ImageOp::Add, point, channel, rect, firstChannel, lastChannel );
10305 template <
class P1>
10308 return Add( image );
10321 template <
class P1>
10323 const Point& point =
Point( int_max ),
int channel = -1,
10324 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10326 return Apply( image, ImageOp::Sub, point, channel, rect, firstChannel, lastChannel );
10332 template <
class P1>
10334 const Point& point =
Point( int_max ),
int channel = -1,
10335 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10337 return Subtract( image, point, channel, rect, firstChannel, lastChannel );
10343 template <
class P1>
10346 return Subtract( image );
10359 template <
class P1>
10361 const Point& point =
Point( int_max ),
int channel = -1,
10362 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10364 return Apply( image, ImageOp::Mul, point, channel, rect, firstChannel, lastChannel );
10370 template <
class P1>
10372 const Point& point =
Point( int_max ),
int channel = -1,
10373 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10375 return Multiply( image, point, channel, rect, firstChannel, lastChannel );
10381 template <
class P1>
10384 return Multiply( image );
10401 template <
class P1>
10403 const Point& point =
Point( int_max ),
int channel = -1,
10404 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10406 return Apply( image, ImageOp::Div, point, channel, rect, firstChannel, lastChannel );
10412 template <
class P1>
10414 const Point& point =
Point( int_max ),
int channel = -1,
10415 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10417 return Divide( image, point, channel, rect, firstChannel, lastChannel );
10423 template <
class P1>
10426 return Divide( image );
10440 template <
class P1>
10442 const Point& point =
Point( int_max ),
int channel = -1,
10443 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10445 return Apply( image, ImageOp::Pow, point, channel, rect, firstChannel, lastChannel );
10451 template <
class P1>
10453 const Point& point =
Point( int_max ),
int channel = -1,
10454 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10456 return Raise( image, point, channel, rect, firstChannel, lastChannel );
10462 template <
class P1>
10465 return Raise( image );
10479 template <
class P1>
10481 const Point& point =
Point( int_max ),
int channel = -1,
10482 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10484 return Apply( image, ImageOp::Dif, point, channel, rect, firstChannel, lastChannel );
10490 template <
class P1>
10492 const Point& point =
Point( int_max ),
int channel = -1,
10493 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10495 return SetAbsoluteDifference( image, point, channel, rect, firstChannel, lastChannel );
10509 template <
class P1>
10511 const Point& point =
Point( int_max ),
int channel = -1,
10512 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10514 return Apply( image, ImageOp::Min, point, channel, rect, firstChannel, lastChannel );
10520 template <
class P1>
10522 const Point& point =
Point( int_max ),
int channel = -1,
10523 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10525 return SetMinimum( image, point, channel, rect, firstChannel, lastChannel );
10539 template <
class P1>
10541 const Point& point =
Point( int_max ),
int channel = -1,
10542 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10544 return Apply( image, ImageOp::Max, point, channel, rect, firstChannel, lastChannel );
10550 template <
class P1>
10552 const Point& point =
Point( int_max ),
int channel = -1,
10553 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10555 return SetMaximum( image, point, channel, rect, firstChannel, lastChannel );
10569 template <
class P1>
10571 const Point& point =
Point( int_max ),
int channel = -1,
10572 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10574 return Apply( image, ImageOp::Or, point, channel, rect, firstChannel, lastChannel );
10588 template <
class P1>
10590 const Point& point =
Point( int_max ),
int channel = -1,
10591 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10593 return Apply( image, ImageOp::And, point, channel, rect, firstChannel, lastChannel );
10607 template <
class P1>
10609 const Point& point =
Point( int_max ),
int channel = -1,
10610 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10612 return Apply( image, ImageOp::Xor, point, channel, rect, firstChannel, lastChannel );
10626 template <
class P1>
10628 const Point& point =
Point( int_max ),
int channel = -1,
10629 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10631 return Apply( image, ImageOp::Nor, point, channel, rect, firstChannel, lastChannel );
10645 template <
class P1>
10647 const Point& point =
Point( int_max ),
int channel = -1,
10648 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10650 return Apply( image, ImageOp::Nand, point, channel, rect, firstChannel, lastChannel );
10664 template <
class P1>
10666 const Point& point =
Point( int_max ),
int channel = -1,
10667 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10669 return Apply( image, ImageOp::Xnor, point, channel, rect, firstChannel, lastChannel );
10711 template <
class P1>
10713 const Point& point =
Point( int_max ),
int channel = -1,
10714 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10720 if ( !ParseChannel( channel ) )
10724 if ( p.
x == int_max || p.
y == int_max )
10729 if ( (r.
x0 -= p.
x) >= r.
x1 )
10733 else if ( p.
x >= m_width )
10738 if ( (r.
y0 -= p.
y) >= r.
y1 )
10742 else if ( p.
y >= m_height )
10748 lastChannel =
pcl::Min( lastChannel, firstChannel + m_numberOfChannels - channel - 1 );
10754 if ( m_status.IsInitializationEnabled() )
10755 m_status.Initialize(
"Exchanging pixel samples", N*(1 + lastChannel - firstChannel) );
10757 if ( r == Bounds() && r == image.
Bounds() )
10758 for (
int i = channel, j = firstChannel; j <= lastChannel; ++i, ++j, m_status += N )
10760 sample* __restrict__ f = m_pixelData[i];
10761 typename P1::sample* __restrict__ g = image[j];
10763 for (
size_type k = 0; k < N; ++k, ++f, ++g )
10766 P1::FromSample( *f, *g );
10767 P::FromSample( *g, t );
10771 for (
int i = channel, j = firstChannel, w = r.
Width(), h = r.
Height(); j <= lastChannel; ++i, ++j, m_status += N )
10773 sample* __restrict__ f = PixelAddress( p, i );
10776 for (
int k = 0; k < h; ++k, f += m_width-w, g += image.
Width()-w )
10779 for (
int l = 0; l < w; ++l, ++f, ++g )
10782 P1::FromSample( *f, *g );
10783 P::FromSample( *g, t );
10794 template <
class P1>
10796 const Point& point =
Point( int_max ),
int channel = -1,
10797 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10799 return Exchange( image, point, channel, rect, firstChannel, lastChannel );
10824 int maxProcessors = 0 )
const
10827 if ( !ParseSelection( r, firstChannel, lastChannel ) )
10831 if ( m_status.IsInitializationEnabled() )
10832 m_status.Initialize(
"Computing minimum pixel sample value", N );
10835 bool useAffinity = m_parallel && Thread::IsRootThread();
10837 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
10838 threads.
Add(
new MinThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
10839 if ( threads.
Length() > 1 )
10842 for ( MinThread& thread : threads )
10843 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
10844 for ( MinThread& thread : threads )
10850 sample min = P::MinSampleValue();
10852 if ( threads[i].count > 0 )
10854 min = threads[i].min;
10855 while ( ++i < threads.
Length() )
10856 if ( threads[i].count > 0 )
10857 if ( threads[i].min < min )
10858 min = threads[i].min;
10873 int maxProcessors = 0 )
const
10875 return MinimumSampleValue( rect, firstChannel, lastChannel, maxProcessors );
10898 int firstChannel = -1,
int lastChannel = -1,
int maxProcessors = 0 )
const
10901 if ( !ParseSelection( r, firstChannel, lastChannel ) )
10905 if ( m_status.IsInitializationEnabled() )
10906 m_status.Initialize(
"Computing maximum pixel sample value", N );
10909 bool useAffinity = m_parallel && Thread::IsRootThread();
10911 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
10912 threads.
Add(
new MaxThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
10913 if ( threads.
Length() > 1 )
10916 for ( MaxThread& thread : threads )
10917 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
10918 for ( MaxThread& thread : threads )
10924 sample max = P::MinSampleValue();
10926 if ( threads[i].count > 0 )
10928 max = threads[i].max;
10929 while ( ++i < threads.
Length() )
10930 if ( threads[i].count > 0 )
10931 if ( max < threads[i].max )
10932 max = threads[i].max;
10947 int maxProcessors = 0 )
const
10949 return MaximumSampleValue( rect, firstChannel, lastChannel, maxProcessors );
10978 template <
typename T>
10980 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
10981 int maxProcessors = 0 )
const
10984 if ( !ParseSelection( r, firstChannel, lastChannel ) )
10987 P::FromSample( min, P::MinSampleValue() );
10993 if ( m_status.IsInitializationEnabled() )
10994 m_status.Initialize(
"Computing extreme pixel sample values", N );
10997 bool useAffinity = m_parallel && Thread::IsRootThread();
10999 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
11000 threads.
Add(
new MinMaxThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
11001 if ( threads.
Length() > 1 )
11004 for ( MinMaxThread& thread : threads )
11005 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
11006 for ( MinMaxThread& thread : threads )
11012 sample vmin = P::MinSampleValue();
11013 sample vmax = P::MinSampleValue();
11015 if ( threads[i].count > 0 )
11017 vmin = threads[i].min;
11018 vmax = threads[i].max;
11019 while ( ++i < threads.
Length() )
11020 if ( threads[i].count > 0 )
11022 if ( threads[i].min < vmin )
11023 vmin = threads[i].min;
11024 if ( vmax < threads[i].max )
11025 vmax = threads[i].max;
11032 P::FromSample( min, vmin );
11033 P::FromSample( max, vmax );
11042 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
11043 int maxProcessors = 0 )
const
11045 GetExtremeSampleValues( min, max, rect, firstChannel, lastChannel, maxProcessors );
11075 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
11076 int maxProcessors = 0 )
const
11079 if ( !ParseSelection( r, firstChannel, lastChannel ) )
11083 return P::MinSampleValue();
11087 if ( m_status.IsInitializationEnabled() )
11088 m_status.Initialize(
"Locating minimum pixel sample value", N );
11091 bool useAffinity = m_parallel && Thread::IsRootThread();
11093 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
11094 threads.
Add(
new MinPosThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
11095 if ( threads.
Length() > 1 )
11098 for ( MinPosThread& thread : threads )
11099 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
11100 for ( MinPosThread& thread : threads )
11107 sample min = P::MinSampleValue();
11109 if ( threads[i].count > 0 )
11111 min = threads[i].min;
11112 xmin = threads[i].pmin.x;
11113 ymin = threads[i].pmin.y;
11114 while ( ++i < threads.
Length() )
11115 if ( threads[i].count > 0 )
11116 if ( threads[i].min < min )
11118 min = threads[i].min;
11119 xmin = threads[i].pmin.x;
11120 ymin = threads[i].pmin.y;
11153 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
11154 int maxProcessors = 0 )
const
11156 return LocateMinimumSampleValue( pmin.
x, pmin.
y, rect, firstChannel, lastChannel, maxProcessors );
11165 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
11166 int maxProcessors = 0 )
const
11168 return LocateMinimumSampleValue( xmin, ymin, rect, firstChannel, lastChannel, maxProcessors );
11177 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
11178 int maxProcessors = 0 )
const
11180 return LocateMinimumSampleValue( pmin, rect, firstChannel, lastChannel, maxProcessors );
11210 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
11211 int maxProcessors = 0 )
const
11214 if ( !ParseSelection( r, firstChannel, lastChannel ) )
11218 return P::MaxSampleValue();
11222 if ( m_status.IsInitializationEnabled() )
11223 m_status.Initialize(
"Locating maximum pixel sample value", N );
11226 bool useAffinity = m_parallel && Thread::IsRootThread();
11228 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
11229 threads.
Add(
new MaxPosThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
11230 if ( threads.
Length() > 1 )
11233 for ( MaxPosThread& thread : threads )
11234 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
11235 for ( MaxPosThread& thread : threads )
11242 sample max = P::MinSampleValue();
11244 if ( threads[i].count > 0 )
11246 max = threads[i].max;
11247 xmax = threads[i].pmax.x;
11248 ymax = threads[i].pmax.y;
11249 while ( ++i < threads.
Length() )
11250 if ( threads[i].count > 0 )
11251 if ( max < threads[i].max )
11253 max = threads[i].max;
11254 xmax = threads[i].pmax.x;
11255 ymax = threads[i].pmax.y;
11288 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
11289 int maxProcessors = 0 )
const
11291 return LocateMaximumSampleValue( pmax.
x, pmax.
y, rect, firstChannel, lastChannel, maxProcessors );
11300 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
11301 int maxProcessors = 0 )
const
11303 return LocateMaximumSampleValue( xmax, ymax, rect, firstChannel, lastChannel, maxProcessors );
11312 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
11313 int maxProcessors = 0 )
const
11315 return LocateMaximumSampleValue( pmax, rect, firstChannel, lastChannel, maxProcessors );
11354 template <
typename T>
11356 int& xmax,
int& ymax, T& max,
11357 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
11358 int maxProcessors = 0 )
const
11361 if ( !ParseSelection( r, firstChannel, lastChannel ) )
11364 xmin = ymin = xmax = ymax = 0;
11365 P::FromSample( min, P::MinSampleValue() );
11371 if ( m_status.IsInitializationEnabled() )
11372 m_status.Initialize(
"Locating extreme pixel sample values", N );
11375 bool useAffinity = m_parallel && Thread::IsRootThread();
11377 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
11378 threads.
Add(
new MinMaxPosThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
11379 if ( threads.
Length() > 1 )
11382 for ( MinMaxPosThread& thread : threads )
11383 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
11384 for ( MinMaxPosThread& thread : threads )
11390 xmin = ymin = xmax = ymax = -1;
11391 sample vmin = P::MinSampleValue();
11392 sample vmax = P::MinSampleValue();
11394 if ( threads[i].count > 0 )
11396 vmin = threads[i].min;
11397 xmin = threads[i].pmin.x;
11398 ymin = threads[i].pmin.y;
11399 vmax = threads[i].max;
11400 xmax = threads[i].pmax.x;
11401 ymax = threads[i].pmax.y;
11402 while ( ++i < threads.
Length() )
11403 if ( threads[i].count > 0 )
11405 if ( threads[i].min < vmin )
11407 vmin = threads[i].min;
11408 xmin = threads[i].pmin.x;
11409 ymin = threads[i].pmin.y;
11411 if ( vmax < threads[i].max )
11413 vmax = threads[i].max;
11414 xmax = threads[i].pmax.x;
11415 ymax = threads[i].pmax.y;
11423 P::FromSample( min, vmin );
11424 P::FromSample( max, vmax );
11454 template <
typename T>
11456 Point& pmax, T& max,
11457 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
11458 int maxProcessors = 0 )
const
11460 LocateExtremeSampleValues( pmin.
x, pmin.
y, min,
11461 pmax.
x, pmax.
y, max,
11462 rect, firstChannel, lastChannel, maxProcessors );
11491 int maxProcessors = 0 )
const
11494 if ( !ParseSelection( r, firstChannel, lastChannel ) )
11498 if ( m_status.IsInitializationEnabled() )
11499 m_status.Initialize(
"Counting pixel samples", N );
11501 if ( !this->IsRangeClippingEnabled() )
11508 bool useAffinity = m_parallel && Thread::IsRootThread();
11510 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
11511 threads.
Add(
new CountThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
11512 if ( threads.
Length() > 1 )
11515 for ( CountThread& thread : threads )
11516 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
11517 for ( CountThread& thread : threads )
11524 for (
const CountThread& thread : threads )
11525 count += thread.count;
11560 double Mean(
const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
11561 int maxProcessors = 0 )
const
11564 if ( !ParseSelection( r, firstChannel, lastChannel ) )
11568 if ( m_status.IsInitializationEnabled() )
11569 m_status.Initialize(
"Computing mean pixel sample value", N );
11572 bool useAffinity = m_parallel && Thread::IsRootThread();
11574 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
11575 threads.
Add(
new SumThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
11576 if ( threads.
Length() > 1 )
11579 for ( SumThread& thread : threads )
11580 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
11581 for ( SumThread& thread : threads )
11590 for (
const SumThread& thread : threads )
11592 double y = thread.s - e;
11633 double Median(
const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
11634 int maxProcessors = 0 )
const
11637 if ( !ParseSelection( r, firstChannel, lastChannel ) )
11641 if ( m_status.IsInitializationEnabled() )
11642 m_status.Initialize(
"Computing median pixel sample value", N );
11644 if ( N <= 2560000 )
11646 SmpThread S( *
this, r, firstChannel, lastChannel, 0, r.
Height() );
11653 double m = double( *
pcl::Select( S.samples.Begin(), S.samples.At( S.n ), S.n >> 1 ) )/double( P::MaxSampleValue() );
11659 m = (m + double( *
pcl::Select( S.samples.Begin(), S.samples.At( S.n ), (S.n >> 1)-1 ) )/double( P::MaxSampleValue() ))/2;
11665 bool useAffinity = m_parallel && Thread::IsRootThread();
11671 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
11672 threads <<
new MinMaxThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) );
11674 if ( threads.
Length() > 1 )
11677 for ( MinMaxThread& thread : threads )
11678 thread.Start( ThreadPriority::DefaultMax, useAffinity ? i++ : -1 );
11679 for ( MinMaxThread& thread : threads )
11685 sample slow = 0, shigh = 0;
11687 if ( threads[i].count > 0 )
11689 slow = threads[i].min;
11690 shigh = threads[i].max;
11691 count = threads[i].count;
11692 while ( ++i < threads.
Length() )
11693 if ( threads[i].count > 0 )
11695 if ( threads[i].min < slow )
11696 slow = threads[i].min;
11697 if ( shigh < threads[i].max )
11698 shigh = threads[i].max;
11699 count += threads[i].count;
11706 low = double( slow );
11707 high = double( shigh );
11710 const double eps = P::IsComplexSample() ? 2*std::numeric_limits<double>::epsilon() :
11711 (P::IsFloatSample() ? 2*std::numeric_limits<typename P::component>::epsilon() :
11712 0.5/
Pow2(
double( P::BitsPerSample() ) ));
11718 if ( high - low < eps )
11721 return low/double( P::MaxSampleValue() );
11725 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
11726 threads <<
new HistogramThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ), low, high );
11728 double mh = 0, l0 = low, h0 = high;
11731 for (
size_type n = 0, n2 = count >> 1, step = 0, it = 0;; ++it )
11734 if ( it == 0 && step )
11738 if ( threads.
Length() > 1 )
11741 for ( HistogramThread& thread : threads )
11742 thread.Start( ThreadPriority::DefaultMax, useAffinity ? i++ : -1 );
11743 for ( HistogramThread& thread : threads )
11753 if ( (count & 1) == 0 )
11757 for (
int i = 0; ; n += H[i++] )
11758 if ( n + H[i] > n2 )
11760 double range = high - low;
11761 high = (range * (i + 1))/(__PCL_MEDIAN_HISTOGRAM_LENGTH - 1) + low;
11762 low = (range * i)/(__PCL_MEDIAN_HISTOGRAM_LENGTH - 1) + low;
11763 if ( high - low < eps )
11769 return low/double( P::MaxSampleValue() );
11775 return (low + mh)/2/double( P::MaxSampleValue() );
11822 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
11823 int maxProcessors = 0 )
const
11825 if ( k < 0 || k > 1 )
11829 if ( !ParseSelection( r, firstChannel, lastChannel ) )
11833 if ( m_status.IsInitializationEnabled() )
11834 m_status.Initialize(
"Computing order statistic", N );
11836 if ( N <= 2560000 )
11838 SmpThread S( *
this, r, firstChannel, lastChannel, 0, r.
Height() );
11843 return double( *
pcl::Select( S.samples.Begin(), S.samples.At( S.n ),
distance_type( k*(S.n - 1) ) ) )/double( P::MaxSampleValue() );
11847 bool useAffinity = m_parallel && Thread::IsRootThread();
11853 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
11854 threads <<
new MinMaxThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) );
11856 if ( threads.
Length() > 1 )
11859 for ( MinMaxThread& thread : threads )
11860 thread.Start( ThreadPriority::DefaultMax, useAffinity ? i++ : -1 );
11861 for ( MinMaxThread& thread : threads )
11867 sample slow = 0, shigh = 0;
11869 if ( threads[i].count > 0 )
11871 slow = threads[i].min;
11872 shigh = threads[i].max;
11873 count = threads[i].count;
11874 while ( ++i < threads.
Length() )
11875 if ( threads[i].count > 0 )
11877 if ( threads[i].min < slow )
11878 slow = threads[i].min;
11879 if ( shigh < threads[i].max )
11880 shigh = threads[i].max;
11881 count += threads[i].count;
11888 low = double( slow );
11889 high = double( shigh );
11892 const double eps = P::IsComplexSample() ? 2*std::numeric_limits<double>::epsilon() :
11893 (P::IsFloatSample() ? 2*std::numeric_limits<typename P::component>::epsilon() :
11894 0.5/
Pow2(
double( P::BitsPerSample() ) ));
11900 if ( k == 0 || high - low < eps )
11903 return low/double( P::MaxSampleValue() );
11908 return high/double( P::MaxSampleValue() );
11914 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
11915 threads <<
new HistogramThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ), low, high );
11919 if ( threads.
Length() > 1 )
11922 for ( HistogramThread& thread : threads )
11923 thread.Start( ThreadPriority::DefaultMax, useAffinity ? i++ : -1 );
11924 for ( HistogramThread& thread : threads )
11934 for (
int i = 0; ; n += H[i++] )
11935 if ( n + H[i] > index )
11937 double range = high - low;
11938 high = (range * (i + 1))/(__PCL_MEDIAN_HISTOGRAM_LENGTH - 1) + low;
11939 low = (range * i)/(__PCL_MEDIAN_HISTOGRAM_LENGTH - 1) + low;
11940 if ( high - low < eps )
11944 return low/double( P::MaxSampleValue() );
11986 int maxProcessors = 0 )
const
11989 if ( !ParseSelection( r, firstChannel, lastChannel ) )
11993 if ( m_status.IsInitializationEnabled() )
11994 m_status.Initialize(
"Computing variance", N );
11997 bool useAffinity = m_parallel && Thread::IsRootThread();
11999 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
12000 sumThreads.
Add(
new SumThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
12001 if ( sumThreads.
Length() > 1 )
12004 for ( SumThread& thread : sumThreads )
12005 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
12006 for ( SumThread& thread : sumThreads )
12010 sumThreads[0].Run();
12015 for (
const SumThread& thread : sumThreads )
12017 double y = thread.s - e;
12031 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
12032 varThreads.
Add(
new VarThread( *
this, mean, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
12033 if ( varThreads.
Length() > 1 )
12036 for ( VarThread& thread : varThreads )
12037 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
12038 for ( VarThread& thread : varThreads )
12042 varThreads[0].Run();
12044 double var = 0, eps = 0;
12045 for (
const VarThread& thread : varThreads )
12046 var += thread.var, eps += thread.eps;
12050 return (var - eps*eps/n)/(n - 1);
12085 double StdDev(
const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
12086 int maxProcessors = 0 )
const
12088 return pcl::Sqrt(
Variance( rect, firstChannel, lastChannel, maxProcessors ) );
12131 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
12132 int maxProcessors = 0 )
const
12135 if ( !ParseSelection( r, firstChannel, lastChannel ) )
12139 if ( m_status.IsInitializationEnabled() )
12140 m_status.Initialize(
"Computing average absolute deviation", N );
12143 bool useAffinity = m_parallel && Thread::IsRootThread();
12145 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
12146 threads.
Add(
new SumAbsDevThread( *
this, center, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
12147 if ( threads.
Length() > 1 )
12150 for ( SumAbsDevThread& thread : threads )
12151 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
12152 for ( SumAbsDevThread& thread : threads )
12161 for (
const SumAbsDevThread& thread : threads )
12163 double y = thread.s - e;
12200 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
12201 int maxProcessors = 0 )
const
12204 if ( !ParseSelection( r, firstChannel, lastChannel ) )
12208 if ( m_status.IsInitializationEnabled() )
12209 m_status.Initialize(
"Computing two-sided average absolute deviation", N );
12212 bool useAffinity = m_parallel && Thread::IsRootThread();
12214 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
12215 threads.
Add(
new TwoSidedSumAbsDevThread( *
this, center, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
12216 if ( threads.
Length() > 1 )
12219 for ( TwoSidedSumAbsDevThread& thread : threads )
12220 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
12221 for ( TwoSidedSumAbsDevThread& thread : threads )
12227 double s0 = 0, s1 = 0;
12228 double e0 = 0, e1 = 0;
12230 for (
const TwoSidedSumAbsDevThread& thread : threads )
12232 double y = thread.s0 - e0;
12237 y = thread.s1 - e1;
12248 return { (n0 > 0) ? s0/n0 : 0.0,
12249 (n1 > 0) ? s1/n1 : 0.0 };
12287 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
12288 int maxProcessors = 0 )
const
12291 if ( !ParseSelection( r, firstChannel, lastChannel ) )
12295 if ( m_status.IsInitializationEnabled() )
12296 m_status.Initialize(
"Computing median absolute deviation", N );
12298 if ( N <= 2560000 )
12300 AbsDevSmpThread S( *
this, center, r, firstChannel, lastChannel, 0, r.
Height() );
12307 double m = *
pcl::Select( S.values.Begin(), S.values.At( S.n ), S.n >> 1 );
12313 m = (m + *
pcl::Select( S.values.Begin(), S.values.At( S.n ), (S.n >> 1)-1 ))/2;
12319 bool useAffinity = m_parallel && Thread::IsRootThread();
12325 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
12326 threads <<
new ExtremeAbsDevThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ), center );
12328 if ( threads.
Length() > 1 )
12331 for ( ExtremeAbsDevThread& thread : threads )
12332 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
12333 for ( ExtremeAbsDevThread& thread : threads )
12340 if ( threads[i].count > 0 )
12342 low = threads[i].minAbsDev;
12343 high = threads[i].maxAbsDev;
12344 count += threads[i].count;
12345 while ( ++i < threads.
Length() )
12346 if ( threads[i].count > 0 )
12348 if ( threads[i].minAbsDev < low )
12349 low = threads[i].minAbsDev;
12350 if ( threads[i].maxAbsDev > high )
12351 high = threads[i].maxAbsDev;
12352 count += threads[i].count;
12360 const double eps = 2*std::numeric_limits<double>::epsilon();
12361 if ( count == 0 || high - low < eps )
12368 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
12369 threads <<
new AbsDevHistogramThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ), center, low, high );
12371 double mh = 0, l0 = low, h0 = high;
12374 for (
size_type n = 0, n2 = count >> 1, step = 0, it = 0;; ++it )
12377 if ( it == 0 && step )
12381 if ( threads.
Length() > 1 )
12384 for ( AbsDevHistogramThread& thread : threads )
12385 thread.Start( ThreadPriority::DefaultMax, useAffinity ? i++ : -1 );
12386 for ( AbsDevHistogramThread& thread : threads )
12396 if ( (count & 1) == 0 )
12400 for (
int i = 0; ; n += H[i++] )
12401 if ( n + H[i] > n2 )
12403 double range = high - low;
12404 high = (range * (i + 1))/(__PCL_MEDIAN_HISTOGRAM_LENGTH - 1) + low;
12405 low = (range * i)/(__PCL_MEDIAN_HISTOGRAM_LENGTH - 1) + low;
12406 if ( high - low < eps )
12418 return (low + mh)/2;
12454 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
12455 int maxProcessors = 0 )
const
12458 if ( !ParseSelection( r, firstChannel, lastChannel ) )
12462 if ( m_status.IsInitializationEnabled() )
12463 m_status.Initialize(
"Computing two-sided median absolute deviation", N );
12465 if ( N <= 2560000 )
12467 TwoSidedAbsDevSmpThread S( *
this, center, r, firstChannel, lastChannel, 0, r.
Height() );
12475 bool useAffinity = m_parallel && Thread::IsRootThread();
12477 double minLow = 0, minHigh = 0, maxLow = 0, maxHigh = 0;
12481 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
12482 threads <<
new TwoSidedExtremeAbsDevThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ), center );
12484 if ( threads.
Length() > 1 )
12487 for ( TwoSidedExtremeAbsDevThread& thread : threads )
12488 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
12489 for ( TwoSidedExtremeAbsDevThread& thread : threads )
12496 if ( threads[i].nLow > 0 )
12498 minLow = threads[i].minAbsDevLow;
12499 maxLow = threads[i].maxAbsDevLow;
12500 nLow = threads[i].nLow;
12501 while ( ++i < threads.
Length() )
12502 if ( threads[i].nLow > 0 )
12504 if ( threads[i].minAbsDevLow < minLow )
12505 minLow = threads[i].minAbsDevLow;
12506 if ( threads[i].maxAbsDevLow > maxLow )
12507 maxLow = threads[i].maxAbsDevLow;
12508 nLow += threads[i].nLow;
12514 if ( threads[i].nHigh > 0 )
12516 minHigh = threads[i].minAbsDevHigh;
12517 maxHigh = threads[i].maxAbsDevHigh;
12518 nHigh = threads[i].nHigh;
12519 while ( ++i < threads.
Length() )
12520 if ( threads[i].nHigh > 0 )
12522 if ( threads[i].minAbsDevHigh < minHigh )
12523 minHigh = threads[i].minAbsDevHigh;
12524 if ( threads[i].maxAbsDevHigh > maxHigh )
12525 maxHigh = threads[i].maxAbsDevHigh;
12526 nHigh += threads[i].nHigh;
12535 double sideLow, sideHigh;
12537 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
12538 threads <<
new TwoSidedAbsDevHistogramThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ), center, side, sideLow, sideHigh );
12540 const double eps = 2*std::numeric_limits<double>::epsilon();
12542 for ( side = 0; side < 2; ++side )
12551 sideLow = side ? minHigh : minLow;
12552 sideHigh = side ? maxHigh : maxLow;
12553 if ( sideHigh - sideLow < eps )
12559 double mh = 0, h0 = sideHigh;
12562 for (
size_type count = 0, n2 = n >> 1, step = 0, it = 0;; ++it )
12565 if ( it == 0 && step )
12569 if ( threads.
Length() > 1 )
12572 for ( TwoSidedAbsDevHistogramThread& thread : threads )
12573 thread.Start( ThreadPriority::DefaultMax, useAffinity ? i++ : -1 );
12574 for ( TwoSidedAbsDevHistogramThread& thread : threads )
12584 if ( (n & 1) == 0 )
12588 for (
int i = 0; ; count += H[i++] )
12589 if ( count + H[i] > n2 )
12591 double range = sideHigh - sideLow;
12592 sideHigh = (range * (i + 1))/(__PCL_MEDIAN_HISTOGRAM_LENGTH - 1) + sideLow;
12593 sideLow = (range * i)/(__PCL_MEDIAN_HISTOGRAM_LENGTH - 1) + sideLow;
12594 if ( sideHigh - sideLow < eps )
12598 mad[side] = sideLow;
12599 goto __madNextSide;
12603 mad[side] = (sideLow + mh)/2;
12604 goto __madNextSide;
12624 return { mad[0], mad[1] };
12672 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
12673 int maxProcessors = 0 )
const
12676 if ( !ParseSelection( r, firstChannel, lastChannel ) )
12680 double kd = k * sigma;
12681 if ( kd < 0 || 1 + kd == 1 )
12687 if ( m_status.IsInitializationEnabled() )
12688 m_status.Initialize(
"Computing biweight midvariance", N );
12691 bool useAffinity = m_parallel && Thread::IsRootThread();
12693 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
12694 threads.
Add(
new BWMVThread( *
this, center, kd, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
12695 if ( threads.
Length() > 1 )
12698 for ( BWMVThread& thread : threads )
12699 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
12700 for ( BWMVThread& thread : threads )
12706 double num = 0, den = 0;
12708 for (
const BWMVThread& thread : threads )
12720 return (n >= 2 && 1 + den != 1) ? (reducedLength ? nr : n)*num/den : 0.0;
12752 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
12753 int maxProcessors = 0 )
const
12756 if ( !ParseSelection( r, firstChannel, lastChannel ) )
12760 double kd0 = k * sigma.
low;
12761 double kd1 = k * sigma.
high;
12762 if ( kd0 < 0 || 1 + kd0 == 1 || kd1 < 0 || 1 + kd1 == 1 )
12768 if ( m_status.IsInitializationEnabled() )
12769 m_status.Initialize(
"Computing two-sided biweight midvariance", N );
12772 bool useAffinity = m_parallel && Thread::IsRootThread();
12774 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
12775 threads.
Add(
new TwoSidedBWMVThread( *
this, center, kd0, kd1, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
12776 if ( threads.
Length() > 1 )
12779 for ( TwoSidedBWMVThread& thread : threads )
12780 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
12781 for ( TwoSidedBWMVThread& thread : threads )
12787 double num0 = 0, den0 = 0, num1 = 0, den1 = 0;
12788 size_type n0 = 0, n1 = 0, nr0 = 0, nr1 = 0;
12789 for (
const TwoSidedBWMVThread& thread : threads )
12791 num0 += thread.num0;
12792 den0 += thread.den0;
12793 num1 += thread.num1;
12794 den1 += thread.den1;
12807 return { (n0 >= 2 && 1 + den0 != 1) ? (reducedLength ? nr0 : n0)*num0/den0 : 0.0,
12808 (n1 >= 2 && 1 + den1 != 1) ? (reducedLength ? nr1 : n1)*num1/den1 : 0.0 };
12855 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
12856 int maxProcessors = 0 )
const
12859 if ( !ParseSelection( r, firstChannel, lastChannel ) )
12863 if ( m_status.IsInitializationEnabled() )
12864 m_status.Initialize(
"Computing percentage bend midvariance", N );
12867 bool useAffinity = m_parallel && Thread::IsRootThread();
12869 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
12870 threads.
Add(
new DSmpThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
12871 if ( threads.
Length() > 1 )
12874 for ( DSmpThread& thread : threads )
12875 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
12876 for ( DSmpThread& thread : threads )
12883 for ( DSmpThread& thread : threads )
12884 if ( !thread.values.IsEmpty() )
12886 values.
Add( thread.values.Begin(), thread.values.At( thread.n ) );
12887 thread.values.Clear();
12940 double Sn(
const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
int maxProcessors = 0 )
const
12943 if ( !ParseSelection( r, firstChannel, lastChannel ) )
12947 if ( m_status.IsInitializationEnabled() )
12948 m_status.Initialize(
"Computing Sn scale estimate", N );
12951 bool useAffinity = m_parallel && Thread::IsRootThread();
12953 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
12954 threads.
Add(
new DSmpThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
12955 if ( threads.
Length() > 1 )
12958 for ( DSmpThread& thread : threads )
12959 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
12960 for ( DSmpThread& thread : threads )
12967 for ( DSmpThread& thread : threads )
12968 if ( !thread.values.IsEmpty() )
12970 values.
Add( thread.values.Begin(), thread.values.At( thread.n ) );
12971 thread.values.Clear();
13023 double Qn(
const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
int maxProcessors = 0 )
const
13026 if ( !ParseSelection( r, firstChannel, lastChannel ) )
13030 if ( m_status.IsInitializationEnabled() )
13031 m_status.Initialize(
"Computing Qn scale estimate", N );
13034 bool useAffinity = m_parallel && Thread::IsRootThread();
13036 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
13037 threads.
Add(
new DSmpThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
13038 if ( threads.
Length() > 1 )
13041 for ( DSmpThread& thread : threads )
13042 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
13043 for ( DSmpThread& thread : threads )
13050 for ( DSmpThread& thread : threads )
13051 if ( !thread.values.IsEmpty() )
13053 values.
Add( thread.values.Begin(), thread.values.At( thread.n ) );
13054 thread.values.Clear();
13101 double Norm(
const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
13102 int maxProcessors = 0 )
const
13105 if ( !ParseSelection( r, firstChannel, lastChannel ) )
13109 if ( m_status.IsInitializationEnabled() )
13110 m_status.Initialize(
"Computing norm", N );
13113 bool useAffinity = m_parallel && Thread::IsRootThread();
13115 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
13116 threads.
Add(
new SumThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
13117 if ( threads.
Length() > 1 )
13120 for ( SumThread& thread : threads )
13121 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
13122 for ( SumThread& thread : threads )
13130 for (
const SumThread& thread : threads )
13132 double y = thread.s - e;
13140 return (1 + s != 1) ? s : 0.0;
13174 int maxProcessors = 0 )
const
13177 if ( !ParseSelection( r, firstChannel, lastChannel ) )
13181 if ( m_status.IsInitializationEnabled() )
13182 m_status.Initialize(
"Computing modulus", N );
13185 bool useAffinity = m_parallel && Thread::IsRootThread();
13187 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
13188 threads.
Add(
new SumAbsThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
13189 if ( threads.
Length() > 1 )
13192 for ( SumAbsThread& thread : threads )
13193 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
13194 for ( SumAbsThread& thread : threads )
13202 for (
const SumAbsThread& thread : threads )
13204 double y = thread.s - e;
13212 return (1 + s != 1) ? s : 0.0;
13244 int maxProcessors = 0 )
const
13247 if ( !ParseSelection( r, firstChannel, lastChannel ) )
13251 if ( m_status.IsInitializationEnabled() )
13252 m_status.Initialize(
"Computing sum of squares", N );
13255 bool useAffinity = m_parallel && Thread::IsRootThread();
13257 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
13258 threads.
Add(
new SumSqrThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
13259 if ( threads.
Length() > 1 )
13262 for ( SumSqrThread& thread : threads )
13263 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
13264 for ( SumSqrThread& thread : threads )
13272 for (
const SumSqrThread& thread : threads )
13274 double y = thread.s - e;
13282 return (1 + s != 1) ? s : 0.0;
13314 int maxProcessors = 0 )
const
13317 if ( !ParseSelection( r, firstChannel, lastChannel ) )
13321 if ( m_status.IsInitializationEnabled() )
13322 m_status.Initialize(
"Computing mean of squares", N );
13325 bool useAffinity = m_parallel && Thread::IsRootThread();
13327 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
13328 threads.
Add(
new SumSqrThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
13329 if ( threads.
Length() > 1 )
13332 for ( SumSqrThread& thread : threads )
13333 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
13334 for ( SumSqrThread& thread : threads )
13343 for (
const SumSqrThread& thread : threads )
13345 double y = thread.s - e;
13399 int maxProcessors = 0 )
const
13401 PCL_PRECONDITION( maxDegree > 0 )
13402 maxDegree =
pcl::Max( 1, maxDegree );
13405 if ( !ParseSelection( r, firstChannel, lastChannel ) )
13409 if ( m_status.IsInitializationEnabled() )
13410 m_status.Initialize(
"Computing norms", N );
13413 bool useAffinity = m_parallel && Thread::IsRootThread();
13415 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
13416 threads.
Add(
new NormThread( *
this, maxDegree, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
13417 if ( threads.
Length() > 1 )
13420 for ( NormThread& thread : threads )
13421 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
13422 for ( NormThread& thread : threads )
13428 Vector R( 0.0, maxDegree );
13429 Vector e( 0.0, maxDegree );
13430 for (
const NormThread& thread : threads )
13431 for (
int i = 0; i < maxDegree; ++i )
13433 double y = thread.R[i] - e[i];
13434 double t = R[i] + y;
13435 e[i] = (t - R[i]) - y;
13438 for (
int i = 0; i < maxDegree; ++i )
13439 if ( 1 + R[i] == 1 )
13461 if ( !ParseChannel( channel ) )
13463 return pcl::Hash64( m_channelData( channel ), ChannelSize(), seed );
13480 if ( !ParseChannel( channel ) )
13482 return pcl::Hash32( m_channelData( channel ), ChannelSize(), seed );
13491 return Hash64( channel, seed );
13516 if ( !ParseSelection( r, firstChannel, lastChannel ) )
13520 int numberOfChannels = 1 + lastChannel - firstChannel;
13522 if ( m_status.IsInitializationEnabled() )
13523 m_status.Initialize(
"Writing to raw-storage image stream", N*numberOfChannels );
13528 file.
WriteUI32( (firstChannel == 0 && lastChannel >= 2) ? m_colorSpace : ColorSpace::Gray );
13530 if ( r == Bounds() )
13532 for (
int i = firstChannel; i <= lastChannel; ++i, m_status += N )
13533 file.
Write( (
const void*)m_pixelData[i],
fsize_type( ChannelSize() ) );
13537 for (
int i = firstChannel, w = r.
Width(), h = r.
Height(); i <= lastChannel; ++i )
13540 for (
int j = 0; j < h; ++j, p += m_width, m_status += w )
13541 file.
Write( (
const void*)p, w*BytesPerSample() );
13559 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
const
13561 File file = File::CreateFileForWriting( filePath );
13562 return Write( file, rect, firstChannel, lastChannel );
13603 int width, height, numberOfChannels, colorSpace;
13606 file.
ReadUI32( numberOfChannels );
13609 AllocateData( width, height, numberOfChannels, color_space( colorSpace ) );
13616 if ( m_status.IsInitializationEnabled() )
13617 m_status.Initialize(
"Reading from raw-storage image stream", N*m_numberOfChannels );
13618 for (
int i = 0; i < m_numberOfChannels; ++i, m_status += N )
13619 file.
Read( (
void*)m_pixelData[i],
fsize_type( ChannelSize() ) );
13638 File file = File::OpenFileForReading( filePath );
13639 return Read( file );
13674 template <
typename T>
13677 if ( left == 0 && top == 0 && right == 0 && bottom == 0 )
13680 if ( m_width+left+right <= 0 || m_height+top+bottom <= 0 )
13686 Rect r( -left, -top, m_width+right, m_height+bottom );
13687 int width = r.
Width();
13688 int height = r.
Height();
13690 if ( !Intersects( r ) )
13691 return AllocateData( width, height, m_numberOfChannels, m_colorSpace ).Fill( fillValues );
13697 if ( m_status.IsInitializationEnabled() )
13698 m_status.Initialize(
String().Format(
"Crop margins: %+d, %+d, %+d, %+d",
13699 left, top, right, bottom ), N*m_numberOfChannels );
13701 sample** newData =
nullptr;
13705 newData = m_allocator.AllocateChannelSlots( m_numberOfChannels );
13707 for (
int c = 0; c < m_numberOfChannels; ++c, m_status += N )
13709 sample* __restrict__ f = newData[c] = m_allocator.AllocatePixels( N );
13710 sample v = (c < fillValues.
Length()) ? P::ToSample( fillValues[c] ) : P::MinSampleValue();
13712 for (
int i = r.
y0, j; i < r.
y1; )
13714 for ( ; i < 0; ++i )
13717 for (
int j = 0; j < width; ++j )
13722 for ( j = r.
x0; j < 0; ++j )
13725 for (
const sample* f0 = PixelAddress( j, i, c ); j < r.
x1; )
13728 if ( ++j == m_width )
13731 for ( ; j < r.
x1; ++j )
13736 if ( ++i == m_height )
13737 for ( ; i < r.
y1; ++i )
13740 for (
int j = 0; j < width; ++j )
13748 for (
int c = 0; c < m_numberOfChannels; ++c )
13750 m_allocator.Deallocate( m_pixelData[c] );
13751 m_pixelData[c] = newData[c];
13753 m_allocator.Deallocate( newData );
13756 m_allocator.SetSharedGeometry( m_width = width, m_height = height, m_numberOfChannels );
13764 m_data->Deallocate();
13771 if ( newData !=
nullptr )
13773 for (
int i = 0; i < m_numberOfChannels; ++i )
13774 if ( newData[i] !=
nullptr )
13775 m_allocator.Deallocate( newData[i] ), newData[i] =
nullptr;
13776 m_allocator.Deallocate( newData );
13795 return CropBy( left, top, right, bottom,
sample_vector() );
13808 template <
typename T>
13812 return CropBy( -r.
x0, -r.
y0, r.
x1 - m_width, r.
y1 - m_height, fillValues );
13841 template <
typename T>
13844 return CropTo(
Rect( x0, y0, x1, y1 ), fillValues );
13873 template <
typename T>
13876 return CropTo( m_rectangle, fillValues );
13916 template <
typename T>
13919 return CropBy( dx, dy, -dx, -dy, fillValues );
13944 template <
typename T>
13947 return ShiftBy( x, y, fillValues );
13976 template <
typename T>
13979 return ShiftBy( p.
x, p.
y, fillValues );
14002 template <
typename T>
14005 int dx2 = (width - m_width) >> 1;
14006 int dy2 = (height - m_height) >> 1;
14007 return CropBy( dx2, dy2, width-m_width-dx2, height-m_height-dy2, fillValues );
14031 template <
typename T>
14034 int dx = width - m_width;
14035 int dy = height - m_height;
14036 return CropBy( 0, 0, dx, dy, fillValues );
14060 template <
typename T>
14063 int dx = width - m_width;
14064 int dy = height - m_height;
14065 return CropBy( dx, 0, 0, dy, fillValues );
14089 template <
typename T>
14092 int dx = width - m_width;
14093 int dy = height - m_height;
14094 return CropBy( 0, dy, dx, 0, fillValues );
14111 return ShiftToBottomLeft( width, height,
sample_vector() );
14118 template <
typename T>
14121 int dx = width - m_width;
14122 int dy = height - m_height;
14123 return CropBy( dx, dy, 0, 0, fillValues );
14140 return ShiftToBottomRight( width, height,
sample_vector() );
14153 template <
typename T>
14156 return ShiftTo( m_point, fillValues );
14216 if ( colorSpace == m_colorSpace )
14224 if ( m_status.IsInitializationEnabled() )
14225 m_status.Initialize(
"In-place color space conversion: "
14230 int n = m_numberOfChannels;
14232 if ( m_colorSpace == ColorSpace::Gray )
14234 sample** oldData = m_pixelData;
14235 sample** newData =
nullptr;
14240 newData = m_allocator.AllocateChannelSlots( 2+n );
14243 newData[0] = oldData[0];
14246 newData[1] = m_allocator.AllocatePixels( N );
14247 ::memcpy( newData[1], oldData[0], ChannelSize() );
14248 newData[2] = m_allocator.AllocatePixels( N );
14249 ::memcpy( newData[2], oldData[0], ChannelSize() );
14252 for (
int i = 1; i < n; ++i )
14253 newData[i+2] = oldData[i];
14257 m_pixelData = newData;
14259 m_numberOfChannels += 2;
14260 m_colorSpace = ColorSpace::RGB;
14261 m_data->UpdateSharedImage();
14263 ResetChannelRange();
14265 m_allocator.Deallocate( oldData );
14269 m_data->Deallocate();
14276 if ( newData !=
nullptr )
14278 newData[0] =
nullptr;
14279 if ( newData[1] !=
nullptr )
14280 m_allocator.Deallocate( newData[1] ), newData[1] =
nullptr;
14281 if ( newData[2] !=
nullptr )
14282 m_allocator.Deallocate( newData[2] ), newData[2] =
nullptr;
14283 m_allocator.Deallocate( newData );
14288 if ( colorSpace == ColorSpace::RGB )
14299 m_parallel ? ((maxProcessors > 0) ? maxProcessors : m_maxProcessors) : 1 );
14302 for (
size_type i = 0, n = 0; i < L.Length(); n += L[i++] )
14303 threads.
Add(
new ColorSpaceConversionThread( *
this, data, colorSpace, n, n + L[i] ) );
14304 RunThreads( threads, data );
14309 if ( colorSpace == ColorSpace::Gray )
14311 sample** oldData = m_pixelData;
14312 sample** newData =
nullptr;
14316 newData = m_allocator.AllocateChannelSlots( n-2 );
14317 newData[0] = oldData[0];
14318 for (
int i = 3; i < n; ++i )
14319 newData[i-2] = oldData[i];
14321 m_pixelData = newData;
14323 m_numberOfChannels -= 2;
14324 m_colorSpace = ColorSpace::Gray;
14325 m_data->UpdateSharedImage();
14327 ResetChannelRange();
14329 m_allocator.Deallocate( oldData[1] );
14330 m_allocator.Deallocate( oldData[2] );
14331 m_allocator.Deallocate( oldData );
14335 m_data->Deallocate();
14337 if ( newData !=
nullptr )
14338 m_allocator.Deallocate( newData );
14344 m_allocator.SetSharedColor( m_colorSpace = colorSpace, m_RGBWS );
14417 template <
class P1>
14421 if ( !ParseRect( r ) )
14427 Y.AllocateData( r );
14428 if ( !Y.IsShared() )
14429 Y.SetRGBWorkingSpace( m_RGBWS );
14433 if ( m_colorSpace == ColorSpace::Gray || m_colorSpace == ColorSpace::CIEXYZ )
14435 if ( m_status.IsInitializationEnabled() )
14436 m_status.Initialize(
"Transferring pixel data", N );
14439 int cY = (m_colorSpace == ColorSpace::Gray) ? 0 : 1;
14440 if ( r == Bounds() )
14442 const sample* __restrict__ f = m_pixelData[cY];
14443 P1::Copy( g, f, N );
14447 const sample* __restrict__ f = PixelAddress( r.
LeftTop(), cY );
14448 for (
int i = 0; i < Y.Height(); ++i, f += m_width, g += Y.Width() )
14449 P1::Copy( g, f, Y.Width() );
14456 if ( m_status.IsInitializationEnabled() )
14457 m_status.Initialize(
"Computing CIE Y component", N );
14459 Array<size_type> L = OptimalThreadRows( Y.Height(), Y.Width(), maxProcessors );
14462 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
14463 threads.
Add(
new GetLuminanceThread<P1>( Y, *
this, data, r, n, n +
int( L[i] ) ) );
14464 RunThreads( threads, data );
14480 void GetLuminance(
ImageVariant& Y,
const Rect& rect =
Rect( 0 ),
int maxProcessors = 0 )
const;
14549 template <
class P1>
14553 if ( !ParseRect( r ) )
14559 L.AllocateData( r );
14560 if ( !L.IsShared() )
14561 L.SetRGBWorkingSpace( m_RGBWS );
14565 if ( m_colorSpace == ColorSpace::Gray || m_colorSpace == ColorSpace::CIELab || m_colorSpace == ColorSpace::CIELch )
14567 if ( m_status.IsInitializationEnabled() )
14568 m_status.Initialize(
"Transferring pixel data", N );
14571 if ( r == Bounds() )
14573 const sample* __restrict__ f = *m_pixelData;
14574 P1::Copy( g, f, N );
14578 const sample* __restrict__ f = PixelAddress( r.
LeftTop() );
14579 for (
int i = 0; i < L.Height(); ++i, f += m_width, g += L.Width() )
14580 P1::Copy( g, f, L.Width() );
14587 if ( m_status.IsInitializationEnabled() )
14588 m_status.Initialize(
"Computing CIE L* component", N );
14590 Array<size_type> R = OptimalThreadRows( L.Height(), L.Width(), maxProcessors );
14593 for (
int i = 0, n = 0; i < int( R.Length() ); n += int( R[i++] ) )
14594 threads.
Add(
new GetLightnessThread<P1>( L, *
this, data, r, n, n +
int( R[i] ) ) );
14595 RunThreads( threads, data );
14611 void GetLightness(
ImageVariant& L,
const Rect& rect =
Rect( 0 ),
int maxProcessors = 0 )
const;
14672 template <
class P1>
14676 if ( !ParseRect( r ) )
14682 I.AllocateData( r );
14683 if ( !I.IsShared() )
14684 I.SetRGBWorkingSpace( m_RGBWS );
14688 if ( m_colorSpace == ColorSpace::Gray || m_colorSpace == ColorSpace::HSI )
14690 if ( m_status.IsInitializationEnabled() )
14691 m_status.Initialize(
"Transferring pixel data", N );
14694 int cI = (m_colorSpace == ColorSpace::Gray) ? 0 : 2;
14695 if ( r == Bounds() )
14697 const sample* __restrict__ f = m_pixelData[cI];
14698 P1::Copy( g, f, N );
14702 const sample* __restrict__ f = PixelAddress( r.
LeftTop(), cI );
14703 for (
int i = 0; i < I.Height(); ++i, f += m_width, g += I.Width() )
14704 P1::Copy( g, f, I.Width() );
14711 if ( m_status.IsInitializationEnabled() )
14712 m_status.Initialize(
"Computing intensity component", N );
14714 Array<size_type> L = OptimalThreadRows( I.Height(), I.Width(), maxProcessors );
14717 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
14718 threads.
Add(
new GetIntensityThread<P1>( I, *
this, data, r, n, n +
int( L[i] ) ) );
14719 RunThreads( threads, data );
14735 void GetIntensity(
ImageVariant& I,
const Rect& rect =
Rect( 0 ),
int maxProcessors = 0 )
const;
14798 template <
class P1>
14801 int maxProcessors = 0 )
14804 if ( !Y.ParseRect( r ) )
14808 if ( p.
x == int_max || p.
y == int_max )
14813 if ( (r.
x0 -= p.
x) >= r.
x1 )
14817 else if ( p.
x >= m_width )
14822 if ( (r.
y0 -= p.
y) >= r.
y1 )
14826 else if ( p.
y >= m_height )
14836 if ( m_colorSpace == ColorSpace::Gray &&
14837 (Y.ColorSpace() == ColorSpace::Gray || Y.ColorSpace() == ColorSpace::CIEXYZ) )
14839 if ( m_status.IsInitializationEnabled() )
14840 m_status.Initialize(
"Transferring pixel data", N );
14842 int c0 = (Y.ColorSpace() == ColorSpace::Gray) ? 0 : 1;
14844 sample* __restrict__ f = PixelAddress( p );
14845 for (
int i = 0, w = r.
Width(), h = r.
Height(); i < h; ++i, f += m_width, g += Y.Width(), m_status += w )
14846 P::Copy( f, g, w );
14850 if ( m_status.IsInitializationEnabled() )
14851 m_status.Initialize(
"Importing CIE Y component", N );
14856 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
14857 threads.
Add(
new SetLuminanceThread<P1>( *
this, Y, data, p, r, n, n +
int( L[i] ) ) );
14858 RunThreads( threads, data );
14878 int maxProcessors = 0 );
14939 template <
class P1>
14942 int maxProcessors = 0 )
14945 if ( !L.ParseRect( r ) )
14949 if ( p.
x == int_max || p.
y == int_max )
14954 if ( (r.
x0 -= p.
x) >= r.
x1 )
14958 else if ( p.
x >= m_width )
14963 if ( (r.
y0 -= p.
y) >= r.
y1 )
14967 else if ( p.
y >= m_height )
14977 if ( m_colorSpace == ColorSpace::Gray &&
14978 (L.ColorSpace() == ColorSpace::Gray ||
14979 L.ColorSpace() == ColorSpace::CIELab || L.ColorSpace() == ColorSpace::CIELch) )
14981 if ( m_status.IsInitializationEnabled() )
14982 m_status.Initialize(
"Transferring pixel data", N );
14985 sample* __restrict__ f = PixelAddress( p );
14986 for (
int i = 0, w = r.
Width(), h = r.
Height(); i < h; ++i, f += m_width, g += L.Width(), m_status += w )
14987 P::Copy( f, g, w );
14991 if ( m_status.IsInitializationEnabled() )
14992 m_status.Initialize(
"Importing CIE L* component", N );
14997 for (
int i = 0, n = 0; i < int( R.Length() ); n += int( R[i++] ) )
14998 threads.
Add(
new SetLightnessThread<P1>( *
this, L, data, p, r, n, n +
int( R[i] ) ) );
14999 RunThreads( threads, data );
15019 int maxProcessors = 0 );
15061 const Rect& rect =
Rect( 0 ),
int channel = -1,
15065 if ( !ParseSelection( r, channel ) )
15067 if ( r == Bounds() )
15068 return compressor.
Compress( m_channelData( channel ), ChannelSize(), perf );
15091 sample** data =
nullptr;
15103 pixel_allocator allocator;
15120 LinkWithClientImage( image );
15126 Data( GenericImage* image,
void* handle )
15127 : allocator( handle )
15129 SynchronizeWithSharedImage();
15130 LinkWithClientImage( image );
15136 Data( GenericImage* image,
int width,
int height,
int numberOfChannels,
int colorSpace )
15137 : allocator( width, height, numberOfChannels, colorSpace )
15139 SynchronizeWithSharedImage();
15140 LinkWithClientImage( image );
15143 void Attach( GenericImage* image )
15145 ReferenceCounter::Attach();
15146 LinkWithClientImage( image );
15157 bool IsShared() const noexcept
15159 return allocator.IsShared();
15162 bool IsEmpty() const noexcept
15164 return data ==
nullptr;
15167 void Allocate(
int width,
int height,
int numberOfChannels, color_space colorSpace )
15169 if ( width <= 0 || height <= 0 || numberOfChannels <= 0 )
15176 throw Error(
"GenericImage::Data::Allocate(): Insufficient number of channels" );
15178 if ( data !=
nullptr )
15182 if ( numberOfChannels != geometry.numberOfChannels )
15184 sample** newData =
nullptr;
15185 int m =
pcl::Min( geometry.numberOfChannels, numberOfChannels );
15189 newData = allocator.AllocateChannelSlots( numberOfChannels );
15190 for (
int i = 0; i < m; ++i )
15191 newData[i] = data[i];
15192 for (
int i = m; i < numberOfChannels; ++i )
15193 newData[i] = allocator.AllocatePixels( width, height );
15197 for (
int i = m; i < geometry.numberOfChannels; ++i )
15198 if ( data[i] !=
nullptr )
15199 allocator.Deallocate( data[i] ), data[i] =
nullptr;
15200 allocator.Deallocate( data );
15212 if ( newData !=
nullptr )
15214 for (
int i = m; i < numberOfChannels; ++i )
15215 if ( newData[i] !=
nullptr )
15216 allocator.Deallocate( newData[i] ), newData[i] =
nullptr;
15217 allocator.Deallocate( newData );
15225 sample** newData =
nullptr;
15229 newData = allocator.AllocateChannelSlots( numberOfChannels );
15230 for (
int i = 0; i < numberOfChannels; ++i )
15231 newData[i] = allocator.AllocatePixels( width, height );
15235 for (
int i = 0; i < geometry.numberOfChannels; ++i )
15236 if ( data[i] !=
nullptr )
15237 allocator.Deallocate( data[i] ), data[i] =
nullptr;
15238 allocator.Deallocate( data );
15250 if ( newData !=
nullptr )
15252 for (
int i = 0; i < numberOfChannels; ++i )
15253 if ( newData[i] !=
nullptr )
15254 allocator.Deallocate( newData[i] ), newData[i] =
nullptr;
15255 allocator.Deallocate( newData );
15265 data = allocator.AllocateChannelSlots( numberOfChannels );
15266 for (
int i = 0; i < numberOfChannels; ++i )
15267 data[i] = allocator.AllocatePixels( width, height );
15271 if ( data !=
nullptr )
15273 for (
int i = 0; i < numberOfChannels; ++i )
15274 if ( data[i] !=
nullptr )
15275 allocator.Deallocate( data[i] ), data[i] =
nullptr;
15276 allocator.Deallocate( data );
15283 geometry.width = width;
15284 geometry.height = height;
15285 geometry.numberOfChannels = numberOfChannels;
15287 color.colorSpace = colorSpace;
15289 UpdateSharedImage();
15292 void Import( sample** newData,
int width,
int height,
int numberOfChannels, color_space colorSpace )
15294 if ( newData != data )
15298 if ( newData !=
nullptr && width > 0 && height > 0 && numberOfChannels > 0 )
15301 throw Error(
"GenericImage::Data::Import(): Insufficient number of channels" );
15305 geometry.width = width;
15306 geometry.height = height;
15307 geometry.numberOfChannels = numberOfChannels;
15309 color.colorSpace = colorSpace;
15311 UpdateSharedImage();
15318 sample** oldData = data;
15320 UpdateSharedImage();
15326 if ( data !=
nullptr )
15328 for (
int i = 0; i < geometry.numberOfChannels; ++i )
15329 if ( data[i] !=
nullptr )
15330 allocator.Deallocate( data[i] ), data[i] =
nullptr;
15331 allocator.Deallocate( data );
15333 UpdateSharedImage();
15337 Data* Clone( GenericImage* image )
const
15339 Data* clone =
nullptr;
15346 clone->data = clone->allocator.AllocateChannelSlots( geometry.numberOfChannels );
15347 for (
int i = 0; i < geometry.numberOfChannels; ++i )
15349 clone->data[i] = clone->allocator.AllocatePixels( geometry.width, geometry.height );
15350 P::Copy( clone->data[i], data[i], geometry.NumberOfPixels() );
15353 clone->geometry.Assign( geometry );
15354 clone->color.Assign( color );
15357 clone->LinkWithClientImage( image );
15362 if ( clone !=
nullptr )
15364 clone->Deallocate();
15378 void UpdateSharedImage()
15380 allocator.SetSharedData( data );
15381 allocator.SetSharedGeometry( geometry.width, geometry.height, geometry.numberOfChannels );
15382 allocator.SetSharedColor( color.colorSpace, color.RGBWS );
15385 void SynchronizeWithSharedImage()
15387 data = allocator.GetSharedData();
15388 allocator.GetSharedGeometry( geometry.width, geometry.height, geometry.numberOfChannels );
15389 allocator.GetSharedColor( color.colorSpace, color.RGBWS );
15396 void LinkWithClientImage( GenericImage* image )
15398 if ( image !=
nullptr )
15400 image->m_geometry = &geometry;
15401 image->m_color = &color;
15410 Data* m_data =
nullptr;
15416 void DetachFromData()
15418 if ( !m_data->Detach() )
15424 class RectThreadBase :
public Thread
15428 RectThreadBase(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
15433 , m_firstRow( firstRow )
15434 , m_endRow( endRow )
15438 virtual void Run() = 0;
15442 const GenericImage& m_image;
15443 const Rect& m_rect;
15445 int m_firstRow, m_endRow;
15447 template <
class F>
void Execute( F process ) noexcept
15449 int w = m_rect.Width();
15450 int dw = m_image.Width() - w;
15452 if ( m_image.IsLowRangeClippingEnabled() )
15454 sample clipLow = P::ToSample( m_image.RangeClipLow() );
15455 if ( m_image.IsHighRangeClippingEnabled() )
15457 sample clipHigh = P::ToSample( m_image.RangeClipHigh() );
15458 for (
int i = m_ch1; i <= m_ch2; ++i )
15460 const sample* __restrict__ f = m_image.PixelAddress( m_rect.x0, m_rect.y0+m_firstRow, i );
15461 for (
int j = m_firstRow; j < m_endRow; ++j, f += dw )
15464 for (
int k = 0; k < w; ++k, ++f )
15465 if ( clipLow < *f )
15466 if ( *f < clipHigh )
15473 for (
int i = m_ch1; i <= m_ch2; ++i )
15475 const sample* __restrict__ f = m_image.PixelAddress( m_rect.x0, m_rect.y0+m_firstRow, i );
15476 for (
int j = m_firstRow; j < m_endRow; ++j, f += dw )
15479 for (
int k = 0; k < w; ++k, ++f )
15480 if ( clipLow < *f )
15486 else if ( m_image.IsHighRangeClippingEnabled() )
15488 sample clipHigh = P::ToSample( m_image.RangeClipHigh() );
15489 for (
int i = m_ch1; i <= m_ch2; ++i )
15491 const sample* __restrict__ f = m_image.PixelAddress( m_rect.x0, m_rect.y0+m_firstRow, i );
15492 for (
int j = m_firstRow; j < m_endRow; ++j, f += dw )
15495 for (
int k = 0; k < w; ++k, ++f )
15496 if ( *f < clipHigh )
15503 for (
int i = m_ch1; i <= m_ch2; ++i )
15505 const sample* __restrict__ f = m_image.PixelAddress( m_rect.x0, m_rect.y0+m_firstRow, i );
15506 for (
int j = m_firstRow; j < m_endRow; ++j, f += dw )
15509 for (
int k = 0; k < w; ++k, ++f )
15519 class CountThread :
public RectThreadBase
15525 CountThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
15526 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
15535 int w = this->m_rect.Width();
15536 int dw = this->m_image.Width() - w;
15538 if ( this->m_image.IsLowRangeClippingEnabled() )
15540 sample clipLow = P::ToSample( this->m_image.RangeClipLow() );
15541 if ( this->m_image.IsHighRangeClippingEnabled() )
15543 sample clipHigh = P::ToSample( this->m_image.RangeClipHigh() );
15544 for (
int i = this->m_ch1; i <= this->m_ch2; ++i )
15546 const sample* __restrict__ f = this->m_image.PixelAddress( this->m_rect.x0, this->m_rect.y0+this->m_firstRow, i );
15547 for (
int j = this->m_firstRow; j < this->m_endRow; ++j, f += dw )
15550 for (
int k = 0; k < w; ++k, ++f )
15551 if ( clipLow < *f )
15552 if ( *f < clipHigh )
15559 for (
int i = this->m_ch1; i <= this->m_ch2; ++i )
15561 const sample* __restrict__ f = this->m_image.PixelAddress( this->m_rect.x0, this->m_rect.y0+this->m_firstRow, i );
15562 for (
int j = this->m_firstRow; j < this->m_endRow; ++j, f += dw )
15565 for (
int k = 0; k < w; ++k, ++f )
15566 if ( clipLow < *f )
15572 else if ( this->m_image.IsHighRangeClippingEnabled() )
15574 sample clipHigh = P::ToSample( this->m_image.RangeClipHigh() );
15575 for (
int i = this->m_ch1; i <= this->m_ch2; ++i )
15577 const sample* __restrict__ f = this->m_image.PixelAddress( this->m_rect.x0, this->m_rect.y0+this->m_firstRow, i );
15578 for (
int j = this->m_firstRow; j < this->m_endRow; ++j, f += dw )
15581 for (
int k = 0; k < w; ++k, ++f )
15582 if ( *f < clipHigh )
15594 class MinThread :
public RectThreadBase
15601 MinThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
15602 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
15608 min = P::HighestSampleValue();
15610 this->Execute( [=](
const sample* f )
15621 class MaxThread :
public RectThreadBase
15628 MaxThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
15629 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
15635 max = P::LowestSampleValue();
15637 this->Execute( [=](
const sample* f )
15648 class MinMaxThread :
public RectThreadBase
15656 MinMaxThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
15657 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
15663 min = P::HighestSampleValue();
15664 max = P::LowestSampleValue();
15666 this->Execute( [=](
const sample* f )
15679 class ExtremePosThreadBase :
public RectThreadBase
15687 ExtremePosThreadBase(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
15688 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
15695 m_amin = m_amax =
nullptr;
15701 for (
int i = this->m_ch1; i <= this->m_ch2; ++i )
15702 if ( m_amin >= this->m_image[i] && m_amin < (this->m_image[i] + this->m_image.NumberOfPixels()) )
15705 pmin.x = (m_amin - this->m_image[i]) % this->m_image.Width();
15706 pmin.y = (m_amin - this->m_image[i]) / this->m_image.Width();
15710 for (
int i = this->m_ch1; i <= this->m_ch2; ++i )
15711 if ( m_amax >= this->m_image[i] && m_amax < (this->m_image[i] + this->m_image.NumberOfPixels()) )
15714 pmax.x = (m_amax - this->m_image[i]) % this->m_image.Width();
15715 pmax.y = (m_amax - this->m_image[i]) / this->m_image.Width();
15723 const sample* m_amin;
15724 const sample* m_amax;
15726 virtual void DoExecute() = 0;
15731 class MinPosThread :
public ExtremePosThreadBase
15737 MinPosThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
15738 : ExtremePosThreadBase( image, rect, ch1, ch2, firstRow, endRow )
15744 void DoExecute()
override
15746 min = P::HighestSampleValue();
15747 this->Execute( [=](
const sample* f )
15750 min = *(this->m_amin = f);
15758 class MaxPosThread :
public ExtremePosThreadBase
15764 MaxPosThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
15765 : ExtremePosThreadBase( image, rect, ch1, ch2, firstRow, endRow )
15771 void DoExecute()
override
15773 max = P::LowestSampleValue();
15774 this->Execute( [=](
const sample* f )
15777 max = *(this->m_amax = f);
15785 class MinMaxPosThread :
public ExtremePosThreadBase
15791 MinMaxPosThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
15792 : ExtremePosThreadBase( image, rect, ch1, ch2, firstRow, endRow )
15798 void DoExecute()
override
15800 min = P::HighestSampleValue();
15801 max = P::LowestSampleValue();
15802 this->Execute( [=](
const sample* f )
15805 min = *(this->m_amin = f);
15807 max = *(this->m_amax = f);
15815 class SumThread :
public RectThreadBase
15822 SumThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
15823 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
15838 void SumStep(
double x ) noexcept
15847 virtual void DoExecute()
15849 this->Execute( [=](
const sample* f )
15851 double v; P::FromSample( v, *f );
15859 class SumSqrThread :
public SumThread
15863 SumSqrThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
15864 : SumThread( image, rect, ch1, ch2, firstRow, endRow )
15870 void DoExecute()
override
15872 this->Execute( [=](
const sample* f )
15874 double v; P::FromSample( v, *f );
15875 this->SumStep( v*v );
15882 class SumAbsThread :
public SumThread
15886 SumAbsThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
15887 : SumThread( image, rect, ch1, ch2, firstRow, endRow )
15893 void DoExecute()
override
15895 this->Execute( [=](
const sample* f )
15897 double v; P::FromSample( v, *f );
15905 class NormThread :
public RectThreadBase
15912 NormThread(
const GenericImage& image,
int degree,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
15913 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
15923 this->Execute( [=](
const sample* f )
15925 double v; P::FromSample( v, *f );
15926 for (
int i = 0;; )
15929 if ( ++i == R.Length() )
15941 void NormStep(
int i,
double x ) noexcept
15943 double y = x - e[i];
15944 double t = R[i] + y;
15945 e[i] = (t - R[i]) - y;
15952 class HistogramThread :
public RectThreadBase
15958 HistogramThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow,
15959 const double& low,
const double& high )
15960 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
15961 , H( __PCL_MEDIAN_HISTOGRAM_LENGTH )
15970 m_range = m_high - m_low;
15973 #ifdef __PCL_MACOSX
15974 if ( 1 + m_range != 1 )
15976 this->Execute( [=](
const sample* f )
15979 if ( *f <= m_high )
15980 ++H[
TruncInt( (__PCL_MEDIAN_HISTOGRAM_LENGTH - 1) * (
double( *f ) - m_low)/m_range )];
15986 const double& m_low;
15987 const double& m_high;
15993 class ExtremeAbsDevThread :
public RectThreadBase
15997 double minAbsDev, maxAbsDev;
16000 ExtremeAbsDevThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow,
double center )
16001 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
16002 , m_center( center )
16008 minAbsDev = std::numeric_limits<double>::max();
16011 this->Execute( [=](
const sample* f )
16013 double d; P::FromSample( d, *f );
16015 if ( d < minAbsDev )
16017 if ( d > maxAbsDev )
16030 class TwoSidedExtremeAbsDevThread :
public RectThreadBase
16034 double minAbsDevLow, minAbsDevHigh;
16035 double maxAbsDevLow, maxAbsDevHigh;
16038 TwoSidedExtremeAbsDevThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow,
double center )
16039 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
16040 , m_center( center )
16046 minAbsDevLow = minAbsDevHigh = std::numeric_limits<double>::max();
16047 maxAbsDevLow = maxAbsDevHigh = 0;
16049 this->Execute( [=](
const sample* f )
16051 double x; P::FromSample( x, *f );
16052 if ( x <= m_center )
16054 double d = m_center - x;
16055 if ( d < minAbsDevLow )
16057 if ( d > maxAbsDevLow )
16063 double d = x - m_center;
16064 if ( d < minAbsDevHigh )
16066 if ( d > maxAbsDevHigh )
16080 class AbsDevHistogramThread :
public RectThreadBase
16086 AbsDevHistogramThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow,
16087 double center,
const double& low,
const double& high )
16088 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
16089 , H( __PCL_MEDIAN_HISTOGRAM_LENGTH )
16090 , m_center( center )
16099 m_range = m_high - m_low;
16102 #ifdef __PCL_MACOSX
16103 if ( 1 + m_range != 1 )
16105 this->Execute( [=](
const sample* f )
16107 double d; P::FromSample( d, *f );
16111 ++H[
TruncInt( (__PCL_MEDIAN_HISTOGRAM_LENGTH - 1) * (d - m_low)/m_range )];
16118 const double& m_low;
16119 const double& m_high;
16125 class TwoSidedAbsDevHistogramThread :
public RectThreadBase
16131 TwoSidedAbsDevHistogramThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow,
16132 double center,
const int& side,
const double& low,
const double& high )
16133 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
16134 , H( __PCL_MEDIAN_HISTOGRAM_LENGTH )
16135 , m_center( center )
16145 m_range = m_high - m_low;
16148 #ifdef __PCL_MACOSX
16149 if ( 1 + m_range != 1 )
16151 this->Execute( [=](
const sample* f )
16153 double x; P::FromSample( x, *f );
16154 if ( m_side > 0 == x > m_center )
16156 double d = m_side ? x - m_center : m_center - x;
16159 ++H[
TruncInt( (__PCL_MEDIAN_HISTOGRAM_LENGTH - 1) * (d - m_low)/m_range )];
16168 const double& m_low;
16169 const double& m_high;
16175 class VarThread :
public RectThreadBase
16181 VarThread(
const GenericImage& image,
double mean,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
16182 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
16190 this->Execute( [=](
const sample* f )
16192 double d; P::FromSample( d, *f );
16206 class SumAbsDevThread :
public SumThread
16210 SumAbsDevThread(
const GenericImage& image,
double center,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
16211 : SumThread( image, rect, ch1, ch2, firstRow, endRow )
16212 , m_center( center )
16220 void DoExecute()
override
16222 this->Execute( [=](
const sample* f )
16224 double v; P::FromSample( v, *f );
16225 this->SumStep(
pcl::Abs( v - m_center ) );
16232 class TwoSidedSumAbsDevThread :
public RectThreadBase
16239 TwoSidedSumAbsDevThread(
const GenericImage& image,
double center,
16240 const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
16241 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
16242 , m_center( center )
16250 this->Execute( [=](
const sample* f )
16252 double v; P::FromSample( v, *f );
16253 if ( v <= m_center )
16255 s0 += m_center - v;
16260 s1 += v - m_center;
16273 class BWMVThread :
public RectThreadBase
16280 BWMVThread(
const GenericImage& image,
double center,
double kd,
16281 const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
16282 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
16283 , m_center( center )
16292 this->Execute( [=](
const sample* f )
16295 double xc; P::FromSample( xc, *f ); xc -= m_center;
16296 double y = xc/m_kd;
16300 double y21 = 1 - y2;
16301 num += xc*xc * y21*y21*y21*y21;
16302 den += y21 * (1 - 5*y2);
16316 class TwoSidedBWMVThread :
public RectThreadBase
16324 TwoSidedBWMVThread(
const GenericImage& image,
double center,
double kd0,
double kd1,
16325 const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
16326 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
16327 , m_center( center )
16335 num0 = den0 = num1 = den1 = 0;
16336 n0 = n1 = nr0 = nr1 = 0;
16337 this->Execute( [=](
const sample* f )
16339 double xc; P::FromSample( xc, *f ); xc -= m_center;
16340 bool low = xc <= 0;
16346 double y = xc/(low ? m_kd0 : m_kd1);
16350 double y21 = 1 - y2;
16351 double num = xc*xc * y21*y21*y21*y21;
16352 double den = y21 * (1 - 5*y2);
16378 class SmpThread :
public RectThreadBase
16382 Array<sample> samples;
16385 SmpThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
16386 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
16389 *
size_type( this->m_endRow - this->m_firstRow )
16390 * (1 + this->m_ch2 - this->m_ch1);
16391 samples = Array<sample>( N );
16397 this->Execute( [=](
const sample* f )
16406 class DSmpThread :
public RectThreadBase
16410 Array<double> values;
16413 DSmpThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
16414 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
16417 *
size_type( this->m_endRow - this->m_firstRow )
16418 * (1 + this->m_ch2 - this->m_ch1);
16419 values = Array<double>( N );
16430 virtual void DoExecute()
16432 this->Execute( [=](
const sample* f )
16434 P::FromSample( values[n++], *f );
16441 class AbsDevSmpThread :
public DSmpThread
16445 AbsDevSmpThread(
const GenericImage& image,
double center,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
16446 : DSmpThread( image, rect, ch1, ch2, firstRow, endRow )
16447 , m_center( center )
16455 void DoExecute()
override
16457 this->Execute( [=](
const sample* f )
16459 double d; P::FromSample( d, *f );
16460 this->values[this->n++] =
pcl::Abs( d - m_center );
16467 class TwoSidedAbsDevSmpThread :
public DSmpThread
16473 TwoSidedAbsDevSmpThread(
const GenericImage& image,
double center,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
16474 : DSmpThread( image, rect, ch1, ch2, firstRow, endRow )
16475 , m_center( center )
16483 void DoExecute()
override
16485 p = this->values.Begin();
16486 q = this->values.End();
16487 this->Execute( [=](
const sample* f )
16489 double x; P::FromSample( x, *f );
16490 if ( x <= m_center )
16491 *p++ = m_center - x;
16493 *--q = x - m_center;
16501 class ColorSpaceConversionThread :
public Thread
16505 ColorSpaceConversionThread( GenericImage& image, ThreadData& data,
16509 , m_toColorSpace( toColorSpace )
16519 const RGBColorSystem& rgbws = m_image.RGBWorkingSpace();
16521 typename P::sample* f0 = m_image[0] + m_begin;
16522 typename P::sample* f1 = m_image[1] + m_begin;
16523 typename P::sample* f2 = m_image[2] + m_begin;
16524 typename P::sample* fN = m_image[0] + m_end;
16526 for ( ; f0 < fN; ++f0, ++f1, ++f2 )
16528 RGBColorSystem::sample r0, r1, r2;
16529 P::FromSample( r0, *f0 );
16530 P::FromSample( r1, *f1 );
16531 P::FromSample( r2, *f2 );
16533 switch ( m_image.ColorSpace() )
16535 case ColorSpace::RGB :
16536 switch ( m_toColorSpace )
16538 case ColorSpace::Gray :
16539 rgbws.RGBToGray( r0, r0, r1, r2 );
16541 case ColorSpace::HSV :
16542 rgbws.RGBToHSV( r0, r1, r2, r0, r1, r2 );
16544 case ColorSpace::HSI :
16545 rgbws.RGBToHSI( r0, r1, r2, r0, r1, r2 );
16547 case ColorSpace::CIEXYZ :
16548 rgbws.RGBToCIEXYZ( r0, r1, r2, r0, r1, r2 );
16550 case ColorSpace::CIELab :
16551 rgbws.RGBToCIELab( r0, r1, r2, r0, r1, r2 );
16553 case ColorSpace::CIELch :
16554 rgbws.RGBToCIELch( r0, r1, r2, r0, r1, r2 );
16560 case ColorSpace::HSV :
16561 rgbws.HSVToRGB( r0, r1, r2, r0, r1, r2 );
16562 switch ( m_toColorSpace )
16564 case ColorSpace::Gray :
16565 rgbws.RGBToGray( r0, r0, r1, r2 );
16567 case ColorSpace::RGB :
16569 case ColorSpace::HSI :
16570 rgbws.RGBToHSI( r0, r1, r2, r0, r1, r2 );
16572 case ColorSpace::CIEXYZ :
16573 rgbws.RGBToCIEXYZ( r0, r1, r2, r0, r1, r2 );
16575 case ColorSpace::CIELab :
16576 rgbws.RGBToCIELab( r0, r1, r2, r0, r1, r2 );
16578 case ColorSpace::CIELch :
16579 rgbws.RGBToCIELch( r0, r1, r2, r0, r1, r2 );
16585 case ColorSpace::HSI :
16586 rgbws.HSIToRGB( r0, r1, r2, r0, r1, r2 );
16587 switch ( m_toColorSpace )
16589 case ColorSpace::Gray :
16590 rgbws.RGBToGray( r0, r0, r1, r2 );
16592 case ColorSpace::RGB :
16594 case ColorSpace::HSV :
16595 rgbws.RGBToHSV( r0, r1, r2, r0, r1, r2 );
16597 case ColorSpace::CIEXYZ :
16598 rgbws.RGBToCIEXYZ( r0, r1, r2, r0, r1, r2 );
16600 case ColorSpace::CIELab :
16601 rgbws.RGBToCIELab( r0, r1, r2, r0, r1, r2 );
16603 case ColorSpace::CIELch :
16604 rgbws.RGBToCIELch( r0, r1, r2, r0, r1, r2 );
16610 case ColorSpace::CIEXYZ :
16611 switch ( m_toColorSpace )
16613 case ColorSpace::Gray :
16614 rgbws.CIEXYZToRGB( r0, r1, r2, r0, r1, r2 );
16615 rgbws.RGBToGray( r0, r0, r1, r2 );
16617 case ColorSpace::RGB :
16618 rgbws.CIEXYZToRGB( r0, r1, r2, r0, r1, r2 );
16620 case ColorSpace::HSV :
16621 rgbws.CIEXYZToRGB( r0, r1, r2, r0, r1, r2 );
16622 rgbws.RGBToHSV( r0, r1, r2, r0, r1, r2 );
16624 case ColorSpace::HSI :
16625 rgbws.CIEXYZToRGB( r0, r1, r2, r0, r1, r2 );
16626 rgbws.RGBToHSI( r0, r1, r2, r0, r1, r2 );
16628 case ColorSpace::CIELab :
16629 rgbws.CIEXYZToCIELab( r0, r1, r2, r0, r1, r2 );
16631 case ColorSpace::CIELch :
16632 rgbws.CIEXYZToCIELab( r0, r1, r2, r0, r1, r2 );
16633 rgbws.CIELabToCIELch( r0, r1, r2, r0, r1, r2 );
16639 case ColorSpace::CIELab :
16640 switch ( m_toColorSpace )
16642 case ColorSpace::Gray :
16643 rgbws.CIELabToRGB( r0, r1, r2, r0, r1, r2 );
16644 rgbws.RGBToGray( r0, r0, r1, r2 );
16646 case ColorSpace::RGB :
16647 rgbws.CIELabToRGB( r0, r1, r2, r0, r1, r2 );
16649 case ColorSpace::HSV :
16650 rgbws.CIELabToRGB( r0, r1, r2, r0, r1, r2 );
16651 rgbws.RGBToHSV( r0, r1, r2, r0, r1, r2 );
16653 case ColorSpace::HSI :
16654 rgbws.CIELabToRGB( r0, r1, r2, r0, r1, r2 );
16655 rgbws.RGBToHSI( r0, r1, r2, r0, r1, r2 );
16657 case ColorSpace::CIEXYZ :
16658 rgbws.CIELabToCIEXYZ( r0, r1, r2, r0, r1, r2 );
16660 case ColorSpace::CIELch :
16661 rgbws.CIELabToCIELch( r0, r1, r2, r0, r1, r2 );
16667 case ColorSpace::CIELch :
16668 switch ( m_toColorSpace )
16670 case ColorSpace::Gray :
16671 rgbws.CIELchToRGB( r0, r1, r2, r0, r1, r2 );
16672 rgbws.RGBToGray( r0, r0, r1, r2 );
16674 case ColorSpace::RGB :
16675 rgbws.CIELchToRGB( r0, r1, r2, r0, r1, r2 );
16677 case ColorSpace::HSV :
16678 rgbws.CIELchToRGB( r0, r1, r2, r0, r1, r2 );
16679 rgbws.RGBToHSV( r0, r1, r2, r0, r1, r2 );
16681 case ColorSpace::HSI :
16682 rgbws.CIELchToRGB( r0, r1, r2, r0, r1, r2 );
16683 rgbws.RGBToHSI( r0, r1, r2, r0, r1, r2 );
16685 case ColorSpace::CIEXYZ :
16686 rgbws.CIELchToCIELab( r0, r1, r2, r0, r1, r2 );
16687 rgbws.CIELabToCIEXYZ( r0, r1, r2, r0, r1, r2 );
16689 case ColorSpace::CIELab :
16690 rgbws.CIELchToCIELab( r0, r1, r2, r0, r1, r2 );
16700 *f0 = P::ToSample( r0 );
16702 if ( m_toColorSpace != ColorSpace::Gray )
16704 *f1 = P::ToSample( r1 );
16705 *f2 = P::ToSample( r2 );
16714 GenericImage& m_image;
16715 ThreadData& m_data;
16716 color_space m_toColorSpace;
16722 template <
class P1>
16723 class GetLuminanceThread :
public Thread
16727 GetLuminanceThread( GenericImage<P1>& luminance,
const GenericImage& image, ThreadData& data,
16728 const Rect& rect,
int firstRow,
int endRow )
16729 : m_luminance( luminance )
16733 , m_firstRow( firstRow )
16734 , m_endRow( endRow )
16742 const RGBColorSystem& rgbws = m_image.RGBWorkingSpace();
16744 const typename P::sample* f0 = m_image.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 0 );
16745 const typename P::sample* f1 = m_image.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 1 );
16746 const typename P::sample* f2 = m_image.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 2 );
16748 typename P1::sample* fY = m_luminance.ScanLine( m_firstRow );
16750 for (
int y = m_firstRow, dw = m_image.Width()-m_rect.Width();
16752 ++y, f0 += dw, f1 += dw, f2 += dw )
16754 const typename P::sample* fN = f0 + m_rect.Width();
16756 for ( ; f0 < fN; ++f0, ++f1, ++f2, ++fY )
16758 RGBColorSystem::sample r0, r1, r2, rY;
16759 P::FromSample( r0, *f0 );
16760 P::FromSample( r1, *f1 );
16761 P::FromSample( r2, *f2 );
16763 switch ( m_image.ColorSpace() )
16765 case ColorSpace::RGB:
16766 case ColorSpace::HSV:
16767 case ColorSpace::HSI:
16768 switch ( m_image.ColorSpace() )
16770 case ColorSpace::HSV:
16771 rgbws.HSVToRGB( r0, r1, r2, r0, r1, r2 );
16773 case ColorSpace::HSI:
16774 rgbws.HSIToRGB( r0, r1, r2, r0, r1, r2 );
16779 rY = rgbws.CIEY( r0, r1, r2 );
16782 case ColorSpace::CIELch:
16783 rgbws.CIELchToCIELab( r0, r1, r2, r0, r1, r2 );
16785 case ColorSpace::CIELab:
16786 rgbws.CIELabToCIEXYZ( r0, rY, r2, r0, r1, r2 );
16794 *fY = P1::ToSample( rY );
16803 GenericImage<P1>& m_luminance;
16804 const GenericImage& m_image;
16805 ThreadData& m_data;
16806 const Rect& m_rect;
16807 int m_firstRow, m_endRow;
16812 template <
class P1>
16813 class GetLightnessThread :
public Thread
16817 GetLightnessThread( GenericImage<P1>& lightness,
const GenericImage& image, ThreadData& data,
16818 const Rect& rect,
int firstRow,
int endRow )
16819 : m_lightness( lightness )
16823 , m_firstRow( firstRow )
16824 , m_endRow( endRow )
16832 const RGBColorSystem& rgbws = m_image.RGBWorkingSpace();
16834 const typename P::sample* f0 = m_image.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 0 );
16835 const typename P::sample* f1 = m_image.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 1 );
16836 const typename P::sample* f2 = m_image.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 2 );
16838 typename P1::sample* fL = m_lightness.ScanLine( m_firstRow );
16840 for (
int y = m_firstRow, dw = m_image.Width()-m_rect.Width();
16842 ++y, f0 += dw, f1 += dw, f2 += dw )
16844 const typename P::sample* fN = f0 + m_rect.Width();
16846 for ( ; f0 < fN; ++f0, ++f1, ++f2, ++fL )
16848 RGBColorSystem::sample r0, r1, r2, rL;
16849 P::FromSample( r0, *f0 );
16850 P::FromSample( r1, *f1 );
16851 P::FromSample( r2, *f2 );
16853 switch ( m_image.ColorSpace() )
16855 case ColorSpace::RGB:
16856 case ColorSpace::HSV:
16857 case ColorSpace::HSI:
16858 case ColorSpace::CIEXYZ:
16859 switch ( m_image.ColorSpace() )
16861 case ColorSpace::HSV:
16862 rgbws.HSVToRGB( r0, r1, r2, r0, r1, r2 );
16864 case ColorSpace::HSI:
16865 rgbws.HSIToRGB( r0, r1, r2, r0, r1, r2 );
16867 case ColorSpace::CIEXYZ:
16868 rgbws.CIEXYZToRGB( r0, r1, r2, r0, r1, r2 );
16873 rL = rgbws.CIEL( r0, r1, r2 );
16881 *fL = P1::ToSample( rL );
16890 GenericImage<P1>& m_lightness;
16891 const GenericImage& m_image;
16892 ThreadData& m_data;
16893 const Rect& m_rect;
16894 int m_firstRow, m_endRow;
16899 template <
class P1>
16900 class GetIntensityThread :
public Thread
16904 GetIntensityThread( GenericImage<P1>& luminance,
const GenericImage& image, ThreadData& data,
16905 const Rect& rect,
int firstRow,
int endRow )
16906 : m_intensity( luminance )
16910 , m_firstRow( firstRow )
16911 , m_endRow( endRow )
16919 const RGBColorSystem& rgbws = m_image.RGBWorkingSpace();
16921 const typename P::sample* f0 = m_image.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 0 );
16922 const typename P::sample* f1 = m_image.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 1 );
16923 const typename P::sample* f2 = m_image.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 2 );
16925 typename P1::sample* fI = m_intensity.ScanLine( m_firstRow );
16927 for (
int y = m_firstRow, dw = m_image.Width()-m_rect.Width();
16929 ++y, f0 += dw, f1 += dw, f2 += dw )
16931 const typename P::sample* fN = f0 + m_rect.Width();
16933 for ( ; f0 < fN; ++f0, ++f1, ++f2, ++fI )
16935 RGBColorSystem::sample r0, r1, r2;
16936 P::FromSample( r0, *f0 );
16937 P::FromSample( r1, *f1 );
16938 P::FromSample( r2, *f2 );
16940 switch ( m_image.ColorSpace() )
16942 case ColorSpace::RGB:
16944 case ColorSpace::HSV:
16945 rgbws.HSVToRGB( r0, r1, r2, r0, r1, r2 );
16947 case ColorSpace::CIEXYZ:
16948 rgbws.CIEXYZToRGB( r0, r1, r2, r0, r1, r2 );
16950 case ColorSpace::CIELab:
16951 rgbws.CIELabToRGB( r0, r1, r2, r0, r1, r2 );
16953 case ColorSpace::CIELch:
16954 rgbws.CIELchToRGB( r0, r1, r2, r0, r1, r2 );
16960 *fI = P1::ToSample( rgbws.Intensity( r0, r1, r2 ) );
16969 GenericImage<P1>& m_intensity;
16970 const GenericImage& m_image;
16971 ThreadData& m_data;
16972 const Rect& m_rect;
16973 int m_firstRow, m_endRow;
16978 template <
class P1>
16979 class SetLuminanceThread :
public Thread
16983 SetLuminanceThread( GenericImage& image,
const GenericImage<P1>& luminance, ThreadData& data,
16984 const Point& target,
const Rect& rect,
int firstRow,
int endRow )
16986 , m_luminance( luminance )
16988 , m_target( target )
16990 , m_firstRow( firstRow )
16991 , m_endRow( endRow )
16999 const RGBColorSystem& sourceRGBWS = m_luminance.RGBWorkingSpace();
17000 const RGBColorSystem& targetRGBWS = m_image.RGBWorkingSpace();
17002 typename P::sample* f0 = m_image.PixelAddress( m_target.x, m_target.y + m_firstRow, 0 );
17003 typename P::sample* f1 = m_image.PixelAddress( m_target.x, m_target.y + m_firstRow, 1 );
17004 typename P::sample* f2 = m_image.PixelAddress( m_target.x, m_target.y + m_firstRow, 2 );
17006 if ( m_luminance.ColorSpace() == ColorSpace::Gray || m_luminance.ColorSpace() == ColorSpace::CIEXYZ )
17008 int cY = (m_luminance.ColorSpace() == ColorSpace::Gray) ? 0 : 1;
17009 const typename P1::sample* fY = m_luminance.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, cY );
17011 for (
int y = m_firstRow, dw = m_image.Width()-m_rect.Width(), dwY = m_luminance.Width()-m_rect.Width();
17013 ++y, f0 += dw, f1 += dw, f2 += dw, fY += dwY )
17015 const typename P::sample* fN = f0 + m_rect.Width();
17017 for ( ; f0 < fN; ++f0, ++f1, ++f2, ++fY )
17019 RGBColorSystem::sample r0, r1, r2, rY;
17020 P::FromSample( r0, *f0 );
17021 P::FromSample( r1, *f1 );
17022 P::FromSample( r2, *f2 );
17023 P1::FromSample( rY, *fY );
17025 switch ( m_image.ColorSpace() )
17027 case ColorSpace::RGB:
17028 case ColorSpace::HSV:
17029 case ColorSpace::HSI:
17030 switch ( m_image.ColorSpace() )
17032 case ColorSpace::HSV:
17033 targetRGBWS.HSVToRGB( r0, r1, r2, r0, r1, r2 );
17035 case ColorSpace::HSI:
17036 targetRGBWS.HSIToRGB( r0, r1, r2, r0, r1, r2 );
17041 targetRGBWS.RGBToCIEab( r1, r2, r0, r1, r2 );
17042 targetRGBWS.CIELabToRGB( r0, r1, r2, sourceRGBWS.CIEYToCIEL( rY ), r1, r2 );
17043 switch ( m_image.ColorSpace() )
17045 case ColorSpace::HSV:
17046 targetRGBWS.RGBToHSV( r0, r1, r2, r0, r1, r2 );
17048 case ColorSpace::HSI:
17049 targetRGBWS.RGBToHSI( r0, r1, r2, r0, r1, r2 );
17056 case ColorSpace::CIEXYZ:
17057 targetRGBWS.CIEXYZToCIELab( r0, r1, r2, r0, r1, r2 );
17058 targetRGBWS.CIELabToCIEXYZ( r0, r1, r2, sourceRGBWS.CIEYToCIEL( rY ), r1, r2 );
17061 case ColorSpace::CIELab:
17062 case ColorSpace::CIELch:
17063 r0 = sourceRGBWS.CIEYToCIEL( rY );
17070 *f0 = P::ToSample( r0 );
17071 *f1 = P::ToSample( r1 );
17072 *f2 = P::ToSample( r2 );
17080 const typename P1::sample* g0 = m_luminance.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 0 );
17081 const typename P1::sample* g1 = m_luminance.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 1 );
17082 const typename P1::sample* g2 = m_luminance.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 2 );
17084 for (
int y = m_firstRow, dw = m_image.Width()-m_rect.Width(), dwY = m_luminance.Width()-m_rect.Width();
17086 ++y, f0 += dw, f1 += dw, f2 += dw, g0 += dwY, g1 += dwY, g2 += dwY )
17088 const typename P::sample* fN = f0 + m_rect.Width();
17090 for ( ; f0 < fN; ++f0, ++f1, ++f2, ++g0, ++g1, ++g2 )
17092 typename RGBColorSystem::sample r0, r1, r2, s0, s1, s2;
17093 P::FromSample( r0, *f0 );
17094 P::FromSample( r1, *f1 );
17095 P::FromSample( r2, *f2 );
17096 P1::FromSample( s0, *g0 );
17097 P1::FromSample( s1, *g1 );
17098 P1::FromSample( s2, *g2 );
17100 switch ( m_image.ColorSpace() )
17102 case ColorSpace::RGB:
17103 case ColorSpace::HSV:
17104 case ColorSpace::HSI:
17105 case ColorSpace::CIEXYZ:
17106 case ColorSpace::CIELab:
17107 case ColorSpace::CIELch:
17108 switch ( m_image.ColorSpace() )
17110 case ColorSpace::RGB:
17111 case ColorSpace::HSV:
17112 case ColorSpace::HSI:
17113 switch ( m_image.ColorSpace() )
17115 case ColorSpace::HSV:
17116 targetRGBWS.HSVToRGB( r0, r1, r2, r0, r1, r2 );
17118 case ColorSpace::HSI:
17119 targetRGBWS.HSIToRGB( r0, r1, r2, r0, r1, r2 );
17124 targetRGBWS.RGBToCIEab( r1, r2, r0, r1, r2 );
17126 case ColorSpace::CIEXYZ:
17127 targetRGBWS.CIEXYZToCIELab( r0, r1, r2, r0, r1, r2 );
17129 case ColorSpace::CIELab:
17130 case ColorSpace::CIELch:
17136 switch ( m_luminance.ColorSpace() )
17138 case ColorSpace::RGB:
17139 case ColorSpace::HSV:
17140 case ColorSpace::HSI:
17141 switch ( m_luminance.ColorSpace() )
17143 case ColorSpace::HSV:
17144 sourceRGBWS.HSVToRGB( s0, s1, s2, s0, s1, s2 );
17146 case ColorSpace::HSI:
17147 sourceRGBWS.HSIToRGB( s0, s1, s2, s0, s1, s2 );
17152 r0 = sourceRGBWS.CIEL( s0, s1, s2 );
17154 case ColorSpace::CIEXYZ:
17155 sourceRGBWS.CIEXYZToCIELab( r0, s1, s2, s0, s1, s2 );
17157 case ColorSpace::CIELab:
17158 case ColorSpace::CIELch:
17165 switch ( m_image.ColorSpace() )
17167 case ColorSpace::RGB:
17168 case ColorSpace::HSV:
17169 case ColorSpace::HSI:
17170 targetRGBWS.CIELabToRGB( r0, r1, r2, r0, r1, r2 );
17171 switch ( m_image.ColorSpace() )
17173 case ColorSpace::HSV:
17174 targetRGBWS.RGBToHSV( r0, r1, r2, r0, r1, r2 );
17176 case ColorSpace::HSI:
17177 targetRGBWS.RGBToHSI( r0, r1, r2, r0, r1, r2 );
17183 case ColorSpace::CIEXYZ:
17184 targetRGBWS.CIELabToCIEXYZ( r0, r1, r2, r0, r1, r2 );
17186 case ColorSpace::CIELab:
17187 case ColorSpace::CIELch:
17198 *f0 = P::ToSample( r0 );
17199 *f1 = P::ToSample( r1 );
17200 *f2 = P::ToSample( r2 );
17210 GenericImage& m_image;
17211 const GenericImage<P1>& m_luminance;
17212 ThreadData& m_data;
17213 const Point& m_target;
17214 const Rect& m_rect;
17215 int m_firstRow, m_endRow;
17220 template <
class P1>
17221 class SetLightnessThread :
public Thread
17225 SetLightnessThread( GenericImage& image,
const GenericImage<P1>& lightness, ThreadData& data,
17226 const Point& target,
const Rect& rect,
int firstRow,
int endRow )
17228 , m_lightness( lightness )
17230 , m_target( target )
17232 , m_firstRow( firstRow )
17233 , m_endRow( endRow )
17241 const RGBColorSystem& sourceRGBWS = m_lightness.RGBWorkingSpace();
17242 const RGBColorSystem& targetRGBWS = m_image.RGBWorkingSpace();
17244 typename P::sample* f0 = m_image.PixelAddress( m_target.x, m_target.y + m_firstRow, 0 );
17245 typename P::sample* f1 = m_image.PixelAddress( m_target.x, m_target.y + m_firstRow, 1 );
17246 typename P::sample* f2 = m_image.PixelAddress( m_target.x, m_target.y + m_firstRow, 2 );
17248 if ( m_lightness.ColorSpace() == ColorSpace::Gray ||
17249 m_lightness.ColorSpace() == ColorSpace::CIELab || m_lightness.ColorSpace() == ColorSpace::CIELch )
17251 const typename P1::sample* fL = m_lightness.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 0 );
17253 for (
int y = m_firstRow, dw = m_image.Width()-m_rect.Width(), dwL = m_lightness.Width()-m_rect.Width();
17255 ++y, f0 += dw, f1 += dw, f2 += dw, fL += dwL )
17257 const typename P::sample* fN = f0 + m_rect.Width();
17259 for ( ; f0 < fN; ++f0, ++f1, ++f2, ++fL )
17261 RGBColorSystem::sample r0, r1, r2, rL;
17262 P::FromSample( r0, *f0 );
17263 P::FromSample( r1, *f1 );
17264 P::FromSample( r2, *f2 );
17265 P1::FromSample( rL, *fL );
17267 switch ( m_image.ColorSpace() )
17269 case ColorSpace::RGB:
17270 case ColorSpace::HSV:
17271 case ColorSpace::HSI:
17272 switch ( m_image.ColorSpace() )
17274 case ColorSpace::HSV:
17275 targetRGBWS.HSVToRGB( r0, r1, r2, r0, r1, r2 );
17277 case ColorSpace::HSI:
17278 targetRGBWS.HSIToRGB( r0, r1, r2, r0, r1, r2 );
17283 targetRGBWS.RGBToCIEab( r1, r2, r0, r1, r2 );
17284 targetRGBWS.CIELabToRGB( r0, r1, r2, rL, r1, r2 );
17285 switch ( m_image.ColorSpace() )
17287 case ColorSpace::HSV:
17288 targetRGBWS.RGBToHSV( r0, r1, r2, r0, r1, r2 );
17290 case ColorSpace::HSI:
17291 targetRGBWS.RGBToHSI( r0, r1, r2, r0, r1, r2 );
17298 case ColorSpace::CIEXYZ:
17299 r1 = targetRGBWS.CIELToCIEY( rL );
17302 case ColorSpace::CIELab:
17303 case ColorSpace::CIELch:
17311 *f0 = P::ToSample( r0 );
17312 *f1 = P::ToSample( r1 );
17313 *f2 = P::ToSample( r2 );
17321 const typename P1::sample* g0 = m_lightness.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 0 );
17322 const typename P1::sample* g1 = m_lightness.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 1 );
17323 const typename P1::sample* g2 = m_lightness.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 2 );
17325 for (
int y = m_firstRow, dw = m_image.Width()-m_rect.Width(), dwL = m_lightness.Width()-m_rect.Width();
17327 ++y, f0 += dw, f1 += dw, f2 += dw, g0 += dwL, g1 += dwL, g2 += dwL )
17329 const typename P::sample* fN = f0 + m_rect.Width();
17331 for ( ; f0 < fN; ++f0, ++f1, ++f2, ++g0, ++g1, ++g2 )
17333 typename RGBColorSystem::sample r0, r1, r2, s0, s1, s2;
17334 P::FromSample( r0, *f0 );
17335 P::FromSample( r1, *f1 );
17336 P::FromSample( r2, *f2 );
17337 P1::FromSample( s0, *g0 );
17338 P1::FromSample( s1, *g1 );
17339 P1::FromSample( s2, *g2 );
17341 switch ( m_image.ColorSpace() )
17343 case ColorSpace::RGB:
17344 case ColorSpace::HSV:
17345 case ColorSpace::HSI:
17346 case ColorSpace::CIEXYZ:
17347 case ColorSpace::CIELab:
17348 case ColorSpace::CIELch:
17349 switch ( m_image.ColorSpace() )
17351 case ColorSpace::RGB:
17352 case ColorSpace::HSV:
17353 case ColorSpace::HSI:
17354 switch ( m_image.ColorSpace() )
17356 case ColorSpace::HSV:
17357 targetRGBWS.HSVToRGB( r0, r1, r2, r0, r1, r2 );
17359 case ColorSpace::HSI:
17360 targetRGBWS.HSIToRGB( r0, r1, r2, r0, r1, r2 );
17365 targetRGBWS.RGBToCIEab( r1, r2, r0, r1, r2 );
17367 case ColorSpace::CIEXYZ:
17368 targetRGBWS.CIEXYZToCIELab( r0, r1, r2, r0, r1, r2 );
17370 case ColorSpace::CIELch:
17371 targetRGBWS.CIELchToCIELab( r0, r1, r2, r0, r1, r2 );
17377 switch ( m_lightness.ColorSpace() )
17379 case ColorSpace::RGB:
17380 case ColorSpace::HSV:
17381 case ColorSpace::HSI:
17382 switch ( m_lightness.ColorSpace() )
17384 case ColorSpace::HSV:
17385 sourceRGBWS.HSVToRGB( s0, s1, s2, s0, s1, s2 );
17387 case ColorSpace::HSI:
17388 sourceRGBWS.HSIToRGB( s0, s1, s2, s0, s1, s2 );
17393 r0 = sourceRGBWS.CIEL( s0, s1, s2 );
17395 case ColorSpace::CIEXYZ:
17396 r0 = sourceRGBWS.CIEYToCIEL( s1 );
17402 switch ( m_image.ColorSpace() )
17404 case ColorSpace::RGB:
17405 case ColorSpace::HSV:
17406 case ColorSpace::HSI:
17407 targetRGBWS.CIELabToRGB( r0, r1, r2, r0, r1, r2 );
17408 switch ( m_image.ColorSpace() )
17410 case ColorSpace::HSV:
17411 targetRGBWS.RGBToHSV( r0, r1, r2, r0, r1, r2 );
17413 case ColorSpace::HSI:
17414 targetRGBWS.RGBToHSI( r0, r1, r2, r0, r1, r2 );
17420 case ColorSpace::CIEXYZ:
17421 targetRGBWS.CIELabToCIEXYZ( r0, r1, r2, r0, r1, r2 );
17423 case ColorSpace::CIELch:
17424 targetRGBWS.CIELabToCIELch( r0, r1, r2, r0, r1, r2 );
17434 *f0 = P::ToSample( r0 );
17435 *f1 = P::ToSample( r1 );
17436 *f2 = P::ToSample( r2 );
17446 GenericImage& m_image;
17447 const GenericImage<P1>& m_lightness;
17448 ThreadData& m_data;
17449 const Point& m_target;
17450 const Rect& m_rect;
17451 int m_firstRow, m_endRow;
17456 #ifdef __PCL_BUILDING_PIXINSIGHT_APPLICATION
17457 friend class pi::SharedImage;
17462 #undef m_channelData
17466 #undef m_numberOfChannels
17467 #undef m_colorSpace
17470 #undef m_lastChannel
17475 #undef m_clippedLow
17476 #undef m_clippedHigh
17489 template <
class P,
typename T>
inline
17493 (void)(result += scalar);
17505 template <
class P,
typename T>
inline
17508 return image + scalar;
17516 template <
class P,
typename T>
inline
17520 (void)(result -= scalar);
17529 template <
class P,
typename T>
inline
17533 (void)(result *= scalar);
17546 template <
class P,
typename T>
inline
17549 return image * scalar;
17557 template <
class P,
typename T>
inline
17561 (void)(result /= scalar);
17570 template <
class P,
typename T>
inline
17574 (void)(result ^= scalar);
17596 template <
class P1,
class P2>
inline
17600 (void)(result += image2);
17616 template <
class P1,
class P2>
inline
17620 (void)(result -= image2);
17636 template <
class P1,
class P2>
inline
17640 (void)(result *= image2);
17657 template <
class P1,
class P2>
inline
17661 (void)(result /= image2);
17678 template <
class P1,
class P2>
inline
17682 (void)(result ^= image2);
17688 #ifndef __PCL_NO_IMAGE_INSTANTIATE
17701 using FImage = GenericImage<FloatPixelTraits>;
17710 using DImage = GenericImage<DoublePixelTraits>;
17740 using UInt8Image = GenericImage<UInt8PixelTraits>;
17750 using UInt16Image = GenericImage<UInt16PixelTraits>;
17760 using UInt32Image = GenericImage<UInt32PixelTraits>;
17790 #ifndef __PCL_NO_IMAGE_VARIANT_AUTO
17792 #ifndef __PCL_ImageVariant_h
Base class of all two-dimensional images in PCL.
int LastSelectedChannel() const noexcept
bool IsCompletelySelected() const noexcept
int FirstSelectedChannel() const noexcept
void ResetSelections() const noexcept
StatusMonitor & Status() const noexcept
bool ParseSelection(Rect &rect, int &firstChannel, int &lastChannel) const noexcept
Client-side interface to a PixInsight Bitmap object.
32-bit floating point complex image.
Abstract base class of data compression algorithm implementations.
subblock_list Compress(const void *data, size_type size, Performance *perf=nullptr) const
Image cropping/expansion algorithm
64-bit floating point complex image.
64-bit floating point real image.
A simple exception with an associated error message.
32-bit floating point complex image.
32-bit floating point real image.
A platform-independent interface to the local file system.
virtual void Write(const void *buffer, fsize_type len)
void WriteUI32(const T &x)
virtual void Read(void *buffer, fsize_type len)
Immutable filter pixel iterator.
const_filter_pixel_iterator(const const_filter_pixel_iterator &)=default
typename image_type::sample sample
const_filter_pixel_iterator & MoveBy(int dx, int dy) noexcept
const_filter_pixel_iterator(const image_type &image, const F &filter)
const_filter_pixel_iterator(const const_pixel_iterator &i, const F &filter)
const filter_type & Filter() const noexcept
typename image_type::pixel_traits pixel_traits
bool IsValid() const noexcept
const image_type & Image() const noexcept
const sample * Position(int channel) const noexcept
filter_type & Filter() noexcept
const_filter_pixel_iterator()=default
Immutable filter pixel sample iterator.
const_filter_sample_iterator()=default
filter_type & Filter() noexcept
const_filter_sample_iterator(const image_type &image, const F &filter, int channel=-1)
const_filter_sample_iterator & MoveBy(int dx, int dy) noexcept
const image_type & Image() const noexcept
bool IsValid() const noexcept
const_filter_sample_iterator(const image_type &image, const F &filter, const sample *i, const sample *j)
typename image_type::sample sample
const sample * Position() const noexcept
const filter_type & Filter() const noexcept
const_filter_sample_iterator(const const_filter_sample_iterator &)=default
typename image_type::pixel_traits pixel_traits
const_filter_sample_iterator(const sample_iterator &i, const F &filter)
const_filter_sample_iterator(const filter_sample_iterator< F > &i)
const_filter_sample_iterator(const const_sample_iterator &i, const F &filter)
Immutable pixel iterator.
const image_type & Image() const noexcept
const_pixel_iterator(const image_type &image)
typename image_type::sample sample
const_pixel_iterator(const const_pixel_iterator &)=default
const_pixel_iterator()=default
bool IsValid() const noexcept
const_pixel_iterator & MoveBy(int dx, int dy) noexcept
typename image_type::pixel_traits pixel_traits
const sample * Position(int channel) const noexcept
Immutable region-of-interest, filter pixel iterator.
const_roi_filter_pixel_iterator(const const_roi_pixel_iterator &i, const F &filter)
const_roi_filter_pixel_iterator(const image_type &image, const F &filter, const Rect &rect=Rect(0))
const_roi_filter_pixel_iterator(const const_roi_filter_pixel_iterator &)=default
const image_type & Image() const noexcept
typename image_type::sample sample
const filter_type & Filter() const noexcept
const sample * Position(int channel) const noexcept
const_roi_filter_pixel_iterator()=default
typename image_type::pixel_traits pixel_traits
filter_type & Filter() noexcept
bool IsValid() const noexcept
const_roi_filter_pixel_iterator & MoveBy(int dx, int dy) noexcept
Immutable region-of-interest, filter pixel sample iterator.
const sample * Position() const noexcept
const_roi_filter_sample_iterator(const image_type &image, const F &filter, const sample *i, const sample *j)
const_roi_filter_sample_iterator()=default
bool IsValid() const noexcept
const_roi_filter_sample_iterator(const const_roi_sample_iterator &i, const F &filter)
const_roi_filter_sample_iterator(const const_roi_filter_sample_iterator &)=default
const filter_type & Filter() const noexcept
typename image_type::pixel_traits pixel_traits
const_roi_filter_sample_iterator(const image_type &image, const F &filter, const Rect &rect=Rect(0), int channel=-1)
const image_type & Image() const noexcept
typename image_type::sample sample
filter_type & Filter() noexcept
const_roi_filter_sample_iterator & MoveBy(int dx, int dy) noexcept
Immutable region-of-interest pixel iterator.
const_roi_pixel_iterator()=default
typename image_type::sample sample
const_roi_pixel_iterator & MoveBy(int dx, int dy) noexcept
const sample * Position(int channel) const noexcept
const image_type & Image() const noexcept
const_roi_pixel_iterator(const const_roi_pixel_iterator &)=default
const_roi_pixel_iterator(const image_type &image, const Rect &rect=Rect(0))
bool IsValid() const noexcept
typename image_type::pixel_traits pixel_traits
Immutable region-of-interest pixel sample iterator.
const_roi_sample_iterator(const const_roi_sample_iterator &)=default
const_roi_sample_iterator(const image_type &image, const Rect &rect=Rect(0), int channel=-1)
const sample * Position() const noexcept
bool IsValid() const noexcept
const_roi_sample_iterator(const image_type &image, const sample *i, const sample *j)
const_roi_sample_iterator()=default
const_roi_sample_iterator & MoveBy(int dx, int dy) noexcept
const image_type & Image() const noexcept
const_roi_sample_iterator(const roi_sample_iterator &i)
typename image_type::sample sample
typename image_type::pixel_traits pixel_traits
Immutable pixel sample iterator.
const_sample_iterator(const image_type &image, int channel=-1)
const_sample_iterator()=default
const_sample_iterator(const sample_iterator &i)
typename image_type::sample sample
typename image_type::pixel_traits pixel_traits
const_sample_iterator & MoveBy(int dx, int dy) noexcept
bool IsValid() const noexcept
const image_type & Image() const noexcept
const_sample_iterator(const image_type &image, const sample *i, const sample *j)
const_sample_iterator(const const_sample_iterator &)=default
const sample * Position() const noexcept
Mutable filter pixel iterator.
filter_pixel_iterator()=default
typename image_type::pixel_traits pixel_traits
bool IsValid() const noexcept
filter_pixel_iterator & MoveBy(int dx, int dy) noexcept
sample * Position(int channel) const noexcept
filter_pixel_iterator(const pixel_iterator &i, const F &filter)
filter_pixel_iterator(const filter_pixel_iterator &)=default
typename image_type::sample sample
const filter_type & Filter() const noexcept
filter_type & Filter() noexcept
filter_pixel_iterator(image_type &image, const F &filter)
image_type & Image() const noexcept
Mutable filter pixel sample iterator.
sample * Position() const noexcept
filter_sample_iterator(const sample_iterator &i, const F &filter)
filter_sample_iterator()=default
filter_sample_iterator(const filter_sample_iterator &i)=default
filter_sample_iterator(image_type &image, const F &filter, int channel=-1)
filter_type & Filter() noexcept
image_type & Image() const noexcept
filter_sample_iterator & MoveBy(int dx, int dy) noexcept
const filter_type & Filter() const noexcept
bool IsValid() const noexcept
filter_sample_iterator(image_type &image, const F &filter, sample *i, sample *j)
typename image_type::sample sample
typename image_type::pixel_traits pixel_traits
typename image_type::pixel_traits pixel_traits
pixel_iterator & MoveBy(int dx, int dy) noexcept
pixel_iterator(image_type &image)
image_type & Image() const noexcept
sample * Position(int channel) const noexcept
pixel_iterator(const pixel_iterator &)=default
typename image_type::sample sample
bool IsValid() const noexcept
Mutable region-of-interest, filter pixel iterator.
roi_filter_pixel_iterator(const roi_filter_pixel_iterator &)=default
sample * Position(int channel) const noexcept
roi_filter_pixel_iterator(const roi_pixel_iterator &i, const F &filter)
roi_filter_pixel_iterator & MoveBy(int dx, int dy) noexcept
filter_type & Filter() noexcept
typename image_type::sample sample
bool IsValid() const noexcept
image_type & Image() const noexcept
roi_filter_pixel_iterator(image_type &image, const F &filter, const Rect &rect=Rect(0))
roi_filter_pixel_iterator()=default
const filter_type & Filter() const noexcept
typename image_type::pixel_traits pixel_traits
Mutable region-of-interest, filter pixel sample iterator.
roi_filter_sample_iterator(const roi_filter_sample_iterator &)=default
filter_type & Filter() noexcept
roi_filter_sample_iterator(image_type &image, const F &filter, const Rect &rect=Rect(0), int channel=-1)
roi_filter_sample_iterator(image_type &image, const F &filter, sample *i, sample *j)
sample * Position() const noexcept
typename image_type::sample sample
roi_filter_sample_iterator & MoveBy(int dx, int dy) noexcept
bool IsValid() const noexcept
const filter_type & Filter() const noexcept
image_type & Image() const noexcept
typename image_type::pixel_traits pixel_traits
roi_filter_sample_iterator(const roi_sample_iterator &i, const F &filter)
roi_filter_sample_iterator()=default
Mutable region-of-interest pixel iterator.
roi_pixel_iterator(const roi_pixel_iterator &)=default
sample * Position(int channel) const noexcept
typename image_type::sample sample
roi_pixel_iterator(image_type &image, const Rect &rect=Rect(0))
typename image_type::pixel_traits pixel_traits
image_type & Image() const noexcept
roi_pixel_iterator()=default
bool IsValid() const noexcept
roi_pixel_iterator & MoveBy(int dx, int dy) noexcept
Mutable region-of-interest pixel sample iterator.
sample * Position() const noexcept
roi_sample_iterator & MoveBy(int dx, int dy) noexcept
roi_sample_iterator(image_type &image, const Rect &rect=Rect(0), int channel=-1)
roi_sample_iterator(const roi_sample_iterator &)=default
typename image_type::pixel_traits pixel_traits
image_type & Image() const noexcept
typename image_type::sample sample
roi_sample_iterator(image_type &image, sample *i, sample *j)
bool IsValid() const noexcept
roi_sample_iterator()=default
Mutable pixel sample iterator.
sample_iterator()=default
sample_iterator(image_type &image, sample *i, sample *j)
sample_iterator & MoveBy(int dx, int dy) noexcept
typename image_type::sample sample
sample * Position() const noexcept
sample_iterator(image_type &image, int channel=-1)
sample_iterator(const sample_iterator &)=default
typename image_type::pixel_traits pixel_traits
bool IsValid() const noexcept
image_type & Image() const noexcept
Implements a generic, two-dimensional, shared or local image.
GenericImage & ShiftToBottomRight(int width, int height, const GenericVector< T > &fillValues)
double Norm(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
const sample * ScanLine(int y, int channel=0) const noexcept
void LocateExtremeSampleValues(Point &pmin, T &min, Point &pmax, T &max, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage & CropBy(int left, int top, int right, int bottom, const GenericVector< T > &fillValues)
double Sn(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage & Write(File &file, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
GenericImage & ShiftToBottomRight(int width, int height)
GenericImage Rescaled(T lowerBound, T upperBound, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
GenericImage & Fill(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Max(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
uint32 Hash32(int channel=-1, uint32 seed=0) const noexcept
GenericImage & ShiftToTopLeft(int width, int height, const GenericVector< T > &fillValues)
GenericImage & ShiftTo(const Point &p, const GenericVector< T > &fillValues)
GenericImage Applied(const ImageTransformation &transformation, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
GenericImage & Subtract(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage Divided(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
GenericImage & FreeData()
GenericImage Added(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
GenericImage & Assign(const GenericImage< P1 > &image, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & SetMinimum(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Xnor(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Transfer(GenericImage &image)
GenericImage & Apply(const GenericImage< P1 > &image, image_op op=ImageOp::Mov, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage Blended(const Bitmap &bitmap, const Point &point=Point(int_max), const Rect &rect=Rect(0)) const
GenericImage & SetMaximum(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
static int BytesPerSample() noexcept
void GetExtremePixelValues(sample &min, sample &max, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage(const GenericImage< P1 > &image, const Rect &rect, int firstChannel=-1, int lastChannel=-1)
sample & Pixel(int x, int y, int channel=0)
sample & Pixel(const Point &p, int channel=0)
double Qn(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage Raised(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
void GetIntensity(GenericImage< P1 > &I, const Rect &rect=Rect(0), int maxProcessors=0) const
GenericImage & ForgetAlphaChannels()
GenericImage & Nor(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Raise(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
bool SameSampleType(const GenericImage< P1 > &image) const noexcept
GenericImage & Sub(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & ShiftToBottomLeft(int width, int height, const GenericVector< T > &fillValues)
void LocateExtremeSampleValues(int &xmin, int &ymin, T &min, int &xmax, int &ymax, T &max, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
const sample * PixelAddress(const Point &p, int channel=0) const noexcept
GenericImage Inverted(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
GenericImage Truncated(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
GenericImage Subtracted(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
GenericImage & CropTo(int x0, int y0, int x1, int y1, const GenericVector< T > &fillValues)
sample * PixelAddress(int x, int y, int channel=0)
GenericImage & Crop(const GenericVector< T > &fillValues)
GenericImage & Move(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Mov(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
double Mean(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
size_type ImageSize() const noexcept
GenericImage & Read(File &file)
TwoSidedEstimate TwoSidedAvgDev(double center, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage & Or(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
void GetLightness(GenericImage< P1 > &L, const Rect &rect=Rect(0), int maxProcessors=0) const
pixel_allocator & Allocator() const noexcept
GenericImage & SetColumn(const T *buffer, int x, int channel=-1)
sample LocateMaximumPixelValue(Point &pmax, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
uint64 Hash(int channel=-1, uint64 seed=0) const noexcept
static bool IsComplexSample() noexcept
GenericImage & Nand(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Multiply(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage Applied(const GenericImage< P1 > &image, image_op op=ImageOp::Mov, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
GenericImage Applied(T scalar, image_op op=ImageOp::Mov, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
GenericImage & SetMinimum(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & SetLightness(const GenericImage< P1 > &L, const Point &point=Point(int_max), const Rect &rect=Rect(0), int maxProcessors=0)
GenericImage Multiplied(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
sample LocateMinimumPixelValue(int &xmin, int &ymin, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage Binarized(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
double MeanOfSquares(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage & White(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & ShiftToTopRight(int width, int height, const GenericVector< T > &fillValues)
GenericImage & DeleteAlphaChannel(int channel)
GenericImage & CropTo(int x0, int y0, int x1, int y1)
GenericImage & Binarize(T threshold, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
sample Pixel(int x, int y, int channel=0) const noexcept
GenericImage Binarized(T threshold, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
GenericImage & SetAbsoluteValue(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage AbsoluteValue(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
GenericImage & ShiftToCenter(int width, int height, const GenericVector< T > &fillValues)
bool SameSampleType(const GenericImage &image) const noexcept
GenericImage & Nor(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
bool IsUnique() const noexcept
void GetExtremeSampleValues(T &min, T &max, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage & Dif(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & CropTo(const Rect &rect)
GenericImage & EnsureLocal()
GenericImage(int width, int height, color_space colorSpace=ColorSpace::Gray)
GenericImage & Sub(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Mov(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Black(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
size_type LineSize() const noexcept
static int BitsPerSample() noexcept
GenericImage & SetColorSpace(color_space colorSpace, int maxProcessors=0)
GenericImage & Invert(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage AbsoluteDifference(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
void GetColumn(T *buffer, int x, int channel=-1) const
double AvgDev(double center, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
bool IsShared() const noexcept
sample * PixelData(int channel=0)
sample LocateMaximumSampleValue(Point &pmax, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage & CropTo(const Rect &rect, const GenericVector< T > &fillValues)
GenericImage Truncated(T lowerBound, T upperBound, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
GenericImage & ReleaseAlphaChannel(GenericImage &image, int channel)
GenericImage(GenericImage &&image)
TwoSidedEstimate TwoSidedMAD(double center, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
double SumOfSquares(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage & ShiftTo(int x, int y)
GenericImage & Truncate(T lowerBound, T upperBound, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & And(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage Maximum(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
GenericImage & Divide(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
sample MaximumSampleValue(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
sample_vector ColVector(int x, int channel=0) const
GenericImage & Raise(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Mul(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
sample_vector ColumnVector(int x, int channel=-1) const
size_type Count(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage & Normalize(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Nand(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Not(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & ShiftToTopRight(int width, int height)
GenericImage & Div(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
sample MaximumPixelValue(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage & SetRow(const T *buffer, int y, int channel=-1)
double Variance(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage & SetAbsoluteDifference(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
void GetRow(T *buffer, int y, int channel=-1) const
GenericImage & Div(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & ForgetAlphaChannel(int channel)
GenericImage & EnsureUnique()
GenericImage Minimum(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
typename pixel_traits::sample sample
GenericImage(void *handle)
void SetRGBWorkingSpace(const RGBColorSystem &RGBWS) override
GenericImage Filled(const GenericVector< T > &values, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
GenericImage(void *, int width, int height, color_space colorSpace=ColorSpace::Gray)
GenericImage & ImportData(sample **data, int width, int height, int numberOfChannels=1, color_space colorSpace=ColorSpace::Gray)
GenericImage & And(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Mul(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
size_type ChannelSize() const noexcept
sample LocateMaximumSampleValue(int &xmax, int &ymax, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage & Rescale(T lowerBound, T upperBound, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Exchange(GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Blend(const Bitmap &bitmap, const Point &point=Point(int_max), const Rect &rect=Rect(0))
GenericImage & ShiftBy(int dx, int dy)
sample * ScanLine(int y, int channel=0)
GenericImage & ShiftToBottomLeft(int width, int height)
double BiweightMidvariance(double center, double sigma, int k=9, bool reducedLength=false, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage & Fill(const GenericVector< T > &values, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Divide(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Rescale(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Add(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Pow(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & SetMaximum(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
sample LocateMinimumSampleValue(Point &pmin, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage & ShiftBy(int dx, int dy, const GenericVector< T > &fillValues)
const sample * PixelData(int channel=0) const noexcept
uint64 Hash64(int channel=-1, uint64 seed=0) const noexcept
GenericImage(const GenericImage< P1 > &image)
GenericImage & Xor(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & AllocateData(const Rect &rect, int numberOfChannels=1, color_space colorSpace=ColorSpace::Gray)
GenericImage & Min(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Apply(T scalar, image_op op=ImageOp::Mov, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & SetAbsoluteDifference(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
static bool IsFloatSample() noexcept
void GetLuminance(GenericImage< P1 > &Y, const Rect &rect=Rect(0), int maxProcessors=0) const
GenericImage & Invert(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & One(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
sample_vector RowVector(int y, int channel=-1) const
Vector Norms(int maxDegree=2, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage & Move(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Xchg(GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
double StdDev(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage & Subtract(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
Compression::subblock_list Compress(const Compression &compressor, const Rect &rect=Rect(0), int channel=-1, Compression::Performance *perf=nullptr) const
GenericImage & AllocateData(int width, int height, int numberOfChannels=1, color_space colorSpace=ColorSpace::Gray)
sample * PixelAddress(const Point &p, int channel=0)
sample MinimumPixelValue(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage & SetLuminance(const GenericImage< P1 > &Y, const Point &point=Point(int_max), const Rect &rect=Rect(0), int maxProcessors=0)
sample Pixel(const Point &p, int channel=0) const noexcept
GenericImage & ShiftToCenter(int width, int height)
sample LocateMaximumPixelValue(int &xmax, int &ymax, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage & Add(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Write(const String &filePath, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
GenericImage Inverted(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
GenericImage & CropBy(int left, int top, int right, int bottom)
GenericImage & Min(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Transfer(GenericImage &&image)
double OrderStatistic(double k, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage & Truncate(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
sample MinimumSampleValue(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage & ShiftToTopLeft(int width, int height)
GenericImage & Or(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
double MAD(double center, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
friend void Swap(GenericImage &x1, GenericImage &x2) noexcept
GenericImage & CreateAlphaChannels(int n)
GenericImage Normalized(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
GenericImage(File &stream)
GenericImage & Normalize(T lowerBound, T upperBound, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Max(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Pow(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
double Median(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage & DeleteAlphaChannels()
size_type NominalSize() const noexcept
GenericImage Filled(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
GenericImage & Read(const String &filePath)
GenericImage & Binarize(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Dif(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage(const GenericImage &image)
sample LocateMinimumPixelValue(Point &pmin, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage Normalized(T lowerBound, T upperBound, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
GenericImage & Shift(const GenericVector< T > &fillValues)
GenericImage & Xor(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
sample LocateMinimumSampleValue(int &xmin, int &ymin, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage & ShiftTo(int x, int y, const GenericVector< T > &fillValues)
double Modulus(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage & AddAlphaChannel(sample *data=nullptr)
const sample * PixelAddress(int x, int y, int channel=0) const noexcept
GenericImage & ShiftTo(const Point &p)
GenericImage & Xnor(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
double BendMidvariance(double center, double beta=0.2, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
size_type AlphaSize() const noexcept
GenericImage & Abs(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage Rescaled(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
GenericImage & Zero(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Multiply(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
TwoSidedEstimate TwoSidedBiweightMidvariance(double center, const TwoSidedEstimate &sigma, int k=9, bool reducedLength=false, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
A generic point in the two-dimensional space.
component x
Abscissa (horizontal, or X-axis coordinate).
component y
Ordinate (vertical, or Y-axis coordinate).
A generic rectangle in the two-dimensional space.
point LeftTop() const noexcept
component x1
Horizontal coordinate of the lower right corner.
component y1
Vertical coordinate of the lower right corner.
bool IsRect() const noexcept
void ResizeTo(T1 w, T1 h) noexcept
component y0
Vertical coordinate of the upper left corner.
component x0
Horizontal coordinate of the upper left corner.
GenericRectangle MovedTo(const pcl::GenericPoint< T1 > &p) const noexcept
GenericRectangle Ordered() const noexcept
component Width() const noexcept
component Height() const noexcept
GenericRectangle Intersection(const GenericRectangle< T1 > &r) const noexcept
Generic vector of arbitrary length.
int Length() const noexcept
const RGBColorSystem & RGBWorkingSpace() const noexcept
color_space ColorSpace() const noexcept
int Width() const noexcept
Rect Bounds() const noexcept
Acts like a union for all types of images in PCL, with optional class-wide ownership of transported i...
32-bit floating point real image.
Manages transparent allocation and deallocation of shared and local pixel data.
32-bit integer point on the plane.
Colorimetrically defined RGB working color space.
32-bit integer rectangle on the plane.
Dynamic array of pointers to objects providing direct iteration and element access by reference.
void Destroy(iterator i, size_type n=1)
void Add(const ReferenceArray &x)
Thread-safe reference counter for copy-on-write data structures.
size_type integer vector.
16-bit unsigned integer image.
32-bit unsigned integer image.
8-bit unsigned integer image.
64-bit floating point real vector.
bool operator==(const Array< T, A > &x1, const Array< T, A > &x2) noexcept
bool operator<(const Array< T, A > &x1, const Array< T, A > &x2) noexcept
const RGBA * ScanLine(int y) const
Complex< T > Sqrt(const Complex< T > &c) noexcept
T Abs(const Complex< T > &c) noexcept
uint64 Hash64(const void *data, size_type size, uint64 seed=0) noexcept
uint32 Hash32(const void *data, size_type size, uint32 seed=0) noexcept
GenericImage< P1 > operator-(const GenericImage< P1 > &image1, const GenericImage< P2 > &image2)
GenericImage< P1 > operator/(const GenericImage< P1 > &image1, const GenericImage< P2 > &image2)
GenericImage< P1 > operator+(const GenericImage< P1 > &image1, const GenericImage< P2 > &image2)
GenericImage< P1 > operator^(const GenericImage< P1 > &image1, const GenericImage< P2 > &image2)
GenericImage< P1 > operator*(const GenericImage< P1 > &image1, const GenericImage< P2 > &image2)
int TruncInt(T x) noexcept
constexpr T Pow2(T x) noexcept
void Swap(GenericPoint< T > &p1, GenericPoint< T > &p2) noexcept
unsigned long long uint64
RI Select(RI i, RI j, distance_type k)
double Qn(T *__restrict__ x, T *__restrict__ xn)
double BendMidvariance(const T *__restrict__ x, const T *__restrict__ xn, double center, double beta=0.2)
double Variance(const T *__restrict__ i, const T *__restrict__ j, double center) noexcept
double Median(const T *__restrict__ i, const T *__restrict__ j)
double Sn(T *__restrict__ x, T *__restrict__ xn)
#define INIT_THREAD_MONITOR()
Declares and initializes local variables used for synchronization of thread status monitoring.
#define UPDATE_THREAD_MONITOR(N)
Synchronized status monitoring of a set of image processing threads.
constexpr const T & Min(const T &a, const T &b) noexcept
constexpr const T & Range(const T &x, const T &a, const T &b) noexcept
constexpr const T & Max(const T &a, const T &b) noexcept
void Apply(FI i, FI j, F f) noexcept(noexcept(f))
int NumberOfNominalChannels(int colorSpace)
String Name(int colorSpace)
bool IsBitwiseLogicalOperator(int op) noexcept
bool IsPixelCompositionOperator(int op) noexcept
String Id(value_type operation)
bool IsArithmeticOperator(int op) noexcept
bool IsMoveOperator(int op) noexcept
Thread synchronization data for status monitoring of parallel image processing tasks.
StatusMonitor status
Status monitoring object.
Two-sided descriptive statistical estimate.
double high
High estimate component.
double low
Low estimate component.