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 !=
nullptr )
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 !=
nullptr )
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 !=
nullptr )
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 !=
nullptr )
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 );
10832 int maxProcessors = 0,
bool __performanceAnalysis__ =
false )
10835 if ( !ParseSelection( r, firstChannel, lastChannel ) )
10839 if ( m_status.IsInitializationEnabled() )
10840 m_status.Initialize(
"Sampling pixel values", N );
10843 if ( likely( !__performanceAnalysis__ ) )
10846 data.
algorithm = PerformanceAnalysisAlgorithm::Sampling;
10851 L = OptimalThreadRows( r.
Height(), r.
Width(), maxProcessors, N/Thread::OptimalNumberOfThreads( data ) );
10854 L = OptimalThreadRows( r.
Height(), r.
Width(), maxProcessors, 1 );
10856 bool useAffinity = m_parallel && Thread::IsRootThread();
10858 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
10859 threads.
Add(
new DSmpThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
10860 if ( threads.
Length() > 1 )
10863 for ( DSmpThread& thread : threads )
10864 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
10865 for ( DSmpThread& thread : threads )
10872 for ( DSmpThread& thread : threads )
10873 if ( thread.n > 0 )
10875 values.
Add( thread.values.Begin(), thread.values.At( thread.n ) );
10876 thread.values.Clear();
10906 int maxProcessors = 0 )
const
10909 if ( !ParseSelection( r, firstChannel, lastChannel ) )
10913 if ( m_status.IsInitializationEnabled() )
10914 m_status.Initialize(
"Computing minimum pixel sample value", N );
10919 data.
algorithm = PerformanceAnalysisAlgorithm::MinMax;
10924 L = OptimalThreadRows( r.
Height(), r.
Width(), maxProcessors, N/Thread::OptimalNumberOfThreads( data ) );
10926 bool useAffinity = m_parallel && Thread::IsRootThread();
10928 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
10929 threads.
Add(
new MinThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
10930 if ( threads.
Length() > 1 )
10933 for ( MinThread& thread : threads )
10934 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
10935 for ( MinThread& thread : threads )
10941 sample min = P::MinSampleValue();
10943 if ( threads[i].count > 0 )
10945 min = threads[i].min;
10946 while ( ++i < threads.
Length() )
10947 if ( threads[i].count > 0 )
10948 if ( threads[i].min < min )
10949 min = threads[i].min;
10964 int maxProcessors = 0 )
const
10966 return MinimumSampleValue( rect, firstChannel, lastChannel, maxProcessors );
10989 int firstChannel = -1,
int lastChannel = -1,
int maxProcessors = 0 )
const
10992 if ( !ParseSelection( r, firstChannel, lastChannel ) )
10996 if ( m_status.IsInitializationEnabled() )
10997 m_status.Initialize(
"Computing maximum pixel sample value", N );
11002 data.
algorithm = PerformanceAnalysisAlgorithm::MinMax;
11007 L = OptimalThreadRows( r.
Height(), r.
Width(), maxProcessors, N/Thread::OptimalNumberOfThreads( data ) );
11009 bool useAffinity = m_parallel && Thread::IsRootThread();
11011 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
11012 threads.
Add(
new MaxThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
11013 if ( threads.
Length() > 1 )
11016 for ( MaxThread& thread : threads )
11017 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
11018 for ( MaxThread& thread : threads )
11024 sample max = P::MinSampleValue();
11026 if ( threads[i].count > 0 )
11028 max = threads[i].max;
11029 while ( ++i < threads.
Length() )
11030 if ( threads[i].count > 0 )
11031 if ( max < threads[i].max )
11032 max = threads[i].max;
11047 int maxProcessors = 0 )
const
11049 return MaximumSampleValue( rect, firstChannel, lastChannel, maxProcessors );
11078 template <
typename T>
11080 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
11081 int maxProcessors = 0,
bool __performanceAnalysis__ =
false )
const
11084 if ( !ParseSelection( r, firstChannel, lastChannel ) )
11087 P::FromSample( min, P::MinSampleValue() );
11093 if ( m_status.IsInitializationEnabled() )
11094 m_status.Initialize(
"Computing extreme pixel sample values", N );
11097 if ( likely( !__performanceAnalysis__ ) )
11100 data.
algorithm = PerformanceAnalysisAlgorithm::MinMax;
11105 L = OptimalThreadRows( r.
Height(), r.
Width(), maxProcessors, N/Thread::OptimalNumberOfThreads( data ) );
11108 L = OptimalThreadRows( r.
Height(), r.
Width(), maxProcessors, 1 );
11110 bool useAffinity = m_parallel && Thread::IsRootThread();
11112 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
11113 threads.
Add(
new MinMaxThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
11114 if ( threads.
Length() > 1 )
11117 for ( MinMaxThread& thread : threads )
11118 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
11119 for ( MinMaxThread& thread : threads )
11125 sample vmin = P::MinSampleValue();
11126 sample vmax = P::MinSampleValue();
11128 if ( threads[i].count > 0 )
11130 vmin = threads[i].min;
11131 vmax = threads[i].max;
11132 while ( ++i < threads.
Length() )
11133 if ( threads[i].count > 0 )
11135 if ( threads[i].min < vmin )
11136 vmin = threads[i].min;
11137 if ( vmax < threads[i].max )
11138 vmax = threads[i].max;
11145 P::FromSample( min, vmin );
11146 P::FromSample( max, vmax );
11155 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
11156 int maxProcessors = 0 )
const
11158 GetExtremeSampleValues( min, max, rect, firstChannel, lastChannel, maxProcessors );
11188 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
11189 int maxProcessors = 0 )
const
11192 if ( !ParseSelection( r, firstChannel, lastChannel ) )
11196 return P::MinSampleValue();
11200 if ( m_status.IsInitializationEnabled() )
11201 m_status.Initialize(
"Locating minimum pixel sample value", N );
11206 data.
algorithm = PerformanceAnalysisAlgorithm::MinMax;
11211 L = OptimalThreadRows( r.
Height(), r.
Width(), maxProcessors, N/Thread::OptimalNumberOfThreads( data ) );
11213 bool useAffinity = m_parallel && Thread::IsRootThread();
11215 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
11216 threads.
Add(
new MinPosThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
11217 if ( threads.
Length() > 1 )
11220 for ( MinPosThread& thread : threads )
11221 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
11222 for ( MinPosThread& thread : threads )
11229 sample min = P::MinSampleValue();
11231 if ( threads[i].count > 0 )
11233 min = threads[i].min;
11234 xmin = threads[i].pmin.x;
11235 ymin = threads[i].pmin.y;
11236 while ( ++i < threads.
Length() )
11237 if ( threads[i].count > 0 )
11238 if ( threads[i].min < min )
11240 min = threads[i].min;
11241 xmin = threads[i].pmin.x;
11242 ymin = threads[i].pmin.y;
11275 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
11276 int maxProcessors = 0 )
const
11278 return LocateMinimumSampleValue( pmin.
x, pmin.
y, rect, firstChannel, lastChannel, maxProcessors );
11287 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
11288 int maxProcessors = 0 )
const
11290 return LocateMinimumSampleValue( xmin, ymin, rect, firstChannel, lastChannel, maxProcessors );
11299 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
11300 int maxProcessors = 0 )
const
11302 return LocateMinimumSampleValue( pmin, rect, firstChannel, lastChannel, maxProcessors );
11332 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
11333 int maxProcessors = 0 )
const
11336 if ( !ParseSelection( r, firstChannel, lastChannel ) )
11340 return P::MaxSampleValue();
11344 if ( m_status.IsInitializationEnabled() )
11345 m_status.Initialize(
"Locating maximum pixel sample value", N );
11350 data.
algorithm = PerformanceAnalysisAlgorithm::MinMax;
11355 L = OptimalThreadRows( r.
Height(), r.
Width(), maxProcessors, N/Thread::OptimalNumberOfThreads( data ) );
11357 bool useAffinity = m_parallel && Thread::IsRootThread();
11359 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
11360 threads.
Add(
new MaxPosThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
11361 if ( threads.
Length() > 1 )
11364 for ( MaxPosThread& thread : threads )
11365 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
11366 for ( MaxPosThread& thread : threads )
11373 sample max = P::MinSampleValue();
11375 if ( threads[i].count > 0 )
11377 max = threads[i].max;
11378 xmax = threads[i].pmax.x;
11379 ymax = threads[i].pmax.y;
11380 while ( ++i < threads.
Length() )
11381 if ( threads[i].count > 0 )
11382 if ( max < threads[i].max )
11384 max = threads[i].max;
11385 xmax = threads[i].pmax.x;
11386 ymax = threads[i].pmax.y;
11419 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
11420 int maxProcessors = 0 )
const
11422 return LocateMaximumSampleValue( pmax.
x, pmax.
y, rect, firstChannel, lastChannel, maxProcessors );
11431 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
11432 int maxProcessors = 0 )
const
11434 return LocateMaximumSampleValue( xmax, ymax, rect, firstChannel, lastChannel, maxProcessors );
11443 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
11444 int maxProcessors = 0 )
const
11446 return LocateMaximumSampleValue( pmax, rect, firstChannel, lastChannel, maxProcessors );
11485 template <
typename T>
11487 int& xmax,
int& ymax, T& max,
11488 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
11489 int maxProcessors = 0 )
const
11492 if ( !ParseSelection( r, firstChannel, lastChannel ) )
11495 xmin = ymin = xmax = ymax = 0;
11496 P::FromSample( min, P::MinSampleValue() );
11502 if ( m_status.IsInitializationEnabled() )
11503 m_status.Initialize(
"Locating extreme pixel sample values", N );
11508 data.
algorithm = PerformanceAnalysisAlgorithm::MinMax;
11513 L = OptimalThreadRows( r.
Height(), r.
Width(), maxProcessors, N/Thread::OptimalNumberOfThreads( data ) );
11515 bool useAffinity = m_parallel && Thread::IsRootThread();
11517 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
11518 threads.
Add(
new MinMaxPosThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
11519 if ( threads.
Length() > 1 )
11522 for ( MinMaxPosThread& thread : threads )
11523 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
11524 for ( MinMaxPosThread& thread : threads )
11530 xmin = ymin = xmax = ymax = -1;
11531 sample vmin = P::MinSampleValue();
11532 sample vmax = P::MinSampleValue();
11534 if ( threads[i].count > 0 )
11536 vmin = threads[i].min;
11537 xmin = threads[i].pmin.x;
11538 ymin = threads[i].pmin.y;
11539 vmax = threads[i].max;
11540 xmax = threads[i].pmax.x;
11541 ymax = threads[i].pmax.y;
11542 while ( ++i < threads.
Length() )
11543 if ( threads[i].count > 0 )
11545 if ( threads[i].min < vmin )
11547 vmin = threads[i].min;
11548 xmin = threads[i].pmin.x;
11549 ymin = threads[i].pmin.y;
11551 if ( vmax < threads[i].max )
11553 vmax = threads[i].max;
11554 xmax = threads[i].pmax.x;
11555 ymax = threads[i].pmax.y;
11563 P::FromSample( min, vmin );
11564 P::FromSample( max, vmax );
11594 template <
typename T>
11596 Point& pmax, T& max,
11597 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
11598 int maxProcessors = 0 )
const
11600 LocateExtremeSampleValues( pmin.
x, pmin.
y, min,
11601 pmax.
x, pmax.
y, max,
11602 rect, firstChannel, lastChannel, maxProcessors );
11631 int maxProcessors = 0 )
const
11634 if ( !ParseSelection( r, firstChannel, lastChannel ) )
11638 if ( m_status.IsInitializationEnabled() )
11639 m_status.Initialize(
"Counting pixel samples", N );
11641 if ( !this->IsRangeClippingEnabled() )
11650 data.
algorithm = PerformanceAnalysisAlgorithm::MinMax;
11655 L = OptimalThreadRows( r.
Height(), r.
Width(), maxProcessors, N/Thread::OptimalNumberOfThreads( data ) );
11657 bool useAffinity = m_parallel && Thread::IsRootThread();
11659 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
11660 threads.
Add(
new CountThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
11661 if ( threads.
Length() > 1 )
11664 for ( CountThread& thread : threads )
11665 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
11666 for ( CountThread& thread : threads )
11673 for (
const CountThread& thread : threads )
11674 count += thread.count;
11709 double Mean(
const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
11710 int maxProcessors = 0,
bool __performanceAnalysis__ =
false )
const
11713 if ( !ParseSelection( r, firstChannel, lastChannel ) )
11717 if ( m_status.IsInitializationEnabled() )
11718 m_status.Initialize(
"Computing mean pixel sample value", N );
11721 if ( likely( !__performanceAnalysis__ ) )
11724 data.
algorithm = PerformanceAnalysisAlgorithm::Sum;
11729 L = OptimalThreadRows( r.
Height(), r.
Width(), maxProcessors, N/Thread::OptimalNumberOfThreads( data ) );
11732 L = OptimalThreadRows( r.
Height(), r.
Width(), maxProcessors, 1 );
11734 bool useAffinity = m_parallel && Thread::IsRootThread();
11736 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
11737 threads.
Add(
new SumThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
11738 if ( threads.
Length() > 1 )
11741 for ( SumThread& thread : threads )
11742 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
11743 for ( SumThread& thread : threads )
11752 for (
const SumThread& thread : threads )
11754 double y = thread.s - e;
11795 double Median(
const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
11796 int maxProcessors = 0 )
const
11799 if ( !ParseSelection( r, firstChannel, lastChannel ) )
11803 if ( m_status.IsInitializationEnabled() )
11804 m_status.Initialize(
"Computing median pixel sample value", N );
11808 SmpThread S( *
this, r, firstChannel, lastChannel, 0, r.
Height() );
11815 double m = double( *
pcl::Select( S.samples.Begin(), S.samples.At( S.n ), S.n >> 1 ) )/double( P::MaxSampleValue() );
11821 m = (m + double( *
pcl::Select( S.samples.Begin(), S.samples.At( S.n ), (S.n >> 1)-1 ) )/double( P::MaxSampleValue() ))/2;
11826 bool useAffinity = m_parallel && Thread::IsRootThread();
11834 data.
algorithm = PerformanceAnalysisAlgorithm::MinMax;
11839 L = OptimalThreadRows( r.
Height(), r.
Width(), maxProcessors, N/Thread::OptimalNumberOfThreads( data ) );
11842 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
11843 threads <<
new MinMaxThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) );
11845 if ( threads.
Length() > 1 )
11848 for ( MinMaxThread& thread : threads )
11849 thread.Start( ThreadPriority::DefaultMax, useAffinity ? i++ : -1 );
11850 for ( MinMaxThread& thread : threads )
11856 sample slow = 0, shigh = 0;
11858 if ( threads[i].count > 0 )
11860 slow = threads[i].min;
11861 shigh = threads[i].max;
11862 count = threads[i].count;
11863 while ( ++i < threads.
Length() )
11864 if ( threads[i].count > 0 )
11866 if ( threads[i].min < slow )
11867 slow = threads[i].min;
11868 if ( shigh < threads[i].max )
11869 shigh = threads[i].max;
11870 count += threads[i].count;
11877 low = double( slow );
11878 high = double( shigh );
11887 const double eps = P::IsComplexSample() ? 2*std::numeric_limits<double>::epsilon() :
11888 (P::IsFloatSample() ? 2*std::numeric_limits<typename P::component>::epsilon() :
11889 0.5/
Pow2(
double( P::BitsPerSample() ) ));
11890 if ( high - low < eps )
11893 return low/double( P::MaxSampleValue() );
11899 data.
algorithm = PerformanceAnalysisAlgorithm::FastMedian;
11904 L = OptimalThreadRows( r.
Height(), r.
Width(), maxProcessors, N/Thread::OptimalNumberOfThreads( data ) );
11907 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
11908 threads <<
new HistogramThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ), low, high );
11910 double mh = 0, l0 = low;
11913 for (
size_type n = 0, n2 = count >> 1, step = 0, it = 0;; ++it )
11916 if ( it == 0 && step )
11920 if ( threads.
Length() > 1 )
11923 for ( HistogramThread& thread : threads )
11924 thread.Start( ThreadPriority::DefaultMax, useAffinity ? i++ : -1 );
11925 for ( HistogramThread& thread : threads )
11935 if ( (count & 1) == 0 )
11939 for (
int i = 0; ; n += H[i++] )
11940 if ( n + H[i] > n2 )
11942 double range = high - low;
11943 high = (range * (i + 1))/(__PCL_MEDIAN_HISTOGRAM_LENGTH - 1) + low;
11944 low = (range * i)/(__PCL_MEDIAN_HISTOGRAM_LENGTH - 1) + low;
11945 if ( high - low < eps )
11951 return low/double( P::MaxSampleValue() );
11957 return (low + mh)/2/double( P::MaxSampleValue() );
12003 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
12004 int maxProcessors = 0 )
const
12006 if ( k < 0 || k > 1 )
12010 if ( !ParseSelection( r, firstChannel, lastChannel ) )
12014 if ( m_status.IsInitializationEnabled() )
12015 m_status.Initialize(
"Computing order statistic", N );
12019 SmpThread S( *
this, r, firstChannel, lastChannel, 0, r.
Height() );
12024 return double( *
pcl::Select( S.samples.Begin(), S.samples.At( S.n ),
distance_type( k*(S.n - 1) ) ) )/double( P::MaxSampleValue() );
12027 bool useAffinity = m_parallel && Thread::IsRootThread();
12035 data.
algorithm = PerformanceAnalysisAlgorithm::MinMax;
12040 L = OptimalThreadRows( r.
Height(), r.
Width(), maxProcessors, N/Thread::OptimalNumberOfThreads( data ) );
12043 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
12044 threads <<
new MinMaxThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) );
12046 if ( threads.
Length() > 1 )
12049 for ( MinMaxThread& thread : threads )
12050 thread.Start( ThreadPriority::DefaultMax, useAffinity ? i++ : -1 );
12051 for ( MinMaxThread& thread : threads )
12057 sample slow = 0, shigh = 0;
12059 if ( threads[i].count > 0 )
12061 slow = threads[i].min;
12062 shigh = threads[i].max;
12063 count = threads[i].count;
12064 while ( ++i < threads.
Length() )
12065 if ( threads[i].count > 0 )
12067 if ( threads[i].min < slow )
12068 slow = threads[i].min;
12069 if ( shigh < threads[i].max )
12070 shigh = threads[i].max;
12071 count += threads[i].count;
12078 low = double( slow );
12079 high = double( shigh );
12091 return high/double( P::MaxSampleValue() );
12094 const double eps = P::IsComplexSample() ? 2*std::numeric_limits<double>::epsilon() :
12095 (P::IsFloatSample() ? 2*std::numeric_limits<typename P::component>::epsilon() :
12096 0.5/
Pow2(
double( P::BitsPerSample() ) ));
12097 if ( k == 0 || high - low < eps )
12100 return low/double( P::MaxSampleValue() );
12108 data.
algorithm = PerformanceAnalysisAlgorithm::FastMedian;
12113 L = OptimalThreadRows( r.
Height(), r.
Width(), maxProcessors, N/Thread::OptimalNumberOfThreads( data ) );
12116 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
12117 threads <<
new HistogramThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ), low, high );
12121 if ( threads.
Length() > 1 )
12124 for ( HistogramThread& thread : threads )
12125 thread.Start( ThreadPriority::DefaultMax, useAffinity ? i++ : -1 );
12126 for ( HistogramThread& thread : threads )
12136 for (
int i = 0; ; n += H[i++] )
12137 if ( n + H[i] > index )
12139 double range = high - low;
12140 high = (range * (i + 1))/(__PCL_MEDIAN_HISTOGRAM_LENGTH - 1) + low;
12141 low = (range * i)/(__PCL_MEDIAN_HISTOGRAM_LENGTH - 1) + low;
12142 if ( high - low < eps )
12146 return low/double( P::MaxSampleValue() );
12188 int maxProcessors = 0 )
const
12191 if ( !ParseSelection( r, firstChannel, lastChannel ) )
12195 if ( m_status.IsInitializationEnabled() )
12196 m_status.Initialize(
"Computing variance", N );
12201 data.
algorithm = PerformanceAnalysisAlgorithm::Sum;
12206 L = OptimalThreadRows( r.
Height(), r.
Width(), maxProcessors, N/Thread::OptimalNumberOfThreads( data ) );
12208 bool useAffinity = m_parallel && Thread::IsRootThread();
12210 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
12211 sumThreads.
Add(
new SumThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
12212 if ( sumThreads.
Length() > 1 )
12215 for ( SumThread& thread : sumThreads )
12216 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
12217 for ( SumThread& thread : sumThreads )
12221 sumThreads[0].Run();
12226 for (
const SumThread& thread : sumThreads )
12228 double y = thread.s - e;
12242 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
12243 varThreads.
Add(
new VarThread( *
this, mean, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
12244 if ( varThreads.
Length() > 1 )
12247 for ( VarThread& thread : varThreads )
12248 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
12249 for ( VarThread& thread : varThreads )
12253 varThreads[0].Run();
12255 double var = 0, eps = 0;
12256 for (
const VarThread& thread : varThreads )
12257 var += thread.var, eps += thread.eps;
12261 return (var - eps*eps/n)/(n - 1);
12296 double StdDev(
const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
12297 int maxProcessors = 0 )
const
12299 return pcl::Sqrt(
Variance( rect, firstChannel, lastChannel, maxProcessors ) );
12342 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
12343 int maxProcessors = 0 )
const
12346 if ( !ParseSelection( r, firstChannel, lastChannel ) )
12350 if ( m_status.IsInitializationEnabled() )
12351 m_status.Initialize(
"Computing average absolute deviation", N );
12356 data.
algorithm = PerformanceAnalysisAlgorithm::Sum;
12361 L = OptimalThreadRows( r.
Height(), r.
Width(), maxProcessors, N/Thread::OptimalNumberOfThreads( data ) );
12363 bool useAffinity = m_parallel && Thread::IsRootThread();
12365 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
12366 threads.
Add(
new SumAbsDevThread( *
this, center, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
12367 if ( threads.
Length() > 1 )
12370 for ( SumAbsDevThread& thread : threads )
12371 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
12372 for ( SumAbsDevThread& thread : threads )
12381 for (
const SumAbsDevThread& thread : threads )
12383 double y = thread.s - e;
12420 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
12421 int maxProcessors = 0 )
const
12424 if ( !ParseSelection( r, firstChannel, lastChannel ) )
12428 if ( m_status.IsInitializationEnabled() )
12429 m_status.Initialize(
"Computing two-sided average absolute deviation", N );
12434 data.
algorithm = PerformanceAnalysisAlgorithm::Sum;
12439 L = OptimalThreadRows( r.
Height(), r.
Width(), maxProcessors, N/Thread::OptimalNumberOfThreads( data ) );
12441 bool useAffinity = m_parallel && Thread::IsRootThread();
12443 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
12444 threads.
Add(
new TwoSidedSumAbsDevThread( *
this, center, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
12445 if ( threads.
Length() > 1 )
12448 for ( TwoSidedSumAbsDevThread& thread : threads )
12449 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
12450 for ( TwoSidedSumAbsDevThread& thread : threads )
12456 double s0 = 0, s1 = 0;
12457 double e0 = 0, e1 = 0;
12459 for (
const TwoSidedSumAbsDevThread& thread : threads )
12461 double y = thread.s0 - e0;
12466 y = thread.s1 - e1;
12477 return { (n0 > 0) ? s0/n0 : 0.0,
12478 (n1 > 0) ? s1/n1 : 0.0 };
12516 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
12517 int maxProcessors = 0 )
const
12520 if ( !ParseSelection( r, firstChannel, lastChannel ) )
12524 if ( m_status.IsInitializationEnabled() )
12525 m_status.Initialize(
"Computing median absolute deviation", N );
12529 AbsDevSmpThread S( *
this, center, r, firstChannel, lastChannel, 0, r.
Height() );
12536 double m = *
pcl::Select( S.values.Begin(), S.values.At( S.n ), S.n >> 1 );
12542 m = (m + *
pcl::Select( S.values.Begin(), S.values.At( S.n ), (S.n >> 1)-1 ))/2;
12547 bool useAffinity = m_parallel && Thread::IsRootThread();
12555 data.
algorithm = PerformanceAnalysisAlgorithm::MinMax;
12560 L = OptimalThreadRows( r.
Height(), r.
Width(), maxProcessors, N/Thread::OptimalNumberOfThreads( data ) );
12563 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
12564 threads <<
new ExtremeAbsDevThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ), center );
12566 if ( threads.
Length() > 1 )
12569 for ( ExtremeAbsDevThread& thread : threads )
12570 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
12571 for ( ExtremeAbsDevThread& thread : threads )
12578 if ( threads[i].count > 0 )
12580 low = threads[i].minAbsDev;
12581 high = threads[i].maxAbsDev;
12582 count += threads[i].count;
12583 while ( ++i < threads.
Length() )
12584 if ( threads[i].count > 0 )
12586 if ( threads[i].minAbsDev < low )
12587 low = threads[i].minAbsDev;
12588 if ( threads[i].maxAbsDev > high )
12589 high = threads[i].maxAbsDev;
12590 count += threads[i].count;
12598 const double eps = 2*std::numeric_limits<double>::epsilon();
12599 if ( count == 0 || high - low < eps )
12608 data.
algorithm = PerformanceAnalysisAlgorithm::FastMedian;
12613 L = OptimalThreadRows( r.
Height(), r.
Width(), maxProcessors, N/Thread::OptimalNumberOfThreads( data ) );
12616 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
12617 threads <<
new AbsDevHistogramThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ), center, low, high );
12619 double mh = 0, l0 = low;
12622 for (
size_type n = 0, n2 = count >> 1, step = 0, it = 0;; ++it )
12625 if ( it == 0 && step )
12629 if ( threads.
Length() > 1 )
12632 for ( AbsDevHistogramThread& thread : threads )
12633 thread.Start( ThreadPriority::DefaultMax, useAffinity ? i++ : -1 );
12634 for ( AbsDevHistogramThread& thread : threads )
12644 if ( (count & 1) == 0 )
12648 for (
int i = 0; ; n += H[i++] )
12649 if ( n + H[i] > n2 )
12651 double range = high - low;
12652 high = (range * (i + 1))/(__PCL_MEDIAN_HISTOGRAM_LENGTH - 1) + low;
12653 low = (range * i)/(__PCL_MEDIAN_HISTOGRAM_LENGTH - 1) + low;
12654 if ( high - low < eps )
12666 return (low + mh)/2;
12701 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
12702 int maxProcessors = 0 )
const
12705 if ( !ParseSelection( r, firstChannel, lastChannel ) )
12709 if ( m_status.IsInitializationEnabled() )
12710 m_status.Initialize(
"Computing two-sided median absolute deviation", N );
12714 TwoSidedAbsDevSmpThread S( *
this, center, r, firstChannel, lastChannel, 0, r.
Height() );
12721 bool useAffinity = m_parallel && Thread::IsRootThread();
12723 double minLow = 0, minHigh = 0, maxLow = 0, maxHigh = 0;
12729 data.
algorithm = PerformanceAnalysisAlgorithm::MinMax;
12734 L = OptimalThreadRows( r.
Height(), r.
Width(), maxProcessors, N/Thread::OptimalNumberOfThreads( data ) );
12737 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
12738 threads <<
new TwoSidedExtremeAbsDevThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ), center );
12740 if ( threads.
Length() > 1 )
12743 for ( TwoSidedExtremeAbsDevThread& thread : threads )
12744 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
12745 for ( TwoSidedExtremeAbsDevThread& thread : threads )
12752 if ( threads[i].nLow > 0 )
12754 minLow = threads[i].minAbsDevLow;
12755 maxLow = threads[i].maxAbsDevLow;
12756 nLow = threads[i].nLow;
12757 while ( ++i < threads.
Length() )
12758 if ( threads[i].nLow > 0 )
12760 if ( threads[i].minAbsDevLow < minLow )
12761 minLow = threads[i].minAbsDevLow;
12762 if ( threads[i].maxAbsDevLow > maxLow )
12763 maxLow = threads[i].maxAbsDevLow;
12764 nLow += threads[i].nLow;
12770 if ( threads[i].nHigh > 0 )
12772 minHigh = threads[i].minAbsDevHigh;
12773 maxHigh = threads[i].maxAbsDevHigh;
12774 nHigh = threads[i].nHigh;
12775 while ( ++i < threads.
Length() )
12776 if ( threads[i].nHigh > 0 )
12778 if ( threads[i].minAbsDevHigh < minHigh )
12779 minHigh = threads[i].minAbsDevHigh;
12780 if ( threads[i].maxAbsDevHigh > maxHigh )
12781 maxHigh = threads[i].maxAbsDevHigh;
12782 nHigh += threads[i].nHigh;
12793 data.
algorithm = PerformanceAnalysisAlgorithm::FastMedian;
12798 L = OptimalThreadRows( r.
Height(), r.
Width(), maxProcessors, N/Thread::OptimalNumberOfThreads( data ) );
12801 double sideLow, sideHigh;
12803 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
12804 threads <<
new TwoSidedAbsDevHistogramThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ), center, side, sideLow, sideHigh );
12806 const double eps = 2*std::numeric_limits<double>::epsilon();
12808 for ( side = 0; side < 2; ++side )
12817 sideLow = side ? minHigh : minLow;
12818 sideHigh = side ? maxHigh : maxLow;
12819 if ( sideHigh - sideLow < eps )
12825 double mh = 0, h0 = sideHigh;
12828 for (
size_type count = 0, n2 = n >> 1, step = 0, it = 0;; ++it )
12831 if ( it == 0 && step )
12835 if ( threads.
Length() > 1 )
12838 for ( TwoSidedAbsDevHistogramThread& thread : threads )
12839 thread.Start( ThreadPriority::DefaultMax, useAffinity ? i++ : -1 );
12840 for ( TwoSidedAbsDevHistogramThread& thread : threads )
12850 if ( (n & 1) == 0 )
12854 for (
int i = 0; ; count += H[i++] )
12855 if ( count + H[i] > n2 )
12857 double range = sideHigh - sideLow;
12858 sideHigh = (range * (i + 1))/(__PCL_MEDIAN_HISTOGRAM_LENGTH - 1) + sideLow;
12859 sideLow = (range * i)/(__PCL_MEDIAN_HISTOGRAM_LENGTH - 1) + sideLow;
12860 if ( sideHigh - sideLow < eps )
12864 mad[side] = sideLow;
12865 goto __madNextSide;
12869 mad[side] = (sideLow + mh)/2;
12870 goto __madNextSide;
12890 return { mad[0], mad[1] };
12938 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
12939 int maxProcessors = 0,
bool __performanceAnalysis__ =
false )
const
12942 if ( !ParseSelection( r, firstChannel, lastChannel ) )
12946 double kd = k * sigma;
12947 if ( kd < 0 || 1 + kd == 1 )
12953 if ( m_status.IsInitializationEnabled() )
12954 m_status.Initialize(
"Computing biweight midvariance", N );
12957 if ( likely( !__performanceAnalysis__ ) )
12960 data.
algorithm = PerformanceAnalysisAlgorithm::BiweightMidvariance;
12965 L = OptimalThreadRows( r.
Height(), r.
Width(), maxProcessors, N/Thread::OptimalNumberOfThreads( data ) );
12968 L = OptimalThreadRows( r.
Height(), r.
Width(), maxProcessors, 1 );
12970 bool useAffinity = m_parallel && Thread::IsRootThread();
12972 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
12973 threads.
Add(
new BWMVThread( *
this, center, kd, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
12974 if ( threads.
Length() > 1 )
12977 for ( BWMVThread& thread : threads )
12978 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
12979 for ( BWMVThread& thread : threads )
12985 double num = 0, den = 0;
12987 for (
const BWMVThread& thread : threads )
12999 return (n >= 2 && 1 + den != 1) ? (reducedLength ? nr : n)*num/den : 0.0;
13031 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
13032 int maxProcessors = 0 )
const
13035 if ( !ParseSelection( r, firstChannel, lastChannel ) )
13039 double kd0 = k * sigma.
low;
13040 double kd1 = k * sigma.
high;
13041 if ( kd0 < 0 || 1 + kd0 == 1 || kd1 < 0 || 1 + kd1 == 1 )
13047 if ( m_status.IsInitializationEnabled() )
13048 m_status.Initialize(
"Computing two-sided biweight midvariance", N );
13053 data.
algorithm = PerformanceAnalysisAlgorithm::BiweightMidvariance;
13058 L = OptimalThreadRows( r.
Height(), r.
Width(), maxProcessors, N/Thread::OptimalNumberOfThreads( data ) );
13060 bool useAffinity = m_parallel && Thread::IsRootThread();
13062 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
13063 threads.
Add(
new TwoSidedBWMVThread( *
this, center, kd0, kd1, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
13064 if ( threads.
Length() > 1 )
13067 for ( TwoSidedBWMVThread& thread : threads )
13068 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
13069 for ( TwoSidedBWMVThread& thread : threads )
13075 double num0 = 0, den0 = 0, num1 = 0, den1 = 0;
13076 size_type n0 = 0, n1 = 0, nr0 = 0, nr1 = 0;
13077 for (
const TwoSidedBWMVThread& thread : threads )
13079 num0 += thread.num0;
13080 den0 += thread.den0;
13081 num1 += thread.num1;
13082 den1 += thread.den1;
13095 return { (n0 >= 2 && 1 + den0 != 1) ? (reducedLength ? nr0 : n0)*num0/den0 : 0.0,
13096 (n1 >= 2 && 1 + den1 != 1) ? (reducedLength ? nr1 : n1)*num1/den1 : 0.0 };
13143 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
13144 int maxProcessors = 0 )
const
13147 if ( !ParseSelection( r, firstChannel, lastChannel ) )
13151 if ( m_status.IsInitializationEnabled() )
13152 m_status.Initialize(
"Computing percentage bend midvariance", N );
13157 data.
algorithm = PerformanceAnalysisAlgorithm::Sampling;
13162 L = OptimalThreadRows( r.
Height(), r.
Width(), maxProcessors, N/Thread::OptimalNumberOfThreads( data ) );
13164 bool useAffinity = m_parallel && Thread::IsRootThread();
13166 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
13167 threads.
Add(
new DSmpThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
13168 if ( threads.
Length() > 1 )
13171 for ( DSmpThread& thread : threads )
13172 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
13173 for ( DSmpThread& thread : threads )
13180 for ( DSmpThread& thread : threads )
13181 if ( thread.n > 0 )
13183 values.
Add( thread.values.Begin(), thread.values.At( thread.n ) );
13184 thread.values.Clear();
13237 double Sn(
const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
int maxProcessors = 0 )
const
13240 if ( !ParseSelection( r, firstChannel, lastChannel ) )
13244 if ( m_status.IsInitializationEnabled() )
13245 m_status.Initialize(
"Computing Sn scale estimate", N );
13250 data.
algorithm = PerformanceAnalysisAlgorithm::Sampling;
13255 L = OptimalThreadRows( r.
Height(), r.
Width(), maxProcessors, N/Thread::OptimalNumberOfThreads( data ) );
13257 bool useAffinity = m_parallel && Thread::IsRootThread();
13259 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
13260 threads.
Add(
new DSmpThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
13261 if ( threads.
Length() > 1 )
13264 for ( DSmpThread& thread : threads )
13265 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
13266 for ( DSmpThread& thread : threads )
13273 for ( DSmpThread& thread : threads )
13274 if ( thread.n > 0 )
13276 values.
Add( thread.values.Begin(), thread.values.At( thread.n ) );
13277 thread.values.Clear();
13329 double Qn(
const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
int maxProcessors = 0 )
const
13332 if ( !ParseSelection( r, firstChannel, lastChannel ) )
13336 if ( m_status.IsInitializationEnabled() )
13337 m_status.Initialize(
"Computing Qn scale estimate", N );
13342 data.
algorithm = PerformanceAnalysisAlgorithm::Sampling;
13347 L = OptimalThreadRows( r.
Height(), r.
Width(), maxProcessors, N/Thread::OptimalNumberOfThreads( data ) );
13349 bool useAffinity = m_parallel && Thread::IsRootThread();
13351 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
13352 threads.
Add(
new DSmpThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
13353 if ( threads.
Length() > 1 )
13356 for ( DSmpThread& thread : threads )
13357 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
13358 for ( DSmpThread& thread : threads )
13365 for ( DSmpThread& thread : threads )
13366 if ( thread.n > 0 )
13368 values.
Add( thread.values.Begin(), thread.values.At( thread.n ) );
13369 thread.values.Clear();
13416 double Norm(
const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
13417 int maxProcessors = 0 )
const
13420 if ( !ParseSelection( r, firstChannel, lastChannel ) )
13424 if ( m_status.IsInitializationEnabled() )
13425 m_status.Initialize(
"Computing norm", N );
13430 data.
algorithm = PerformanceAnalysisAlgorithm::Sum;
13435 L = OptimalThreadRows( r.
Height(), r.
Width(), maxProcessors, N/Thread::OptimalNumberOfThreads( data ) );
13437 bool useAffinity = m_parallel && Thread::IsRootThread();
13439 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
13440 threads.
Add(
new SumThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
13441 if ( threads.
Length() > 1 )
13444 for ( SumThread& thread : threads )
13445 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
13446 for ( SumThread& thread : threads )
13454 for (
const SumThread& thread : threads )
13456 double y = thread.s - e;
13464 return (1 + s != 1) ? s : 0.0;
13498 int maxProcessors = 0 )
const
13501 if ( !ParseSelection( r, firstChannel, lastChannel ) )
13505 if ( m_status.IsInitializationEnabled() )
13506 m_status.Initialize(
"Computing modulus", N );
13511 data.
algorithm = PerformanceAnalysisAlgorithm::Sum;
13516 L = OptimalThreadRows( r.
Height(), r.
Width(), maxProcessors, N/Thread::OptimalNumberOfThreads( data ) );
13518 bool useAffinity = m_parallel && Thread::IsRootThread();
13520 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
13521 threads.
Add(
new SumAbsThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
13522 if ( threads.
Length() > 1 )
13525 for ( SumAbsThread& thread : threads )
13526 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
13527 for ( SumAbsThread& thread : threads )
13535 for (
const SumAbsThread& thread : threads )
13537 double y = thread.s - e;
13545 return (1 + s != 1) ? s : 0.0;
13577 int maxProcessors = 0 )
const
13580 if ( !ParseSelection( r, firstChannel, lastChannel ) )
13584 if ( m_status.IsInitializationEnabled() )
13585 m_status.Initialize(
"Computing sum of squares", N );
13590 data.
algorithm = PerformanceAnalysisAlgorithm::Sum;
13595 L = OptimalThreadRows( r.
Height(), r.
Width(), maxProcessors, N/Thread::OptimalNumberOfThreads( data ) );
13597 bool useAffinity = m_parallel && Thread::IsRootThread();
13599 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
13600 threads.
Add(
new SumSqrThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
13601 if ( threads.
Length() > 1 )
13604 for ( SumSqrThread& thread : threads )
13605 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
13606 for ( SumSqrThread& thread : threads )
13614 for (
const SumSqrThread& thread : threads )
13616 double y = thread.s - e;
13624 return (1 + s != 1) ? s : 0.0;
13656 int maxProcessors = 0 )
const
13659 if ( !ParseSelection( r, firstChannel, lastChannel ) )
13663 if ( m_status.IsInitializationEnabled() )
13664 m_status.Initialize(
"Computing mean of squares", N );
13669 data.
algorithm = PerformanceAnalysisAlgorithm::Sum;
13674 L = OptimalThreadRows( r.
Height(), r.
Width(), maxProcessors, N/Thread::OptimalNumberOfThreads( data ) );
13676 bool useAffinity = m_parallel && Thread::IsRootThread();
13678 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
13679 threads.
Add(
new SumSqrThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
13680 if ( threads.
Length() > 1 )
13683 for ( SumSqrThread& thread : threads )
13684 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
13685 for ( SumSqrThread& thread : threads )
13694 for (
const SumSqrThread& thread : threads )
13696 double y = thread.s - e;
13750 int maxProcessors = 0 )
const
13752 PCL_PRECONDITION( maxDegree > 0 )
13753 maxDegree =
pcl::Max( 1, maxDegree );
13756 if ( !ParseSelection( r, firstChannel, lastChannel ) )
13760 if ( m_status.IsInitializationEnabled() )
13761 m_status.Initialize(
"Computing norms", N );
13766 data.
algorithm = PerformanceAnalysisAlgorithm::Sum;
13771 L = OptimalThreadRows( r.
Height(), r.
Width(), maxProcessors, N/Thread::OptimalNumberOfThreads( data ) );
13773 bool useAffinity = m_parallel && Thread::IsRootThread();
13775 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
13776 threads.
Add(
new NormThread( *
this, maxDegree, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
13777 if ( threads.
Length() > 1 )
13780 for ( NormThread& thread : threads )
13781 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
13782 for ( NormThread& thread : threads )
13788 Vector R( 0.0, maxDegree );
13789 Vector e( 0.0, maxDegree );
13790 for (
const NormThread& thread : threads )
13791 for (
int i = 0; i < maxDegree; ++i )
13793 double y = thread.R[i] - e[i];
13794 double t = R[i] + y;
13795 e[i] = (t - R[i]) - y;
13798 for (
int i = 0; i < maxDegree; ++i )
13799 if ( 1 + R[i] == 1 )
13821 if ( !ParseChannel( channel ) )
13823 return pcl::Hash64( m_channelData( channel ), ChannelSize(), seed );
13840 if ( !ParseChannel( channel ) )
13842 return pcl::Hash32( m_channelData( channel ), ChannelSize(), seed );
13851 return Hash64( channel, seed );
13876 if ( !ParseSelection( r, firstChannel, lastChannel ) )
13880 int numberOfChannels = 1 + lastChannel - firstChannel;
13882 if ( m_status.IsInitializationEnabled() )
13883 m_status.Initialize(
"Writing to raw-storage image stream", N*numberOfChannels );
13888 file.
WriteUI32( (firstChannel == 0 && lastChannel >= 2) ? m_colorSpace : ColorSpace::Gray );
13890 if ( r == Bounds() )
13892 for (
int i = firstChannel; i <= lastChannel; ++i, m_status += N )
13893 file.
Write( (
const void*)m_pixelData[i],
fsize_type( ChannelSize() ) );
13897 for (
int i = firstChannel, w = r.
Width(), h = r.
Height(); i <= lastChannel; ++i )
13900 for (
int j = 0; j < h; ++j, p += m_width, m_status += w )
13901 file.
Write( (
const void*)p, w*BytesPerSample() );
13919 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
const
13921 File file = File::CreateFileForWriting( filePath );
13922 return Write( file, rect, firstChannel, lastChannel );
13963 int width, height, numberOfChannels, colorSpace;
13966 file.
ReadUI32( numberOfChannels );
13969 AllocateData( width, height, numberOfChannels, color_space( colorSpace ) );
13976 if ( m_status.IsInitializationEnabled() )
13977 m_status.Initialize(
"Reading from raw-storage image stream", N*m_numberOfChannels );
13978 for (
int i = 0; i < m_numberOfChannels; ++i, m_status += N )
13979 file.
Read( (
void*)m_pixelData[i],
fsize_type( ChannelSize() ) );
13998 File file = File::OpenFileForReading( filePath );
13999 return Read( file );
14034 template <
typename T>
14037 if ( left == 0 && top == 0 && right == 0 && bottom == 0 )
14040 if ( m_width+left+right <= 0 || m_height+top+bottom <= 0 )
14046 Rect r( -left, -top, m_width+right, m_height+bottom );
14047 int width = r.
Width();
14048 int height = r.
Height();
14050 if ( !Intersects( r ) )
14051 return AllocateData( width, height, m_numberOfChannels, m_colorSpace ).Fill( fillValues );
14057 if ( m_status.IsInitializationEnabled() )
14058 m_status.Initialize(
String().Format(
"Crop margins: %+d, %+d, %+d, %+d",
14059 left, top, right, bottom ), N*m_numberOfChannels );
14061 sample** newData =
nullptr;
14065 newData = m_allocator.AllocateChannelSlots( m_numberOfChannels );
14067 for (
int c = 0; c < m_numberOfChannels; ++c, m_status += N )
14069 sample* __restrict__ f = newData[c] = m_allocator.AllocatePixels( N );
14070 sample v = (c < fillValues.
Length()) ? P::ToSample( fillValues[c] ) : P::MinSampleValue();
14072 for (
int i = r.
y0, j; i < r.
y1; )
14074 for ( ; i < 0; ++i )
14077 for (
int j = 0; j < width; ++j )
14082 for ( j = r.
x0; j < 0; ++j )
14085 for (
const sample* f0 = PixelAddress( j, i, c ); j < r.
x1; )
14088 if ( ++j == m_width )
14091 for ( ; j < r.
x1; ++j )
14096 if ( ++i == m_height )
14097 for ( ; i < r.
y1; ++i )
14100 for (
int j = 0; j < width; ++j )
14108 for (
int c = 0; c < m_numberOfChannels; ++c )
14110 m_allocator.Deallocate( m_pixelData[c] );
14111 m_pixelData[c] = newData[c];
14113 m_allocator.Deallocate( newData );
14116 m_allocator.SetSharedGeometry( m_width = width, m_height = height, m_numberOfChannels );
14124 m_data->Deallocate();
14131 if ( newData !=
nullptr )
14133 for (
int i = 0; i < m_numberOfChannels; ++i )
14134 if ( newData[i] !=
nullptr )
14135 m_allocator.Deallocate( newData[i] ), newData[i] =
nullptr;
14136 m_allocator.Deallocate( newData );
14155 return CropBy( left, top, right, bottom,
sample_vector() );
14168 template <
typename T>
14172 return CropBy( -r.
x0, -r.
y0, r.
x1 - m_width, r.
y1 - m_height, fillValues );
14201 template <
typename T>
14204 return CropTo(
Rect( x0, y0, x1, y1 ), fillValues );
14233 template <
typename T>
14236 return CropTo( m_rectangle, fillValues );
14276 template <
typename T>
14279 return CropBy( dx, dy, -dx, -dy, fillValues );
14304 template <
typename T>
14307 return ShiftBy( x, y, fillValues );
14336 template <
typename T>
14339 return ShiftBy( p.
x, p.
y, fillValues );
14362 template <
typename T>
14365 int dx2 = (width - m_width) >> 1;
14366 int dy2 = (height - m_height) >> 1;
14367 return CropBy( dx2, dy2, width-m_width-dx2, height-m_height-dy2, fillValues );
14391 template <
typename T>
14394 int dx = width - m_width;
14395 int dy = height - m_height;
14396 return CropBy( 0, 0, dx, dy, fillValues );
14420 template <
typename T>
14423 int dx = width - m_width;
14424 int dy = height - m_height;
14425 return CropBy( dx, 0, 0, dy, fillValues );
14449 template <
typename T>
14452 int dx = width - m_width;
14453 int dy = height - m_height;
14454 return CropBy( 0, dy, dx, 0, fillValues );
14471 return ShiftToBottomLeft( width, height,
sample_vector() );
14478 template <
typename T>
14481 int dx = width - m_width;
14482 int dy = height - m_height;
14483 return CropBy( dx, dy, 0, 0, fillValues );
14500 return ShiftToBottomRight( width, height,
sample_vector() );
14513 template <
typename T>
14516 return ShiftTo( m_point, fillValues );
14576 if ( colorSpace == m_colorSpace )
14584 if ( m_status.IsInitializationEnabled() )
14585 m_status.Initialize(
"In-place color space conversion: "
14590 int n = m_numberOfChannels;
14592 if ( m_colorSpace == ColorSpace::Gray )
14594 sample** oldData = m_pixelData;
14595 sample** newData =
nullptr;
14600 newData = m_allocator.AllocateChannelSlots( 2+n );
14603 newData[0] = oldData[0];
14606 newData[1] = m_allocator.AllocatePixels( N );
14607 ::memcpy( newData[1], oldData[0], ChannelSize() );
14608 newData[2] = m_allocator.AllocatePixels( N );
14609 ::memcpy( newData[2], oldData[0], ChannelSize() );
14612 for (
int i = 1; i < n; ++i )
14613 newData[i+2] = oldData[i];
14617 m_pixelData = newData;
14619 m_numberOfChannels += 2;
14620 m_colorSpace = ColorSpace::RGB;
14621 m_data->UpdateSharedImage();
14623 ResetChannelRange();
14625 m_allocator.Deallocate( oldData );
14629 m_data->Deallocate();
14636 if ( newData !=
nullptr )
14638 newData[0] =
nullptr;
14639 if ( newData[1] !=
nullptr )
14640 m_allocator.Deallocate( newData[1] ), newData[1] =
nullptr;
14641 if ( newData[2] !=
nullptr )
14642 m_allocator.Deallocate( newData[2] ), newData[2] =
nullptr;
14643 m_allocator.Deallocate( newData );
14648 if ( colorSpace == ColorSpace::RGB )
14658 if ( likely( !__performanceAnalysis__ ) )
14661 data.
algorithm = PerformanceAnalysisAlgorithm::ColorSpaceConversion;
14666 L = Thread::OptimalThreadLoads( N, N/Thread::OptimalNumberOfThreads( data ),
14667 m_parallel ? ((maxProcessors > 0) ? maxProcessors : m_maxProcessors) : 1 );
14670 L = Thread::OptimalThreadLoads( N, 1, maxProcessors );
14674 for (
size_type i = 0, n = 0; i < L.Length(); n += L[i++] )
14675 threads.
Add(
new ColorSpaceConversionThread( *
this, data, colorSpace, n, n + L[i] ) );
14676 RunThreads( threads, data );
14681 if ( colorSpace == ColorSpace::Gray )
14683 sample** oldData = m_pixelData;
14684 sample** newData =
nullptr;
14688 newData = m_allocator.AllocateChannelSlots( n-2 );
14689 newData[0] = oldData[0];
14690 for (
int i = 3; i < n; ++i )
14691 newData[i-2] = oldData[i];
14693 m_pixelData = newData;
14695 m_numberOfChannels -= 2;
14696 m_colorSpace = ColorSpace::Gray;
14697 m_data->UpdateSharedImage();
14699 ResetChannelRange();
14701 m_allocator.Deallocate( oldData[1] );
14702 m_allocator.Deallocate( oldData[2] );
14703 m_allocator.Deallocate( oldData );
14707 m_data->Deallocate();
14709 if ( newData !=
nullptr )
14710 m_allocator.Deallocate( newData );
14716 m_allocator.SetSharedColor( m_colorSpace = colorSpace, m_RGBWS );
14789 template <
class P1>
14793 if ( !ParseRect( r ) )
14799 Y.AllocateData( r );
14800 if ( !Y.IsShared() )
14801 Y.SetRGBWorkingSpace( m_RGBWS );
14805 if ( m_colorSpace == ColorSpace::Gray || m_colorSpace == ColorSpace::CIEXYZ )
14807 if ( m_status.IsInitializationEnabled() )
14808 m_status.Initialize(
"Transferring pixel data", N );
14811 int cY = (m_colorSpace == ColorSpace::Gray) ? 0 : 1;
14812 if ( r == Bounds() )
14814 const sample* __restrict__ f = m_pixelData[cY];
14815 P1::Copy( g, f, N );
14819 const sample* __restrict__ f = PixelAddress( r.
LeftTop(), cY );
14820 for (
int i = 0; i < Y.Height(); ++i, f += m_width, g += Y.Width() )
14821 P1::Copy( g, f, Y.Width() );
14828 if ( m_status.IsInitializationEnabled() )
14829 m_status.Initialize(
"Computing CIE Y component", N );
14834 data.
algorithm = PerformanceAnalysisAlgorithm::GetLightness;
14839 L = OptimalThreadRows( Y.Height(), Y.Width(), maxProcessors, N/Thread::OptimalNumberOfThreads( data ) );
14843 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
14844 threads.
Add(
new GetLuminanceThread<P1>( Y, *
this, data, r, n, n +
int( L[i] ) ) );
14845 RunThreads( threads, data );
14861 void GetLuminance(
ImageVariant& Y,
const Rect& rect =
Rect( 0 ),
int maxProcessors = 0 )
const;
14930 template <
class P1>
14932 bool __performanceAnalysis__ =
false )
const
14935 if ( !ParseRect( r ) )
14941 L.AllocateData( r );
14942 if ( !L.IsShared() )
14943 L.SetRGBWorkingSpace( m_RGBWS );
14947 if ( m_colorSpace == ColorSpace::Gray || m_colorSpace == ColorSpace::CIELab || m_colorSpace == ColorSpace::CIELch )
14949 if ( m_status.IsInitializationEnabled() )
14950 m_status.Initialize(
"Transferring pixel data", N );
14953 if ( r == Bounds() )
14955 const sample* __restrict__ f = *m_pixelData;
14956 P1::Copy( g, f, N );
14960 const sample* __restrict__ f = PixelAddress( r.
LeftTop() );
14961 for (
int i = 0; i < L.Height(); ++i, f += m_width, g += L.Width() )
14962 P1::Copy( g, f, L.Width() );
14969 if ( m_status.IsInitializationEnabled() )
14970 m_status.Initialize(
"Computing CIE L* component", N );
14973 if ( likely( !__performanceAnalysis__ ) )
14976 data.
algorithm = PerformanceAnalysisAlgorithm::GetLightness;
14981 R = OptimalThreadRows( L.Height(), L.Width(), maxProcessors, N/Thread::OptimalNumberOfThreads( data ) );
14984 R = OptimalThreadRows( L.Height(), L.Width(), maxProcessors, 1 );
14988 for (
int i = 0, n = 0; i < int( R.Length() ); n += int( R[i++] ) )
14989 threads.
Add(
new GetLightnessThread<P1>( L, *
this, data, r, n, n +
int( R[i] ) ) );
14990 RunThreads( threads, data );
15006 void GetLightness(
ImageVariant& L,
const Rect& rect =
Rect( 0 ),
int maxProcessors = 0 )
const;
15067 template <
class P1>
15069 bool __performanceAnalysis__ =
false )
const
15072 if ( !ParseRect( r ) )
15078 I.AllocateData( r );
15079 if ( !I.IsShared() )
15080 I.SetRGBWorkingSpace( m_RGBWS );
15084 if ( m_colorSpace == ColorSpace::Gray || m_colorSpace == ColorSpace::HSI )
15086 if ( m_status.IsInitializationEnabled() )
15087 m_status.Initialize(
"Transferring pixel data", N );
15090 int cI = (m_colorSpace == ColorSpace::Gray) ? 0 : 2;
15091 if ( r == Bounds() )
15093 const sample* __restrict__ f = m_pixelData[cI];
15094 P1::Copy( g, f, N );
15098 const sample* __restrict__ f = PixelAddress( r.
LeftTop(), cI );
15099 for (
int i = 0; i < I.Height(); ++i, f += m_width, g += I.Width() )
15100 P1::Copy( g, f, I.Width() );
15107 if ( m_status.IsInitializationEnabled() )
15108 m_status.Initialize(
"Computing intensity component", N );
15111 if ( likely( !__performanceAnalysis__ ) )
15114 data.
algorithm = PerformanceAnalysisAlgorithm::GetIntensity;
15119 L = OptimalThreadRows( I.Height(), I.Width(), maxProcessors, N/Thread::OptimalNumberOfThreads( data ) );
15122 L = OptimalThreadRows( I.Height(), I.Width(), maxProcessors, 1 );
15126 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
15127 threads.
Add(
new GetIntensityThread<P1>( I, *
this, data, r, n, n +
int( L[i] ) ) );
15128 RunThreads( threads, data );
15144 void GetIntensity(
ImageVariant& I,
const Rect& rect =
Rect( 0 ),
int maxProcessors = 0 )
const;
15207 template <
class P1>
15210 int maxProcessors = 0 )
15213 if ( !Y.ParseRect( r ) )
15217 if ( p.
x == int_max || p.
y == int_max )
15222 if ( (r.
x0 -= p.
x) >= r.
x1 )
15226 else if ( p.
x >= m_width )
15231 if ( (r.
y0 -= p.
y) >= r.
y1 )
15235 else if ( p.
y >= m_height )
15245 if ( m_colorSpace == ColorSpace::Gray &&
15246 (Y.ColorSpace() == ColorSpace::Gray || Y.ColorSpace() == ColorSpace::CIEXYZ) )
15248 if ( m_status.IsInitializationEnabled() )
15249 m_status.Initialize(
"Transferring pixel data", N );
15251 int c0 = (Y.ColorSpace() == ColorSpace::Gray) ? 0 : 1;
15253 sample* __restrict__ f = PixelAddress( p );
15254 for (
int i = 0, w = r.
Width(), h = r.
Height(); i < h; ++i, f += m_width, g += Y.Width(), m_status += w )
15255 P::Copy( f, g, w );
15259 if ( m_status.IsInitializationEnabled() )
15260 m_status.Initialize(
"Importing CIE Y component", N );
15265 data.
algorithm = PerformanceAnalysisAlgorithm::GetLightness;
15270 L = OptimalThreadRows( r.
Height(), r.
Width(), maxProcessors, N/Thread::OptimalNumberOfThreads( data ) );
15274 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
15275 threads.
Add(
new SetLuminanceThread<P1>( *
this, Y, data, p, r, n, n +
int( L[i] ) ) );
15276 RunThreads( threads, data );
15296 int maxProcessors = 0 );
15357 template <
class P1>
15360 int maxProcessors = 0 )
15363 if ( !L.ParseRect( r ) )
15367 if ( p.
x == int_max || p.
y == int_max )
15372 if ( (r.
x0 -= p.
x) >= r.
x1 )
15376 else if ( p.
x >= m_width )
15381 if ( (r.
y0 -= p.
y) >= r.
y1 )
15385 else if ( p.
y >= m_height )
15395 if ( m_colorSpace == ColorSpace::Gray &&
15396 (L.ColorSpace() == ColorSpace::Gray ||
15397 L.ColorSpace() == ColorSpace::CIELab || L.ColorSpace() == ColorSpace::CIELch) )
15399 if ( m_status.IsInitializationEnabled() )
15400 m_status.Initialize(
"Transferring pixel data", N );
15403 sample* __restrict__ f = PixelAddress( p );
15404 for (
int i = 0, w = r.
Width(), h = r.
Height(); i < h; ++i, f += m_width, g += L.Width(), m_status += w )
15405 P::Copy( f, g, w );
15409 if ( m_status.IsInitializationEnabled() )
15410 m_status.Initialize(
"Importing CIE L* component", N );
15415 data.
algorithm = PerformanceAnalysisAlgorithm::GetLightness;
15420 R = OptimalThreadRows( r.
Height(), r.
Width(), maxProcessors, N/Thread::OptimalNumberOfThreads( data ) );
15424 for (
int i = 0, n = 0; i < int( R.Length() ); n += int( R[i++] ) )
15425 threads.
Add(
new SetLightnessThread<P1>( *
this, L, data, p, r, n, n +
int( R[i] ) ) );
15426 RunThreads( threads, data );
15446 int maxProcessors = 0 );
15488 const Rect& rect =
Rect( 0 ),
int channel = -1,
15492 if ( !ParseSelection( r, channel ) )
15494 if ( r == Bounds() )
15495 return compressor.
Compress( m_channelData( channel ), ChannelSize(), perf );
15518 sample** data =
nullptr;
15530 pixel_allocator allocator;
15547 LinkWithClientImage( image );
15553 Data( GenericImage* image,
void* handle )
15554 : allocator( handle )
15556 SynchronizeWithSharedImage();
15557 LinkWithClientImage( image );
15563 Data( GenericImage* image,
int width,
int height,
int numberOfChannels,
int colorSpace )
15564 : allocator( width, height, numberOfChannels, colorSpace )
15566 SynchronizeWithSharedImage();
15567 LinkWithClientImage( image );
15570 void Attach( GenericImage* image )
15572 ReferenceCounter::Attach();
15573 LinkWithClientImage( image );
15584 bool IsShared() const noexcept
15586 return allocator.IsShared();
15589 bool IsEmpty() const noexcept
15591 return data ==
nullptr;
15594 void Allocate(
int width,
int height,
int numberOfChannels, color_space colorSpace )
15596 if ( width <= 0 || height <= 0 || numberOfChannels <= 0 )
15603 throw Error(
"GenericImage::Data::Allocate(): Insufficient number of channels" );
15605 if ( data !=
nullptr )
15609 if ( numberOfChannels != geometry.numberOfChannels )
15611 sample** newData =
nullptr;
15612 int m =
pcl::Min( geometry.numberOfChannels, numberOfChannels );
15616 newData = allocator.AllocateChannelSlots( numberOfChannels );
15617 for (
int i = 0; i < m; ++i )
15618 newData[i] = data[i];
15619 for (
int i = m; i < numberOfChannels; ++i )
15620 newData[i] = allocator.AllocatePixels( width, height );
15624 for (
int i = m; i < geometry.numberOfChannels; ++i )
15625 if ( data[i] !=
nullptr )
15626 allocator.Deallocate( data[i] ), data[i] =
nullptr;
15627 allocator.Deallocate( data );
15639 if ( newData !=
nullptr )
15641 for (
int i = m; i < numberOfChannels; ++i )
15642 if ( newData[i] !=
nullptr )
15643 allocator.Deallocate( newData[i] ), newData[i] =
nullptr;
15644 allocator.Deallocate( newData );
15652 sample** newData =
nullptr;
15656 newData = allocator.AllocateChannelSlots( numberOfChannels );
15657 for (
int i = 0; i < numberOfChannels; ++i )
15658 newData[i] = allocator.AllocatePixels( width, height );
15662 for (
int i = 0; i < geometry.numberOfChannels; ++i )
15663 if ( data[i] !=
nullptr )
15664 allocator.Deallocate( data[i] ), data[i] =
nullptr;
15665 allocator.Deallocate( data );
15677 if ( newData !=
nullptr )
15679 for (
int i = 0; i < numberOfChannels; ++i )
15680 if ( newData[i] !=
nullptr )
15681 allocator.Deallocate( newData[i] ), newData[i] =
nullptr;
15682 allocator.Deallocate( newData );
15692 data = allocator.AllocateChannelSlots( numberOfChannels );
15693 for (
int i = 0; i < numberOfChannels; ++i )
15694 data[i] = allocator.AllocatePixels( width, height );
15698 if ( data !=
nullptr )
15700 for (
int i = 0; i < numberOfChannels; ++i )
15701 if ( data[i] !=
nullptr )
15702 allocator.Deallocate( data[i] ), data[i] =
nullptr;
15703 allocator.Deallocate( data );
15710 geometry.width = width;
15711 geometry.height = height;
15712 geometry.numberOfChannels = numberOfChannels;
15714 color.colorSpace = colorSpace;
15716 UpdateSharedImage();
15719 void Import( sample** newData,
int width,
int height,
int numberOfChannels, color_space colorSpace )
15721 if ( newData != data )
15725 if ( newData !=
nullptr && width > 0 && height > 0 && numberOfChannels > 0 )
15728 throw Error(
"GenericImage::Data::Import(): Insufficient number of channels" );
15732 geometry.width = width;
15733 geometry.height = height;
15734 geometry.numberOfChannels = numberOfChannels;
15736 color.colorSpace = colorSpace;
15738 UpdateSharedImage();
15745 sample** oldData = data;
15747 UpdateSharedImage();
15753 if ( data !=
nullptr )
15755 for (
int i = 0; i < geometry.numberOfChannels; ++i )
15756 if ( data[i] !=
nullptr )
15757 allocator.Deallocate( data[i] ), data[i] =
nullptr;
15758 allocator.Deallocate( data );
15760 UpdateSharedImage();
15764 Data* Clone( GenericImage* image )
const
15766 Data* clone =
nullptr;
15773 clone->data = clone->allocator.AllocateChannelSlots( geometry.numberOfChannels );
15774 for (
int i = 0; i < geometry.numberOfChannels; ++i )
15776 clone->data[i] = clone->allocator.AllocatePixels( geometry.width, geometry.height );
15777 P::Copy( clone->data[i], data[i], geometry.NumberOfPixels() );
15780 clone->geometry.Assign( geometry );
15781 clone->color.Assign( color );
15784 clone->LinkWithClientImage( image );
15789 if ( clone !=
nullptr )
15791 clone->Deallocate();
15805 void UpdateSharedImage()
15807 allocator.SetSharedData( data );
15808 allocator.SetSharedGeometry( geometry.width, geometry.height, geometry.numberOfChannels );
15809 allocator.SetSharedColor( color.colorSpace, color.RGBWS );
15812 void SynchronizeWithSharedImage()
15814 data = allocator.GetSharedData();
15815 allocator.GetSharedGeometry( geometry.width, geometry.height, geometry.numberOfChannels );
15816 allocator.GetSharedColor( color.colorSpace, color.RGBWS );
15823 void LinkWithClientImage( GenericImage* image )
15825 if ( image !=
nullptr )
15827 image->m_geometry = &geometry;
15828 image->m_color = &color;
15837 Data* m_data =
nullptr;
15843 void DetachFromData()
15845 if ( !m_data->Detach() )
15851 class RectThreadBase :
public Thread
15855 RectThreadBase(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
15860 , m_firstRow( firstRow )
15861 , m_endRow( endRow )
15865 virtual void Run() = 0;
15869 const GenericImage& m_image;
15870 const Rect& m_rect;
15872 int m_firstRow, m_endRow;
15874 bool HasSimpleSelection()
const
15876 return m_rect.Width() == m_image.Width()
15877 && !m_image.IsLowRangeClippingEnabled()
15878 && !m_image.IsHighRangeClippingEnabled();
15881 template <
class F>
void Execute( F process ) noexcept
15883 int w = m_rect.Width();
15884 int dw = m_image.Width() - w;
15890 if ( m_image.IsLowRangeClippingEnabled() )
15892 sample clipLow = P::ToSample( m_image.RangeClipLow() );
15893 if ( m_image.IsHighRangeClippingEnabled() )
15895 sample clipHigh = P::ToSample( m_image.RangeClipHigh() );
15896 for (
int i = m_ch1; i <= m_ch2; ++i )
15898 const sample* __restrict__ f = m_image.PixelAddress( 0, m_rect.y0+m_firstRow, i );
15900 for (
size_type j = 0; j < n; ++j, ++f )
15901 if ( clipLow < *f )
15902 if ( *f < clipHigh )
15908 for (
int i = m_ch1; i <= m_ch2; ++i )
15910 const sample* __restrict__ f = m_image.PixelAddress( 0, m_rect.y0+m_firstRow, i );
15912 for (
size_type j = 0; j < n; ++j, ++f )
15913 if ( clipLow < *f )
15918 else if ( m_image.IsHighRangeClippingEnabled() )
15920 sample clipHigh = P::ToSample( m_image.RangeClipHigh() );
15921 for (
int i = m_ch1; i <= m_ch2; ++i )
15923 const sample* __restrict__ f = m_image.PixelAddress( 0, m_rect.y0+m_firstRow, i );
15925 for (
size_type j = 0; j < n; ++j, ++f )
15926 if ( *f < clipHigh )
15933 for (
int i = m_ch1; i <= m_ch2; ++i )
15935 const sample* __restrict__ f = m_image.PixelAddress( 0, m_rect.y0+m_firstRow, i );
15937 for (
size_type j = 0; j < n; ++j, ++f )
15944 if ( m_image.IsLowRangeClippingEnabled() )
15946 sample clipLow = P::ToSample( m_image.RangeClipLow() );
15947 if ( m_image.IsHighRangeClippingEnabled() )
15949 sample clipHigh = P::ToSample( m_image.RangeClipHigh() );
15950 for (
int i = m_ch1; i <= m_ch2; ++i )
15952 const sample* __restrict__ f = m_image.PixelAddress( m_rect.x0, m_rect.y0+m_firstRow, i );
15953 for (
int j = m_firstRow; j < m_endRow; ++j, f += dw )
15956 for (
int k = 0; k < w; ++k, ++f )
15957 if ( clipLow < *f )
15958 if ( *f < clipHigh )
15965 for (
int i = m_ch1; i <= m_ch2; ++i )
15967 const sample* __restrict__ f = m_image.PixelAddress( m_rect.x0, m_rect.y0+m_firstRow, i );
15968 for (
int j = m_firstRow; j < m_endRow; ++j, f += dw )
15971 for (
int k = 0; k < w; ++k, ++f )
15972 if ( clipLow < *f )
15978 else if ( m_image.IsHighRangeClippingEnabled() )
15980 sample clipHigh = P::ToSample( m_image.RangeClipHigh() );
15981 for (
int i = m_ch1; i <= m_ch2; ++i )
15983 const sample* __restrict__ f = m_image.PixelAddress( m_rect.x0, m_rect.y0+m_firstRow, i );
15984 for (
int j = m_firstRow; j < m_endRow; ++j, f += dw )
15987 for (
int k = 0; k < w; ++k, ++f )
15988 if ( *f < clipHigh )
15995 for (
int i = m_ch1; i <= m_ch2; ++i )
15997 const sample* __restrict__ f = m_image.PixelAddress( m_rect.x0, m_rect.y0+m_firstRow, i );
15998 for (
int j = m_firstRow; j < m_endRow; ++j, f += dw )
16001 for (
int k = 0; k < w; ++k, ++f )
16012 class CountThread :
public RectThreadBase
16018 CountThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
16019 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
16028 int w = this->m_rect.Width();
16029 int dw = this->m_image.Width() - w;
16031 if ( this->m_image.IsLowRangeClippingEnabled() )
16033 sample clipLow = P::ToSample( this->m_image.RangeClipLow() );
16034 if ( this->m_image.IsHighRangeClippingEnabled() )
16036 sample clipHigh = P::ToSample( this->m_image.RangeClipHigh() );
16037 for (
int i = this->m_ch1; i <= this->m_ch2; ++i )
16039 const sample* __restrict__ f = this->m_image.PixelAddress( this->m_rect.x0, this->m_rect.y0+this->m_firstRow, i );
16040 for (
int j = this->m_firstRow; j < this->m_endRow; ++j, f += dw )
16043 for (
int k = 0; k < w; ++k, ++f )
16044 if ( clipLow < *f )
16045 if ( *f < clipHigh )
16052 for (
int i = this->m_ch1; i <= this->m_ch2; ++i )
16054 const sample* __restrict__ f = this->m_image.PixelAddress( this->m_rect.x0, this->m_rect.y0+this->m_firstRow, i );
16055 for (
int j = this->m_firstRow; j < this->m_endRow; ++j, f += dw )
16058 for (
int k = 0; k < w; ++k, ++f )
16059 if ( clipLow < *f )
16065 else if ( this->m_image.IsHighRangeClippingEnabled() )
16067 sample clipHigh = P::ToSample( this->m_image.RangeClipHigh() );
16068 for (
int i = this->m_ch1; i <= this->m_ch2; ++i )
16070 const sample* __restrict__ f = this->m_image.PixelAddress( this->m_rect.x0, this->m_rect.y0+this->m_firstRow, i );
16071 for (
int j = this->m_firstRow; j < this->m_endRow; ++j, f += dw )
16074 for (
int k = 0; k < w; ++k, ++f )
16075 if ( *f < clipHigh )
16087 class MinThread :
public RectThreadBase
16094 MinThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
16095 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
16101 min = P::HighestSampleValue();
16103 this->Execute( [=](
const sample* __restrict__ f )
16114 class MaxThread :
public RectThreadBase
16121 MaxThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
16122 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
16128 max = P::LowestSampleValue();
16130 this->Execute( [=](
const sample* __restrict__ f )
16141 class MinMaxThread :
public RectThreadBase
16149 MinMaxThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
16150 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
16156 min = P::HighestSampleValue();
16157 max = P::LowestSampleValue();
16159 this->Execute( [=](
const sample* __restrict__ f )
16172 class ExtremePosThreadBase :
public RectThreadBase
16180 ExtremePosThreadBase(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
16181 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
16188 m_amin = m_amax =
nullptr;
16193 if ( m_amin !=
nullptr )
16194 for (
int i = this->m_ch1; i <= this->m_ch2; ++i )
16195 if ( m_amin >= this->m_image[i] && m_amin < (this->m_image[i] + this->m_image.NumberOfPixels()) )
16198 pmin.x = (m_amin - this->m_image[i]) % this->m_image.Width();
16199 pmin.y = (m_amin - this->m_image[i]) / this->m_image.Width();
16202 if ( m_amax !=
nullptr )
16203 for (
int i = this->m_ch1; i <= this->m_ch2; ++i )
16204 if ( m_amax >= this->m_image[i] && m_amax < (this->m_image[i] + this->m_image.NumberOfPixels()) )
16207 pmax.x = (m_amax - this->m_image[i]) % this->m_image.Width();
16208 pmax.y = (m_amax - this->m_image[i]) / this->m_image.Width();
16216 const sample* m_amin;
16217 const sample* m_amax;
16219 virtual void DoExecute() = 0;
16224 class MinPosThread :
public ExtremePosThreadBase
16230 MinPosThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
16231 : ExtremePosThreadBase( image, rect, ch1, ch2, firstRow, endRow )
16237 void DoExecute()
override
16239 min = P::HighestSampleValue();
16240 this->Execute( [=](
const sample* __restrict__ f )
16243 min = *(this->m_amin = f);
16251 class MaxPosThread :
public ExtremePosThreadBase
16257 MaxPosThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
16258 : ExtremePosThreadBase( image, rect, ch1, ch2, firstRow, endRow )
16264 void DoExecute()
override
16266 max = P::LowestSampleValue();
16267 this->Execute( [=](
const sample* __restrict__ f )
16270 max = *(this->m_amax = f);
16278 class MinMaxPosThread :
public ExtremePosThreadBase
16284 MinMaxPosThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
16285 : ExtremePosThreadBase( image, rect, ch1, ch2, firstRow, endRow )
16291 void DoExecute()
override
16293 min = P::HighestSampleValue();
16294 max = P::LowestSampleValue();
16295 this->Execute( [=](
const sample* __restrict__ f )
16298 min = *(this->m_amin = f);
16300 max = *(this->m_amax = f);
16308 class SumThread :
public RectThreadBase
16315 SumThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
16316 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
16331 void SumStep(
double x ) noexcept
16340 virtual void DoExecute()
16342 this->Execute( [=](
const sample* __restrict__ f )
16344 double v; P::FromSample( v, *f );
16352 class SumSqrThread :
public SumThread
16356 SumSqrThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
16357 : SumThread( image, rect, ch1, ch2, firstRow, endRow )
16363 void DoExecute()
override
16365 this->Execute( [=](
const sample* __restrict__ f )
16367 double v; P::FromSample( v, *f );
16368 this->SumStep( v*v );
16375 class SumAbsThread :
public SumThread
16379 SumAbsThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
16380 : SumThread( image, rect, ch1, ch2, firstRow, endRow )
16386 void DoExecute()
override
16388 this->Execute( [=](
const sample* __restrict__ f )
16390 double v; P::FromSample( v, *f );
16398 class NormThread :
public RectThreadBase
16405 NormThread(
const GenericImage& image,
int degree,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
16406 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
16416 this->Execute( [=](
const sample* __restrict__ f )
16418 double v; P::FromSample( v, *f );
16419 for (
int i = 0;; )
16422 if ( ++i == R.Length() )
16434 void NormStep(
int i,
double x ) noexcept
16436 double y = x - e[i];
16437 double t = R[i] + y;
16438 e[i] = (t - R[i]) - y;
16445 class HistogramThread :
public RectThreadBase
16451 HistogramThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow,
16452 const double& low,
const double& high )
16453 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
16454 , H( __PCL_MEDIAN_HISTOGRAM_LENGTH )
16464 if ( this->HasSimpleSelection() )
16467 for (
int i = this->m_ch1; i <= this->m_ch2; ++i )
16468 Build( H, this->m_image.PixelAddress( 0, this->m_rect.y0+this->m_firstRow, i ), n, m_low, m_high );
16472 m_range = m_high - m_low;
16473 if ( 1 + m_range != 1 )
16475 const double scale = (__PCL_MEDIAN_HISTOGRAM_LENGTH - 1)/m_range;
16476 this->Execute( [=](
const sample* __restrict__ f )
16478 const int k =
TruncInt( scale*(*f - m_low) );
16479 if ( k >= 0 && k < __PCL_MEDIAN_HISTOGRAM_LENGTH )
16488 const double& m_low;
16489 const double& m_high;
16492 template <
typename T1>
16493 static void Build(
SzVector& H,
const T1* __restrict__ A,
size_type N,
double low,
double high )
16495 const double range = high - low;
16496 if ( 1 + range != 1 )
16498 const double scale = (__PCL_MEDIAN_HISTOGRAM_LENGTH - 1)/range;
16502 const int k =
TruncInt( scale*(A[i] - low) );
16503 if ( k >= 0 && k < __PCL_MEDIAN_HISTOGRAM_LENGTH )
16512 static void Build(
SzVector& H,
const float* __restrict__ A,
size_type N,
double low,
double high )
16514 const double range = high - low;
16515 if ( 1 + range == 1 )
16518 const float s = float( (__PCL_MEDIAN_HISTOGRAM_LENGTH - 1)/range );
16519 const float l = float( low );
16520 const __m256 S = _mm256_set1_ps( s );
16521 const __m256 L = _mm256_set1_ps( l );
16522 const size_type stepLength = 0x40000000u;
16524 for (
size_type p = 0; p < N; p += stepLength )
16526 const float* __restrict__ V = A + p;
16527 const int n = int(
pcl::Min( stepLength, N - p ) );
16528 const int n8 = n >> 3;
16530 if ( ((ptrdiff_t)V) & 31 )
16531 for (
int i = 0; i < n8; ++i )
16533 __m256 v = _mm256_loadu_ps( (
const float* __restrict__)(V + i*8) );
16534 __m256i K = _mm256_cvttps_epi32( _mm256_mul_ps( _mm256_sub_ps( v, L ), S ) );
16535 for (
int j = 0; j < 8; ++j )
16537 const int k = ((
const int* __restrict__)&K)[j];
16538 if ( k >= 0 && k < __PCL_MEDIAN_HISTOGRAM_LENGTH )
16543 for (
int i = 0; i < n8; ++i )
16545 __m256i K = _mm256_cvttps_epi32( _mm256_mul_ps( _mm256_sub_ps( ((
const __m256* __restrict__)V)[i], L ), S ) );
16546 for (
int j = 0; j < 8; ++j )
16548 const int k = ((
const int* __restrict__)&K)[j];
16549 if ( k >= 0 && k < __PCL_MEDIAN_HISTOGRAM_LENGTH )
16554 for (
int i = n8 << 3; i < n; ++i )
16556 const int k =
TruncInt( s * (V[i] - l) );
16557 if ( k >= 0 && k < __PCL_MEDIAN_HISTOGRAM_LENGTH )
16564 static void Build(
SzVector& H,
const double* __restrict__ A,
size_type N,
double low,
double high )
16566 const double range = high - low;
16567 if ( 1 + range == 1 )
16570 const double s = (__PCL_MEDIAN_HISTOGRAM_LENGTH - 1)/range;
16571 const __m256d S = _mm256_set1_pd( s );
16572 const __m256d L = _mm256_set1_pd( low );
16573 const size_type stepLength = 0x40000000u;
16575 for (
size_type p = 0; p < N; p += stepLength )
16577 const double* __restrict__ V = A + p;
16578 const int n = int(
pcl::Min( stepLength, N - p ) );
16579 const int n4 = n >> 2;
16581 if ( ((ptrdiff_t)V) & 31 )
16582 for (
int i = 0; i < n4; ++i )
16584 __m256d v = _mm256_loadu_pd( (
const double* __restrict__)(V + i*4) );
16585 __m128i K = _mm256_cvttpd_epi32( _mm256_mul_pd( _mm256_sub_pd( v, L ), S ) );
16586 for (
int j = 0; j < 4; ++j )
16588 const int k = ((
const int* __restrict__)&K)[j];
16589 if ( k >= 0 && k < __PCL_MEDIAN_HISTOGRAM_LENGTH )
16594 for (
int i = 0; i < n4; ++i )
16596 __m128i K = _mm256_cvttpd_epi32( _mm256_mul_pd( _mm256_sub_pd( ((
const __m256d* __restrict__)V)[i], L ), S ) );
16597 for (
int j = 0; j < 4; ++j )
16599 const int k = ((
const int* __restrict__)&K)[j];
16600 if ( k >= 0 && k < __PCL_MEDIAN_HISTOGRAM_LENGTH )
16605 for (
int i = n4 << 2; i < n; ++i )
16607 const int k =
TruncInt( s * (V[i] - low) );
16608 if ( k >= 0 && k < __PCL_MEDIAN_HISTOGRAM_LENGTH )
16619 class ExtremeAbsDevThread :
public RectThreadBase
16623 double minAbsDev = 0, maxAbsDev = 0;
16626 ExtremeAbsDevThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow,
double center )
16627 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
16628 , m_center( center )
16634 minAbsDev = std::numeric_limits<double>::max();
16637 this->Execute( [=](
const sample* __restrict__ f )
16639 double d; P::FromSample( d, *f );
16641 if ( d < minAbsDev )
16643 if ( d > maxAbsDev )
16656 class TwoSidedExtremeAbsDevThread :
public RectThreadBase
16660 double minAbsDevLow = 0, minAbsDevHigh = 0;
16661 double maxAbsDevLow = 0, maxAbsDevHigh = 0;
16664 TwoSidedExtremeAbsDevThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow,
double center )
16665 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
16666 , m_center( center )
16672 minAbsDevLow = minAbsDevHigh = std::numeric_limits<double>::max();
16673 maxAbsDevLow = maxAbsDevHigh = 0;
16675 this->Execute( [=](
const sample* __restrict__ f )
16677 double x; P::FromSample( x, *f );
16678 if ( x <= m_center )
16680 double d = m_center - x;
16681 if ( d < minAbsDevLow )
16683 if ( d > maxAbsDevLow )
16689 double d = x - m_center;
16690 if ( d < minAbsDevHigh )
16692 if ( d > maxAbsDevHigh )
16706 class AbsDevHistogramThread :
public RectThreadBase
16712 AbsDevHistogramThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow,
16713 double center,
const double& low,
const double& high )
16714 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
16715 , H( __PCL_MEDIAN_HISTOGRAM_LENGTH )
16716 , m_center( center )
16725 m_range = m_high - m_low;
16728 #ifdef __PCL_MACOSX
16729 if ( 1 + m_range != 1 )
16731 this->Execute( [=](
const sample* __restrict__ f )
16733 double d; P::FromSample( d, *f );
16737 ++H[
TruncInt( (__PCL_MEDIAN_HISTOGRAM_LENGTH - 1) * (d - m_low)/m_range )];
16744 const double& m_low;
16745 const double& m_high;
16751 class TwoSidedAbsDevHistogramThread :
public RectThreadBase
16757 TwoSidedAbsDevHistogramThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow,
16758 double center,
const int& side,
const double& low,
const double& high )
16759 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
16760 , H( __PCL_MEDIAN_HISTOGRAM_LENGTH )
16761 , m_center( center )
16771 m_range = m_high - m_low;
16774 #ifdef __PCL_MACOSX
16775 if ( 1 + m_range != 1 )
16777 this->Execute( [=](
const sample* __restrict__ f )
16779 double x; P::FromSample( x, *f );
16780 if ( m_side > 0 == x > m_center )
16782 double d = m_side ? x - m_center : m_center - x;
16785 ++H[
TruncInt( (__PCL_MEDIAN_HISTOGRAM_LENGTH - 1) * (d - m_low)/m_range )];
16794 const double& m_low;
16795 const double& m_high;
16801 class VarThread :
public RectThreadBase
16805 double var = 0, eps = 0;
16807 VarThread(
const GenericImage& image,
double mean,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
16808 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
16816 this->Execute( [=](
const sample* __restrict__ f )
16818 double d; P::FromSample( d, *f );
16832 class SumAbsDevThread :
public SumThread
16836 SumAbsDevThread(
const GenericImage& image,
double center,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
16837 : SumThread( image, rect, ch1, ch2, firstRow, endRow )
16838 , m_center( center )
16846 void DoExecute()
override
16848 this->Execute( [=](
const sample* __restrict__ f )
16850 double v; P::FromSample( v, *f );
16851 this->SumStep(
pcl::Abs( v - m_center ) );
16858 class TwoSidedSumAbsDevThread :
public RectThreadBase
16862 double s0 = 0, s1 = 0;
16865 TwoSidedSumAbsDevThread(
const GenericImage& image,
double center,
16866 const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
16867 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
16868 , m_center( center )
16876 this->Execute( [=](
const sample* __restrict__ f )
16878 double v; P::FromSample( v, *f );
16879 if ( v <= m_center )
16881 s0 += m_center - v;
16886 s1 += v - m_center;
16899 class BWMVThread :
public RectThreadBase
16903 double num = 0, den = 0;
16906 BWMVThread(
const GenericImage& image,
double center,
double kd,
16907 const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
16908 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
16909 , m_center( center )
16918 this->Execute( [=](
const sample* __restrict__ f )
16921 double xc; P::FromSample( xc, *f ); xc -= m_center;
16922 double y = xc/m_kd;
16926 double y21 = 1 - y2;
16927 num += xc*xc * y21*y21*y21*y21;
16928 den += y21 * (1 - 5*y2);
16942 class TwoSidedBWMVThread :
public RectThreadBase
16946 double num0 = 0, den0 = 0;
16947 double num1 = 0, den1 = 0;
16948 size_type n0 = 0, n1 = 0, nr0 = 0, nr1 = 0;
16950 TwoSidedBWMVThread(
const GenericImage& image,
double center,
double kd0,
double kd1,
16951 const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
16952 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
16953 , m_center( center )
16961 num0 = den0 = num1 = den1 = 0;
16962 n0 = n1 = nr0 = nr1 = 0;
16963 this->Execute( [=](
const sample* __restrict__ f )
16965 double xc; P::FromSample( xc, *f ); xc -= m_center;
16966 bool low = xc <= 0;
16972 double y = xc/(low ? m_kd0 : m_kd1);
16976 double y21 = 1 - y2;
16977 double num = xc*xc * y21*y21*y21*y21;
16978 double den = y21 * (1 - 5*y2);
17004 class SmpThread :
public RectThreadBase
17008 Array<sample> samples;
17011 SmpThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
17012 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
17015 *
size_type( this->m_endRow - this->m_firstRow )
17016 * (1 + this->m_ch2 - this->m_ch1);
17017 samples = Array<sample>( N );
17023 this->Execute( [=](
const sample* __restrict__ f )
17032 class DSmpThread :
public RectThreadBase
17036 Array<double> values;
17039 DSmpThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
17040 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
17043 *
size_type( this->m_endRow - this->m_firstRow )
17044 * (1 + this->m_ch2 - this->m_ch1);
17045 values = Array<double>( N );
17056 virtual void DoExecute()
17058 if ( this->HasSimpleSelection() )
17061 for (
int i = this->m_ch1; i <= this->m_ch2; ++i )
17063 const sample* __restrict__ f = this->m_image.PixelAddress( 0, this->m_rect.y0 + this->m_firstRow, i );
17065 for (
size_type j = 0; j < N; ++j, ++n, ++f )
17066 P::FromSample( values[n], *f );
17071 this->Execute( [=](
const sample* __restrict__ f )
17073 P::FromSample( values[n++], *f );
17081 class AbsDevSmpThread :
public DSmpThread
17085 AbsDevSmpThread(
const GenericImage& image,
double center,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
17086 : DSmpThread( image, rect, ch1, ch2, firstRow, endRow )
17087 , m_center( center )
17095 void DoExecute()
override
17097 this->Execute( [=](
const sample* __restrict__ f )
17099 double d; P::FromSample( d, *f );
17100 this->values[this->n++] =
pcl::Abs( d - m_center );
17107 class TwoSidedAbsDevSmpThread :
public DSmpThread
17113 TwoSidedAbsDevSmpThread(
const GenericImage& image,
double center,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
17114 : DSmpThread( image, rect, ch1, ch2, firstRow, endRow )
17115 , m_center( center )
17123 void DoExecute()
override
17125 p = this->values.Begin();
17126 q = this->values.End();
17127 this->Execute( [=](
const sample* __restrict__ f )
17129 double x; P::FromSample( x, *f );
17130 if ( x <= m_center )
17131 *p++ = m_center - x;
17133 *--q = x - m_center;
17141 class ColorSpaceConversionThread :
public Thread
17145 ColorSpaceConversionThread( GenericImage& image, ThreadData& data,
17149 , m_toColorSpace( toColorSpace )
17159 const RGBColorSystem& rgbws = m_image.RGBWorkingSpace();
17161 typename P::sample* f0 = m_image[0] + m_begin;
17162 typename P::sample* f1 = m_image[1] + m_begin;
17163 typename P::sample* f2 = m_image[2] + m_begin;
17164 typename P::sample* fN = m_image[0] + m_end;
17166 for ( ; f0 < fN; ++f0, ++f1, ++f2 )
17168 RGBColorSystem::sample r0, r1, r2;
17169 P::FromSample( r0, *f0 );
17170 P::FromSample( r1, *f1 );
17171 P::FromSample( r2, *f2 );
17173 switch ( m_image.ColorSpace() )
17175 case ColorSpace::RGB :
17176 switch ( m_toColorSpace )
17178 case ColorSpace::Gray :
17179 rgbws.RGBToGray( r0, r0, r1, r2 );
17181 case ColorSpace::HSV :
17182 rgbws.RGBToHSV( r0, r1, r2, r0, r1, r2 );
17184 case ColorSpace::HSI :
17185 rgbws.RGBToHSI( r0, r1, r2, r0, r1, r2 );
17187 case ColorSpace::CIEXYZ :
17188 rgbws.RGBToCIEXYZ( r0, r1, r2, r0, r1, r2 );
17190 case ColorSpace::CIELab :
17191 rgbws.RGBToCIELab( r0, r1, r2, r0, r1, r2 );
17193 case ColorSpace::CIELch :
17194 rgbws.RGBToCIELch( r0, r1, r2, r0, r1, r2 );
17200 case ColorSpace::HSV :
17201 rgbws.HSVToRGB( r0, r1, r2, r0, r1, r2 );
17202 switch ( m_toColorSpace )
17204 case ColorSpace::Gray :
17205 rgbws.RGBToGray( r0, r0, r1, r2 );
17207 case ColorSpace::RGB :
17209 case ColorSpace::HSI :
17210 rgbws.RGBToHSI( r0, r1, r2, r0, r1, r2 );
17212 case ColorSpace::CIEXYZ :
17213 rgbws.RGBToCIEXYZ( r0, r1, r2, r0, r1, r2 );
17215 case ColorSpace::CIELab :
17216 rgbws.RGBToCIELab( r0, r1, r2, r0, r1, r2 );
17218 case ColorSpace::CIELch :
17219 rgbws.RGBToCIELch( r0, r1, r2, r0, r1, r2 );
17225 case ColorSpace::HSI :
17226 rgbws.HSIToRGB( r0, r1, r2, r0, r1, r2 );
17227 switch ( m_toColorSpace )
17229 case ColorSpace::Gray :
17230 rgbws.RGBToGray( r0, r0, r1, r2 );
17232 case ColorSpace::RGB :
17234 case ColorSpace::HSV :
17235 rgbws.RGBToHSV( r0, r1, r2, r0, r1, r2 );
17237 case ColorSpace::CIEXYZ :
17238 rgbws.RGBToCIEXYZ( r0, r1, r2, r0, r1, r2 );
17240 case ColorSpace::CIELab :
17241 rgbws.RGBToCIELab( r0, r1, r2, r0, r1, r2 );
17243 case ColorSpace::CIELch :
17244 rgbws.RGBToCIELch( r0, r1, r2, r0, r1, r2 );
17250 case ColorSpace::CIEXYZ :
17251 switch ( m_toColorSpace )
17253 case ColorSpace::Gray :
17254 rgbws.CIEXYZToRGB( r0, r1, r2, r0, r1, r2 );
17255 rgbws.RGBToGray( r0, r0, r1, r2 );
17257 case ColorSpace::RGB :
17258 rgbws.CIEXYZToRGB( r0, r1, r2, r0, r1, r2 );
17260 case ColorSpace::HSV :
17261 rgbws.CIEXYZToRGB( r0, r1, r2, r0, r1, r2 );
17262 rgbws.RGBToHSV( r0, r1, r2, r0, r1, r2 );
17264 case ColorSpace::HSI :
17265 rgbws.CIEXYZToRGB( r0, r1, r2, r0, r1, r2 );
17266 rgbws.RGBToHSI( r0, r1, r2, r0, r1, r2 );
17268 case ColorSpace::CIELab :
17269 rgbws.CIEXYZToCIELab( r0, r1, r2, r0, r1, r2 );
17271 case ColorSpace::CIELch :
17272 rgbws.CIEXYZToCIELab( r0, r1, r2, r0, r1, r2 );
17273 rgbws.CIELabToCIELch( r0, r1, r2, r0, r1, r2 );
17279 case ColorSpace::CIELab :
17280 switch ( m_toColorSpace )
17282 case ColorSpace::Gray :
17283 rgbws.CIELabToRGB( r0, r1, r2, r0, r1, r2 );
17284 rgbws.RGBToGray( r0, r0, r1, r2 );
17286 case ColorSpace::RGB :
17287 rgbws.CIELabToRGB( r0, r1, r2, r0, r1, r2 );
17289 case ColorSpace::HSV :
17290 rgbws.CIELabToRGB( r0, r1, r2, r0, r1, r2 );
17291 rgbws.RGBToHSV( r0, r1, r2, r0, r1, r2 );
17293 case ColorSpace::HSI :
17294 rgbws.CIELabToRGB( r0, r1, r2, r0, r1, r2 );
17295 rgbws.RGBToHSI( r0, r1, r2, r0, r1, r2 );
17297 case ColorSpace::CIEXYZ :
17298 rgbws.CIELabToCIEXYZ( r0, r1, r2, r0, r1, r2 );
17300 case ColorSpace::CIELch :
17301 rgbws.CIELabToCIELch( r0, r1, r2, r0, r1, r2 );
17307 case ColorSpace::CIELch :
17308 switch ( m_toColorSpace )
17310 case ColorSpace::Gray :
17311 rgbws.CIELchToRGB( r0, r1, r2, r0, r1, r2 );
17312 rgbws.RGBToGray( r0, r0, r1, r2 );
17314 case ColorSpace::RGB :
17315 rgbws.CIELchToRGB( r0, r1, r2, r0, r1, r2 );
17317 case ColorSpace::HSV :
17318 rgbws.CIELchToRGB( r0, r1, r2, r0, r1, r2 );
17319 rgbws.RGBToHSV( r0, r1, r2, r0, r1, r2 );
17321 case ColorSpace::HSI :
17322 rgbws.CIELchToRGB( r0, r1, r2, r0, r1, r2 );
17323 rgbws.RGBToHSI( r0, r1, r2, r0, r1, r2 );
17325 case ColorSpace::CIEXYZ :
17326 rgbws.CIELchToCIELab( r0, r1, r2, r0, r1, r2 );
17327 rgbws.CIELabToCIEXYZ( r0, r1, r2, r0, r1, r2 );
17329 case ColorSpace::CIELab :
17330 rgbws.CIELchToCIELab( r0, r1, r2, r0, r1, r2 );
17340 *f0 = P::ToSample( r0 );
17342 if ( m_toColorSpace != ColorSpace::Gray )
17344 *f1 = P::ToSample( r1 );
17345 *f2 = P::ToSample( r2 );
17354 GenericImage& m_image;
17355 ThreadData& m_data;
17356 color_space m_toColorSpace;
17362 template <
class P1>
17363 class GetLuminanceThread :
public Thread
17367 GetLuminanceThread( GenericImage<P1>& luminance,
const GenericImage& image, ThreadData& data,
17368 const Rect& rect,
int firstRow,
int endRow )
17369 : m_luminance( luminance )
17373 , m_firstRow( firstRow )
17374 , m_endRow( endRow )
17382 const RGBColorSystem& rgbws = m_image.RGBWorkingSpace();
17384 const typename P::sample* f0 = m_image.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 0 );
17385 const typename P::sample* f1 = m_image.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 1 );
17386 const typename P::sample* f2 = m_image.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 2 );
17388 typename P1::sample* fY = m_luminance.ScanLine( m_firstRow );
17390 for (
int y = m_firstRow, dw = m_image.Width()-m_rect.Width();
17392 ++y, f0 += dw, f1 += dw, f2 += dw )
17394 const typename P::sample* fN = f0 + m_rect.Width();
17396 for ( ; f0 < fN; ++f0, ++f1, ++f2, ++fY )
17398 RGBColorSystem::sample r0, r1, r2, rY;
17399 P::FromSample( r0, *f0 );
17400 P::FromSample( r1, *f1 );
17401 P::FromSample( r2, *f2 );
17403 switch ( m_image.ColorSpace() )
17405 case ColorSpace::RGB:
17406 case ColorSpace::HSV:
17407 case ColorSpace::HSI:
17408 switch ( m_image.ColorSpace() )
17410 case ColorSpace::HSV:
17411 rgbws.HSVToRGB( r0, r1, r2, r0, r1, r2 );
17413 case ColorSpace::HSI:
17414 rgbws.HSIToRGB( r0, r1, r2, r0, r1, r2 );
17419 rY = rgbws.CIEY( r0, r1, r2 );
17422 case ColorSpace::CIELch:
17423 rgbws.CIELchToCIELab( r0, r1, r2, r0, r1, r2 );
17425 case ColorSpace::CIELab:
17426 rgbws.CIELabToCIEXYZ( r0, rY, r2, r0, r1, r2 );
17434 *fY = P1::ToSample( rY );
17443 GenericImage<P1>& m_luminance;
17444 const GenericImage& m_image;
17445 ThreadData& m_data;
17446 const Rect& m_rect;
17447 int m_firstRow, m_endRow;
17452 template <
class P1>
17453 class GetLightnessThread :
public Thread
17457 GetLightnessThread( GenericImage<P1>& lightness,
const GenericImage& image, ThreadData& data,
17458 const Rect& rect,
int firstRow,
int endRow )
17459 : m_lightness( lightness )
17463 , m_firstRow( firstRow )
17464 , m_endRow( endRow )
17472 const RGBColorSystem& rgbws = m_image.RGBWorkingSpace();
17474 const typename P::sample* f0 = m_image.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 0 );
17475 const typename P::sample* f1 = m_image.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 1 );
17476 const typename P::sample* f2 = m_image.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 2 );
17478 typename P1::sample* fL = m_lightness.ScanLine( m_firstRow );
17480 for (
int y = m_firstRow, dw = m_image.Width()-m_rect.Width();
17482 ++y, f0 += dw, f1 += dw, f2 += dw )
17484 const typename P::sample* fN = f0 + m_rect.Width();
17486 for ( ; f0 < fN; ++f0, ++f1, ++f2, ++fL )
17488 RGBColorSystem::sample r0, r1, r2, rL;
17489 P::FromSample( r0, *f0 );
17490 P::FromSample( r1, *f1 );
17491 P::FromSample( r2, *f2 );
17493 switch ( m_image.ColorSpace() )
17495 case ColorSpace::RGB:
17496 case ColorSpace::HSV:
17497 case ColorSpace::HSI:
17498 case ColorSpace::CIEXYZ:
17499 switch ( m_image.ColorSpace() )
17501 case ColorSpace::HSV:
17502 rgbws.HSVToRGB( r0, r1, r2, r0, r1, r2 );
17504 case ColorSpace::HSI:
17505 rgbws.HSIToRGB( r0, r1, r2, r0, r1, r2 );
17507 case ColorSpace::CIEXYZ:
17508 rgbws.CIEXYZToRGB( r0, r1, r2, r0, r1, r2 );
17513 rL = rgbws.CIEL( r0, r1, r2 );
17521 *fL = P1::ToSample( rL );
17530 GenericImage<P1>& m_lightness;
17531 const GenericImage& m_image;
17532 ThreadData& m_data;
17533 const Rect& m_rect;
17534 int m_firstRow, m_endRow;
17539 template <
class P1>
17540 class GetIntensityThread :
public Thread
17544 GetIntensityThread( GenericImage<P1>& luminance,
const GenericImage& image, ThreadData& data,
17545 const Rect& rect,
int firstRow,
int endRow )
17546 : m_intensity( luminance )
17550 , m_firstRow( firstRow )
17551 , m_endRow( endRow )
17559 const RGBColorSystem& rgbws = m_image.RGBWorkingSpace();
17561 const typename P::sample* f0 = m_image.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 0 );
17562 const typename P::sample* f1 = m_image.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 1 );
17563 const typename P::sample* f2 = m_image.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 2 );
17565 typename P1::sample* fI = m_intensity.ScanLine( m_firstRow );
17567 for (
int y = m_firstRow, dw = m_image.Width()-m_rect.Width();
17569 ++y, f0 += dw, f1 += dw, f2 += dw )
17571 const typename P::sample* fN = f0 + m_rect.Width();
17573 for ( ; f0 < fN; ++f0, ++f1, ++f2, ++fI )
17575 RGBColorSystem::sample r0, r1, r2;
17576 P::FromSample( r0, *f0 );
17577 P::FromSample( r1, *f1 );
17578 P::FromSample( r2, *f2 );
17580 switch ( m_image.ColorSpace() )
17582 case ColorSpace::RGB:
17584 case ColorSpace::HSV:
17585 rgbws.HSVToRGB( r0, r1, r2, r0, r1, r2 );
17587 case ColorSpace::CIEXYZ:
17588 rgbws.CIEXYZToRGB( r0, r1, r2, r0, r1, r2 );
17590 case ColorSpace::CIELab:
17591 rgbws.CIELabToRGB( r0, r1, r2, r0, r1, r2 );
17593 case ColorSpace::CIELch:
17594 rgbws.CIELchToRGB( r0, r1, r2, r0, r1, r2 );
17600 *fI = P1::ToSample( rgbws.Intensity( r0, r1, r2 ) );
17609 GenericImage<P1>& m_intensity;
17610 const GenericImage& m_image;
17611 ThreadData& m_data;
17612 const Rect& m_rect;
17613 int m_firstRow, m_endRow;
17618 template <
class P1>
17619 class SetLuminanceThread :
public Thread
17623 SetLuminanceThread( GenericImage& image,
const GenericImage<P1>& luminance, ThreadData& data,
17624 const Point& target,
const Rect& rect,
int firstRow,
int endRow )
17626 , m_luminance( luminance )
17628 , m_target( target )
17630 , m_firstRow( firstRow )
17631 , m_endRow( endRow )
17639 const RGBColorSystem& sourceRGBWS = m_luminance.RGBWorkingSpace();
17640 const RGBColorSystem& targetRGBWS = m_image.RGBWorkingSpace();
17642 typename P::sample* f0 = m_image.PixelAddress( m_target.x, m_target.y + m_firstRow, 0 );
17643 typename P::sample* f1 = m_image.PixelAddress( m_target.x, m_target.y + m_firstRow, 1 );
17644 typename P::sample* f2 = m_image.PixelAddress( m_target.x, m_target.y + m_firstRow, 2 );
17646 if ( m_luminance.ColorSpace() == ColorSpace::Gray || m_luminance.ColorSpace() == ColorSpace::CIEXYZ )
17648 int cY = (m_luminance.ColorSpace() == ColorSpace::Gray) ? 0 : 1;
17649 const typename P1::sample* fY = m_luminance.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, cY );
17651 for (
int y = m_firstRow, dw = m_image.Width()-m_rect.Width(), dwY = m_luminance.Width()-m_rect.Width();
17653 ++y, f0 += dw, f1 += dw, f2 += dw, fY += dwY )
17655 const typename P::sample* fN = f0 + m_rect.Width();
17657 for ( ; f0 < fN; ++f0, ++f1, ++f2, ++fY )
17659 RGBColorSystem::sample r0, r1, r2, rY;
17660 P::FromSample( r0, *f0 );
17661 P::FromSample( r1, *f1 );
17662 P::FromSample( r2, *f2 );
17663 P1::FromSample( rY, *fY );
17665 switch ( m_image.ColorSpace() )
17667 case ColorSpace::RGB:
17668 case ColorSpace::HSV:
17669 case ColorSpace::HSI:
17670 switch ( m_image.ColorSpace() )
17672 case ColorSpace::HSV:
17673 targetRGBWS.HSVToRGB( r0, r1, r2, r0, r1, r2 );
17675 case ColorSpace::HSI:
17676 targetRGBWS.HSIToRGB( r0, r1, r2, r0, r1, r2 );
17681 targetRGBWS.RGBToCIEab( r1, r2, r0, r1, r2 );
17682 targetRGBWS.CIELabToRGB( r0, r1, r2, sourceRGBWS.CIEYToCIEL( rY ), r1, r2 );
17683 switch ( m_image.ColorSpace() )
17685 case ColorSpace::HSV:
17686 targetRGBWS.RGBToHSV( r0, r1, r2, r0, r1, r2 );
17688 case ColorSpace::HSI:
17689 targetRGBWS.RGBToHSI( r0, r1, r2, r0, r1, r2 );
17696 case ColorSpace::CIEXYZ:
17697 targetRGBWS.CIEXYZToCIELab( r0, r1, r2, r0, r1, r2 );
17698 targetRGBWS.CIELabToCIEXYZ( r0, r1, r2, sourceRGBWS.CIEYToCIEL( rY ), r1, r2 );
17701 case ColorSpace::CIELab:
17702 case ColorSpace::CIELch:
17703 r0 = sourceRGBWS.CIEYToCIEL( rY );
17710 *f0 = P::ToSample( r0 );
17711 *f1 = P::ToSample( r1 );
17712 *f2 = P::ToSample( r2 );
17720 const typename P1::sample* g0 = m_luminance.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 0 );
17721 const typename P1::sample* g1 = m_luminance.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 1 );
17722 const typename P1::sample* g2 = m_luminance.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 2 );
17724 for (
int y = m_firstRow, dw = m_image.Width()-m_rect.Width(), dwY = m_luminance.Width()-m_rect.Width();
17726 ++y, f0 += dw, f1 += dw, f2 += dw, g0 += dwY, g1 += dwY, g2 += dwY )
17728 const typename P::sample* fN = f0 + m_rect.Width();
17730 for ( ; f0 < fN; ++f0, ++f1, ++f2, ++g0, ++g1, ++g2 )
17732 typename RGBColorSystem::sample r0, r1, r2, s0, s1, s2;
17733 P::FromSample( r0, *f0 );
17734 P::FromSample( r1, *f1 );
17735 P::FromSample( r2, *f2 );
17736 P1::FromSample( s0, *g0 );
17737 P1::FromSample( s1, *g1 );
17738 P1::FromSample( s2, *g2 );
17740 switch ( m_image.ColorSpace() )
17742 case ColorSpace::RGB:
17743 case ColorSpace::HSV:
17744 case ColorSpace::HSI:
17745 case ColorSpace::CIEXYZ:
17746 case ColorSpace::CIELab:
17747 case ColorSpace::CIELch:
17748 switch ( m_image.ColorSpace() )
17750 case ColorSpace::RGB:
17751 case ColorSpace::HSV:
17752 case ColorSpace::HSI:
17753 switch ( m_image.ColorSpace() )
17755 case ColorSpace::HSV:
17756 targetRGBWS.HSVToRGB( r0, r1, r2, r0, r1, r2 );
17758 case ColorSpace::HSI:
17759 targetRGBWS.HSIToRGB( r0, r1, r2, r0, r1, r2 );
17764 targetRGBWS.RGBToCIEab( r1, r2, r0, r1, r2 );
17766 case ColorSpace::CIEXYZ:
17767 targetRGBWS.CIEXYZToCIELab( r0, r1, r2, r0, r1, r2 );
17769 case ColorSpace::CIELab:
17770 case ColorSpace::CIELch:
17776 switch ( m_luminance.ColorSpace() )
17778 case ColorSpace::RGB:
17779 case ColorSpace::HSV:
17780 case ColorSpace::HSI:
17781 switch ( m_luminance.ColorSpace() )
17783 case ColorSpace::HSV:
17784 sourceRGBWS.HSVToRGB( s0, s1, s2, s0, s1, s2 );
17786 case ColorSpace::HSI:
17787 sourceRGBWS.HSIToRGB( s0, s1, s2, s0, s1, s2 );
17792 r0 = sourceRGBWS.CIEL( s0, s1, s2 );
17794 case ColorSpace::CIEXYZ:
17795 sourceRGBWS.CIEXYZToCIELab( r0, s1, s2, s0, s1, s2 );
17797 case ColorSpace::CIELab:
17798 case ColorSpace::CIELch:
17805 switch ( m_image.ColorSpace() )
17807 case ColorSpace::RGB:
17808 case ColorSpace::HSV:
17809 case ColorSpace::HSI:
17810 targetRGBWS.CIELabToRGB( r0, r1, r2, r0, r1, r2 );
17811 switch ( m_image.ColorSpace() )
17813 case ColorSpace::HSV:
17814 targetRGBWS.RGBToHSV( r0, r1, r2, r0, r1, r2 );
17816 case ColorSpace::HSI:
17817 targetRGBWS.RGBToHSI( r0, r1, r2, r0, r1, r2 );
17823 case ColorSpace::CIEXYZ:
17824 targetRGBWS.CIELabToCIEXYZ( r0, r1, r2, r0, r1, r2 );
17826 case ColorSpace::CIELab:
17827 case ColorSpace::CIELch:
17838 *f0 = P::ToSample( r0 );
17839 *f1 = P::ToSample( r1 );
17840 *f2 = P::ToSample( r2 );
17850 GenericImage& m_image;
17851 const GenericImage<P1>& m_luminance;
17852 ThreadData& m_data;
17853 const Point& m_target;
17854 const Rect& m_rect;
17855 int m_firstRow, m_endRow;
17860 template <
class P1>
17861 class SetLightnessThread :
public Thread
17865 SetLightnessThread( GenericImage& image,
const GenericImage<P1>& lightness, ThreadData& data,
17866 const Point& target,
const Rect& rect,
int firstRow,
int endRow )
17868 , m_lightness( lightness )
17870 , m_target( target )
17872 , m_firstRow( firstRow )
17873 , m_endRow( endRow )
17881 const RGBColorSystem& sourceRGBWS = m_lightness.RGBWorkingSpace();
17882 const RGBColorSystem& targetRGBWS = m_image.RGBWorkingSpace();
17884 typename P::sample* f0 = m_image.PixelAddress( m_target.x, m_target.y + m_firstRow, 0 );
17885 typename P::sample* f1 = m_image.PixelAddress( m_target.x, m_target.y + m_firstRow, 1 );
17886 typename P::sample* f2 = m_image.PixelAddress( m_target.x, m_target.y + m_firstRow, 2 );
17888 if ( m_lightness.ColorSpace() == ColorSpace::Gray ||
17889 m_lightness.ColorSpace() == ColorSpace::CIELab || m_lightness.ColorSpace() == ColorSpace::CIELch )
17891 const typename P1::sample* fL = m_lightness.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 0 );
17893 for (
int y = m_firstRow, dw = m_image.Width()-m_rect.Width(), dwL = m_lightness.Width()-m_rect.Width();
17895 ++y, f0 += dw, f1 += dw, f2 += dw, fL += dwL )
17897 const typename P::sample* fN = f0 + m_rect.Width();
17899 for ( ; f0 < fN; ++f0, ++f1, ++f2, ++fL )
17901 RGBColorSystem::sample r0, r1, r2, rL;
17902 P::FromSample( r0, *f0 );
17903 P::FromSample( r1, *f1 );
17904 P::FromSample( r2, *f2 );
17905 P1::FromSample( rL, *fL );
17907 switch ( m_image.ColorSpace() )
17909 case ColorSpace::RGB:
17910 case ColorSpace::HSV:
17911 case ColorSpace::HSI:
17912 switch ( m_image.ColorSpace() )
17914 case ColorSpace::HSV:
17915 targetRGBWS.HSVToRGB( r0, r1, r2, r0, r1, r2 );
17917 case ColorSpace::HSI:
17918 targetRGBWS.HSIToRGB( r0, r1, r2, r0, r1, r2 );
17923 targetRGBWS.RGBToCIEab( r1, r2, r0, r1, r2 );
17924 targetRGBWS.CIELabToRGB( r0, r1, r2, rL, r1, r2 );
17925 switch ( m_image.ColorSpace() )
17927 case ColorSpace::HSV:
17928 targetRGBWS.RGBToHSV( r0, r1, r2, r0, r1, r2 );
17930 case ColorSpace::HSI:
17931 targetRGBWS.RGBToHSI( r0, r1, r2, r0, r1, r2 );
17938 case ColorSpace::CIEXYZ:
17939 r1 = targetRGBWS.CIELToCIEY( rL );
17942 case ColorSpace::CIELab:
17943 case ColorSpace::CIELch:
17951 *f0 = P::ToSample( r0 );
17952 *f1 = P::ToSample( r1 );
17953 *f2 = P::ToSample( r2 );
17961 const typename P1::sample* g0 = m_lightness.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 0 );
17962 const typename P1::sample* g1 = m_lightness.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 1 );
17963 const typename P1::sample* g2 = m_lightness.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 2 );
17965 for (
int y = m_firstRow, dw = m_image.Width()-m_rect.Width(), dwL = m_lightness.Width()-m_rect.Width();
17967 ++y, f0 += dw, f1 += dw, f2 += dw, g0 += dwL, g1 += dwL, g2 += dwL )
17969 const typename P::sample* fN = f0 + m_rect.Width();
17971 for ( ; f0 < fN; ++f0, ++f1, ++f2, ++g0, ++g1, ++g2 )
17973 typename RGBColorSystem::sample r0, r1, r2, s0, s1, s2;
17974 P::FromSample( r0, *f0 );
17975 P::FromSample( r1, *f1 );
17976 P::FromSample( r2, *f2 );
17977 P1::FromSample( s0, *g0 );
17978 P1::FromSample( s1, *g1 );
17979 P1::FromSample( s2, *g2 );
17981 switch ( m_image.ColorSpace() )
17983 case ColorSpace::RGB:
17984 case ColorSpace::HSV:
17985 case ColorSpace::HSI:
17986 case ColorSpace::CIEXYZ:
17987 case ColorSpace::CIELab:
17988 case ColorSpace::CIELch:
17989 switch ( m_image.ColorSpace() )
17991 case ColorSpace::RGB:
17992 case ColorSpace::HSV:
17993 case ColorSpace::HSI:
17994 switch ( m_image.ColorSpace() )
17996 case ColorSpace::HSV:
17997 targetRGBWS.HSVToRGB( r0, r1, r2, r0, r1, r2 );
17999 case ColorSpace::HSI:
18000 targetRGBWS.HSIToRGB( r0, r1, r2, r0, r1, r2 );
18005 targetRGBWS.RGBToCIEab( r1, r2, r0, r1, r2 );
18007 case ColorSpace::CIEXYZ:
18008 targetRGBWS.CIEXYZToCIELab( r0, r1, r2, r0, r1, r2 );
18010 case ColorSpace::CIELch:
18011 targetRGBWS.CIELchToCIELab( r0, r1, r2, r0, r1, r2 );
18017 switch ( m_lightness.ColorSpace() )
18019 case ColorSpace::RGB:
18020 case ColorSpace::HSV:
18021 case ColorSpace::HSI:
18022 switch ( m_lightness.ColorSpace() )
18024 case ColorSpace::HSV:
18025 sourceRGBWS.HSVToRGB( s0, s1, s2, s0, s1, s2 );
18027 case ColorSpace::HSI:
18028 sourceRGBWS.HSIToRGB( s0, s1, s2, s0, s1, s2 );
18033 r0 = sourceRGBWS.CIEL( s0, s1, s2 );
18035 case ColorSpace::CIEXYZ:
18036 r0 = sourceRGBWS.CIEYToCIEL( s1 );
18042 switch ( m_image.ColorSpace() )
18044 case ColorSpace::RGB:
18045 case ColorSpace::HSV:
18046 case ColorSpace::HSI:
18047 targetRGBWS.CIELabToRGB( r0, r1, r2, r0, r1, r2 );
18048 switch ( m_image.ColorSpace() )
18050 case ColorSpace::HSV:
18051 targetRGBWS.RGBToHSV( r0, r1, r2, r0, r1, r2 );
18053 case ColorSpace::HSI:
18054 targetRGBWS.RGBToHSI( r0, r1, r2, r0, r1, r2 );
18060 case ColorSpace::CIEXYZ:
18061 targetRGBWS.CIELabToCIEXYZ( r0, r1, r2, r0, r1, r2 );
18063 case ColorSpace::CIELch:
18064 targetRGBWS.CIELabToCIELch( r0, r1, r2, r0, r1, r2 );
18074 *f0 = P::ToSample( r0 );
18075 *f1 = P::ToSample( r1 );
18076 *f2 = P::ToSample( r2 );
18086 GenericImage& m_image;
18087 const GenericImage<P1>& m_lightness;
18088 ThreadData& m_data;
18089 const Point& m_target;
18090 const Rect& m_rect;
18091 int m_firstRow, m_endRow;
18096 #ifdef __PCL_BUILDING_PIXINSIGHT_APPLICATION
18097 friend class pi::SharedImage;
18102 #undef m_channelData
18106 #undef m_numberOfChannels
18107 #undef m_colorSpace
18110 #undef m_lastChannel
18115 #undef m_clippedLow
18116 #undef m_clippedHigh
18129 template <
class P,
typename T>
inline
18133 (void)(result += scalar);
18145 template <
class P,
typename T>
inline
18148 return image + scalar;
18156 template <
class P,
typename T>
inline
18160 (void)(result -= scalar);
18169 template <
class P,
typename T>
inline
18173 (void)(result *= scalar);
18186 template <
class P,
typename T>
inline
18189 return image * scalar;
18197 template <
class P,
typename T>
inline
18201 (void)(result /= scalar);
18210 template <
class P,
typename T>
inline
18214 (void)(result ^= scalar);
18236 template <
class P1,
class P2>
inline
18240 (void)(result += image2);
18256 template <
class P1,
class P2>
inline
18260 (void)(result -= image2);
18276 template <
class P1,
class P2>
inline
18280 (void)(result *= image2);
18297 template <
class P1,
class P2>
inline
18301 (void)(result /= image2);
18318 template <
class P1,
class P2>
inline
18322 (void)(result ^= image2);
18328 #ifndef __PCL_NO_IMAGE_INSTANTIATE
18341 using FImage = GenericImage<FloatPixelTraits>;
18350 using DImage = GenericImage<DoublePixelTraits>;
18380 using UInt8Image = GenericImage<UInt8PixelTraits>;
18390 using UInt16Image = GenericImage<UInt16PixelTraits>;
18400 using UInt32Image = GenericImage<UInt32PixelTraits>;
18430 #ifndef __PCL_NO_IMAGE_VARIANT_AUTO
18432 #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
double Mean(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0, bool __performanceAnalysis__=false) 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)
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)
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)
Array< double > PixelSamples(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0, bool __performanceAnalysis__=false)
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
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, bool __performanceAnalysis__=false) 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)
void GetIntensity(GenericImage< P1 > &I, const Rect &rect=Rect(0), int maxProcessors=0, bool __performanceAnalysis__=false) const
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 & 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 & SetColorSpace(color_space colorSpace, int maxProcessors=0, bool __performanceAnalysis__=false)
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)
void GetExtremeSampleValues(T &min, T &max, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0, bool __performanceAnalysis__=false) const
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)
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()
void GetLightness(GenericImage< P1 > &L, const Rect &rect=Rect(0), int maxProcessors=0, bool __performanceAnalysis__=false) const
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.
size_type IntegerArea() const
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 eps=0)
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.