58 #include <pcl/Diagnostics.h>
71 #ifndef __PCL_IMAGE_NO_BITMAP
72 # ifdef __PCL_BUILDING_PIXINSIGHT_APPLICATION
73 # ifndef __PI_Bitmap_h
74 # include <API/Bitmap.h>
78 # ifndef __PCL_Bitmap_h
82 # ifndef __PCL_Color_h
87 #ifdef __PCL_BUILDING_PIXINSIGHT_APPLICATION
176 return op >= Add && op <= Dif;
185 return op >= Or && op <= Xnor;
194 return op == Mov || op == Min || op == Max;
203 return op >= ColorBurn && op <= Exclusion;
214 #define m_pixelData m_data->data
215 #define m_channelData( c ) reinterpret_cast<sample*>( PCL_ASSUME_ALIGNED_32( m_pixelData[c] ) )
216 #define m_allocator m_data->allocator
218 #define m_width m_geometry->width
219 #define m_height m_geometry->height
220 #define m_numberOfChannels m_geometry->numberOfChannels
222 #define m_colorSpace m_color->colorSpace
223 #define m_RGBWS m_color->RGBWS
225 #define m_channel m_selected.channel
226 #define m_lastChannel m_selected.lastChannel
227 #define m_point m_selected.point
228 #define m_rectangle m_selected.rectangle
229 #define m_clipLow m_selected.clipLow
230 #define m_clipHigh m_selected.clipHigh
231 #define m_clippedLow m_selected.clippedLow
232 #define m_clippedHigh m_selected.clippedHigh
305 using sample =
typename pixel_traits::sample;
312 using color_space = AbstractImage::color_space;
325 using image_op = ImageOp::value_type;
394 m_image->EnsureUnique();
395 if ( m_image->ParseChannel( channel ) )
397 m_iterator = (*m_image)[channel];
398 m_end = m_iterator + m_image->NumberOfPixels();
441 return m_image !=
nullptr && m_iterator !=
nullptr;
467 operator bool() const noexcept
469 return m_iterator < m_end;
595 return i.m_iterator - j.m_iterator;
604 return i.m_iterator - j;
613 return i - j.m_iterator;
622 return i.m_iterator == j.m_iterator;
631 return i.m_iterator == j;
640 return i == j.m_iterator;
649 return i.m_iterator < j.m_iterator;
657 return i.m_iterator < j;
665 return i < j.m_iterator;
670 image_type* m_image =
nullptr;
671 sample* __restrict__ m_iterator =
nullptr;
672 const sample* __restrict__ m_end =
nullptr;
728 if ( m_image->ParseChannel( channel ) )
730 m_iterator = (*m_image)[channel];
731 m_end = m_iterator + m_image->NumberOfPixels();
766 : m_image( i.m_image )
767 , m_iterator( i.m_iterator )
784 m_iterator = i.m_iterator;
800 return m_image !=
nullptr && m_iterator !=
nullptr;
828 operator bool() const noexcept
830 return m_iterator < m_end;
956 return i.m_iterator - j.m_iterator;
965 return i.m_iterator - j;
974 return i - j.m_iterator;
983 return i.m_iterator == j.m_iterator;
992 return i.m_iterator == j;
1001 return i == j.m_iterator;
1010 return i.m_iterator < j.m_iterator;
1018 return i.m_iterator < j;
1026 return i < j.m_iterator;
1031 const image_type* m_image =
nullptr;
1032 const sample* __restrict__ m_iterator =
nullptr;
1033 const sample* __restrict__ m_end =
nullptr;
1038 template <
class image_type,
class sample_po
inter>
1039 class roi_sample_iterator_base
1043 image_type* m_image =
nullptr;
1044 sample_pointer m_iterator =
nullptr;
1045 sample_pointer m_rowBegin =
nullptr;
1046 sample_pointer m_rowEnd =
nullptr;
1047 sample_pointer m_end =
nullptr;
1049 roi_sample_iterator_base() =
default;
1051 roi_sample_iterator_base( image_type& image,
const Rect& rect,
int channel )
1055 if ( m_image->ParseRect( r ) )
1057 if ( m_image->ParseChannel( channel ) )
1059 m_iterator = m_rowBegin = m_image->PixelAddress( r.
x0, r.
y0, channel );
1060 m_rowEnd = m_rowBegin + r.
Width();
1061 m_end = m_rowEnd + ((r.
Height() - 1)*m_image->Width());
1066 roi_sample_iterator_base( image_type& image, sample_pointer i, sample_pointer j )
1071 m_iterator = m_rowBegin = i;
1072 m_rowEnd = m_rowBegin + (j - i)%m_image->Width();
1076 roi_sample_iterator_base(
const roi_sample_iterator_base& i ) =
default;
1078 roi_sample_iterator_base& operator =(
const roi_sample_iterator_base& ) =
default;
1080 void Increment() noexcept
1082 if ( ++m_iterator == m_rowEnd )
1084 m_rowBegin += m_image->Width();
1085 m_rowEnd += m_image->Width();
1086 m_iterator = m_rowBegin;
1090 void Decrement() noexcept
1092 if ( m_iterator == m_rowBegin )
1094 m_rowBegin -= m_image->Width();
1095 m_rowEnd -= m_image->Width();
1096 m_iterator = m_rowEnd;
1101 void MoveBy(
int cols,
int rows ) noexcept
1103 cols += m_iterator - m_rowBegin;
1106 int w = m_rowEnd - m_rowBegin;
1113 int dy = rows * m_image->Width();
1116 m_iterator = m_rowBegin + cols;
1151 using iterator_base = roi_sample_iterator_base<GenericImage<P>,
sample*>;
1181 : iterator_base( image.EnsureUnique(), rect, channel )
1202 : iterator_base( image, i, j )
1222 return this->m_image !=
nullptr && this->m_iterator !=
nullptr;
1230 return *this->m_image;
1238 return this->m_iterator;
1247 operator bool() const noexcept
1249 return this->m_iterator < this->m_end;
1258 return *this->m_iterator;
1318 int w = this->m_rowEnd - this->m_rowBegin;
1319 iterator_base::MoveBy( delta%w, delta/w );
1334 int w = this->m_rowEnd - this->m_rowBegin;
1335 iterator_base::MoveBy( -delta%w, -delta/w );
1349 iterator_base::MoveBy( dx, dy );
1392 return i.m_iterator == j.m_iterator;
1401 return i.m_iterator == j;
1410 return i == j.m_iterator;
1419 return i.m_iterator < j.m_iterator;
1427 return i.m_iterator < j;
1435 return i < j.m_iterator;
1472 using iterator_base = roi_sample_iterator_base<const GenericImage<P>,
const sample*>;
1502 : iterator_base( image, rect, channel )
1523 : iterator_base( image, i, j )
1536 : iterator_base( i.m_image, i.m_rowBegin, i.m_end )
1551 this->m_image = i.m_image;
1552 this->m_iterator = i.m_iterator;
1553 this->m_rowBegin = i.m_rowBegin;
1554 this->m_rowEnd = i.m_rowEnd;
1555 this->m_end = i.m_end;
1570 return this->m_image !=
nullptr && this->m_iterator !=
nullptr;
1579 return *this->m_image;
1588 return this->m_iterator;
1597 operator bool() const noexcept
1599 return this->m_iterator < this->m_end;
1608 return *this->m_iterator;
1668 int w = this->m_rowEnd - this->m_rowBegin;
1669 iterator_base::MoveBy( delta%w, delta/w );
1684 int w = this->m_rowEnd - this->m_rowBegin;
1685 iterator_base::MoveBy( -delta%w, -delta/w );
1699 iterator_base::MoveBy( dx, dy );
1742 return i.m_iterator == j.m_iterator;
1751 return i.m_iterator == j;
1760 return i == j.m_iterator;
1769 return i.m_iterator < j.m_iterator;
1777 return i.m_iterator < j;
1785 return i < j.m_iterator;
1791 template <
class image_type,
class iterator_base,
class sample_po
inter,
class filter_type>
1792 class filter_sample_iterator_base :
public iterator_base
1796 filter_type m_filter;
1797 sample_pointer m_begin =
nullptr;
1799 filter_sample_iterator_base() =
default;
1801 filter_sample_iterator_base( image_type& image,
const filter_type& filter,
int channel )
1802 : iterator_base( image, channel )
1803 , m_filter( filter )
1804 , m_begin( iterator_base::m_iterator )
1806 JumpToNextValidSample();
1809 filter_sample_iterator_base( image_type& image,
const filter_type& filter, sample_pointer i, sample_pointer j )
1810 : iterator_base( image, i, j )
1811 , m_filter( filter )
1812 , m_begin( iterator_base::m_iterator )
1814 JumpToNextValidSample();
1817 filter_sample_iterator_base(
const iterator_base& i,
const filter_type& filter )
1818 : iterator_base( i )
1819 , m_filter( filter )
1820 , m_begin( iterator_base::m_iterator )
1822 JumpToNextValidSample();
1825 filter_sample_iterator_base(
const filter_sample_iterator_base& ) =
default;
1827 filter_sample_iterator_base& operator =(
const filter_sample_iterator_base& ) =
default;
1829 filter_sample_iterator_base& operator =(
const iterator_base& i ) noexcept
1831 (void)iterator_base::operator =( i );
1832 JumpToNextValidSample();
1836 void JumpToNextValidSample() noexcept
1838 while ( this->m_iterator < this->m_end && !this->m_filter( *this->m_iterator ) )
1842 void JumpToPrevValidSample() noexcept
1844 while ( this->m_iterator > this->m_begin && !this->m_filter( *this->m_iterator ) )
1886 public filter_sample_iterator_base<GenericImage<P>, sample_iterator, sample*, F>
1935 : iterator_base( image.EnsureUnique(), filter, channel )
1958 : iterator_base( image, filter, i, j )
1967 : iterator_base( i, filter )
1987 (void)iterator_base::operator =( i );
1997 return this->m_image !=
nullptr && this->m_iterator !=
nullptr;
2005 return *this->m_image;
2014 return this->m_filter;
2023 return this->m_filter;
2031 return this->m_iterator;
2041 operator bool() const noexcept
2043 return this->m_iterator < this->m_end;
2052 return *this->m_iterator;
2063 this->JumpToNextValidSample();
2074 sample* __restrict__ i0 = this->m_iterator++;
2075 this->JumpToNextValidSample();
2087 this->JumpToPrevValidSample();
2098 sample* __restrict__ i0 = this->m_iterator--;
2099 this->JumpToPrevValidSample();
2112 this->m_iterator += delta;
2113 this->JumpToNextValidSample();
2126 this->m_iterator -= delta;
2127 this->JumpToPrevValidSample();
2141 this->m_iterator += d;
2143 this->JumpToNextValidSample();
2145 this->JumpToPrevValidSample();
2182 return i.m_iterator - j.m_iterator;
2191 return i.m_iterator == j.m_iterator;
2200 return i.m_iterator == j;
2209 return i == j.m_iterator;
2218 return i.m_iterator < j.m_iterator;
2226 return i.m_iterator < j;
2234 return i < j.m_iterator;
2275 public filter_sample_iterator_base<const GenericImage<P>, const_sample_iterator, const sample*, F>
2324 : iterator_base( image, filter, channel )
2347 : iterator_base( image, filter, i, j )
2356 : iterator_base( i.m_image, filter, i.m_iterator, i.m_end )
2365 : iterator_base( i, filter )
2374 : iterator_base( i )
2394 (void)const_sample_iterator::operator =( i );
2395 this->JumpToNextValidSample();
2405 (void)iterator_base::operator =( i );
2415 return this->m_image !=
nullptr && this->m_iterator !=
nullptr;
2424 return *this->m_image;
2433 return this->m_filter;
2442 return this->m_filter;
2451 return this->m_iterator;
2461 operator bool() const noexcept
2463 return this->m_iterator < this->m_end;
2472 return *this->m_iterator;
2483 this->JumpToNextValidSample();
2494 sample* __restrict__ i0 = this->m_iterator++;
2495 this->JumpToNextValidSample();
2507 this->JumpToPrevValidSample();
2518 sample* __restrict__ i0 = this->m_iterator--;
2519 this->JumpToPrevValidSample();
2532 this->m_iterator += delta;
2533 this->JumpToNextValidSample();
2546 this->m_iterator -= delta;
2547 this->JumpToPrevValidSample();
2561 this->m_iterator += d;
2563 this->JumpToNextValidSample();
2565 this->JumpToPrevValidSample();
2602 return i.m_iterator - j.m_iterator;
2611 return i.m_iterator == j.m_iterator;
2620 return i.m_iterator == j;
2629 return i == j.m_iterator;
2638 return i.m_iterator < j.m_iterator;
2646 return i.m_iterator < j;
2654 return i < j.m_iterator;
2660 template <
class image_type,
class sample_po
inter,
class filter_type>
2661 class roi_filter_sample_iterator_base :
public roi_sample_iterator_base<image_type, sample_pointer>
2665 using roi_iterator_base = roi_sample_iterator_base<image_type, sample_pointer>;
2667 filter_type m_filter;
2668 sample_pointer m_begin =
nullptr;
2670 roi_filter_sample_iterator_base() =
default;
2672 roi_filter_sample_iterator_base( image_type& image,
const filter_type& filter,
const Rect& rect,
int channel )
2673 : roi_iterator_base( image, rect, channel )
2674 , m_filter( filter )
2675 , m_begin( roi_iterator_base::m_iterator )
2677 JumpToNextValidSample();
2680 roi_filter_sample_iterator_base( image_type& image,
const filter_type& filter, sample_pointer i, sample_pointer j )
2681 : roi_iterator_base( image, i, j )
2682 , m_filter( filter )
2683 , m_begin( roi_iterator_base::m_iterator )
2685 JumpToNextValidSample();
2688 roi_filter_sample_iterator_base(
const roi_iterator_base& i,
const filter_type& filter )
2689 : roi_iterator_base( i )
2690 , m_filter( filter )
2691 , m_begin( roi_iterator_base::m_iterator )
2693 JumpToNextValidSample();
2696 roi_filter_sample_iterator_base(
const roi_filter_sample_iterator_base& ) =
default;
2698 roi_filter_sample_iterator_base& operator =(
const roi_filter_sample_iterator_base& i ) =
default;
2700 roi_filter_sample_iterator_base& operator =(
const roi_iterator_base& i ) noexcept
2702 (void)roi_iterator_base::operator =( i );
2703 JumpToNextValidSample();
2707 void JumpToNextValidSample() noexcept
2709 while ( this->m_iterator < this->m_end && !this->m_filter( *this->m_iterator ) )
2710 roi_iterator_base::Increment();
2713 void JumpToPrevValidSample() noexcept
2715 while ( this->m_iterator > this->m_begin && !this->m_filter( *this->m_iterator ) )
2716 roi_iterator_base::Decrement();
2758 using iterator_base = roi_filter_sample_iterator_base<GenericImage<P>,
sample*, F>;
2791 : iterator_base( image.EnsureUnique(), filter, rect, channel )
2814 : iterator_base( image, filter, i, j )
2823 : iterator_base( i, filter )
2843 (void)iterator_base::operator =( i );
2853 return this->m_image !=
nullptr && this->m_iterator !=
nullptr;
2861 return *this->m_image;
2870 return this->m_filter;
2879 return this->m_filter;
2887 return this->m_iterator;
2896 operator bool() const noexcept
2898 return this->m_iterator < this->m_end;
2907 return *this->m_iterator;
2918 this->JumpToNextValidSample();
2931 this->JumpToNextValidSample();
2943 this->JumpToPrevValidSample();
2956 this->JumpToPrevValidSample();
2971 int w = this->m_rowEnd - this->m_rowBegin;
2972 return MoveBy( delta%w, delta/w );
2986 int w = this->m_rowEnd - this->m_rowBegin;
2987 return MoveBy( -delta%w, -delta/w );
3000 sample* __restrict__ i0 = this->m_iterator;
3001 iterator_base::MoveBy( dx, dy );
3002 if ( this->m_iterator >= i0 )
3003 this->JumpToNextValidSample();
3005 this->JumpToPrevValidSample();
3048 return i.m_iterator == j.m_iterator;
3057 return i.m_iterator == j;
3066 return i == j.m_iterator;
3075 return i.m_iterator < j.m_iterator;
3083 return i.m_iterator < j;
3091 return i < j.m_iterator;
3133 using iterator_base = roi_filter_sample_iterator_base<const GenericImage<P>,
const sample*, F>;
3166 : iterator_base( image, filter, rect, channel )
3189 : iterator_base( image, filter, i, j )
3198 : iterator_base( i, filter )
3218 (void)iterator_base::operator =( i );
3228 return this->m_image !=
nullptr && this->m_iterator !=
nullptr;
3237 return *this->m_image;
3246 return this->m_filter;
3255 return this->m_filter;
3264 return this->m_iterator;
3273 operator bool() const noexcept
3275 return this->m_iterator < this->m_end;
3284 return *this->m_iterator;
3295 this->JumpToNextValidSample();
3308 this->JumpToNextValidSample();
3320 this->JumpToPrevValidSample();
3333 this->JumpToPrevValidSample();
3348 int w = this->m_rowEnd - this->m_rowBegin;
3349 return MoveBy( delta%w, delta/w );
3363 int w = this->m_rowEnd - this->m_rowBegin;
3364 return MoveBy( -delta%w, -delta/w );
3377 const sample* __restrict__ i0 = this->m_iterator;
3378 iterator_base::MoveBy( dx, dy );
3379 if ( this->m_iterator >= i0 )
3380 this->JumpToNextValidSample();
3382 this->JumpToPrevValidSample();
3425 return i.m_iterator == j.m_iterator;
3434 return i.m_iterator == j;
3443 return i == j.m_iterator;
3452 return i.m_iterator < j.m_iterator;
3460 return i.m_iterator < j;
3468 return i < j.m_iterator;
3515 m_image->EnsureUnique();
3516 if ( !m_image->IsEmpty() )
3519 for (
int i = 0; i < m_iterator.Length(); ++i )
3520 m_iterator[i] = (*m_image)[i];
3521 m_end = m_iterator[0] + m_image->NumberOfPixels();
3541 return m_image !=
nullptr && !m_iterator.IsEmpty();
3558 return m_iterator[channel];
3566 operator bool() const noexcept
3568 return m_iterator[0] < m_end;
3575 sample& operator [](
int channel )
const noexcept
3577 return *m_iterator[channel];
3586 for (
int i = 0; i < m_iterator.Length(); ++i )
3599 for (
int i = 0; i < m_iterator.Length(); ++i )
3610 for (
int i = 0; i < m_iterator.Length(); ++i )
3623 for (
int i = 0; i < m_iterator.Length(); ++i )
3637 for (
int i = 0; i < m_iterator.Length(); ++i )
3638 m_iterator[i] += delta;
3651 for (
int i = 0; i < m_iterator.Length(); ++i )
3652 m_iterator[i] -= delta;
3707 return i.m_iterator[0] - j.m_iterator[0];
3716 return i.m_iterator[0] == j.m_iterator[0];
3725 return i.m_iterator[0] < j.m_iterator[0];
3730 image_type* m_image =
nullptr;
3731 iterator_type m_iterator;
3732 const sample* __restrict__ m_end =
nullptr;
3778 if ( !m_image->IsEmpty() )
3781 for (
int i = 0; i < m_iterator.Length(); ++i )
3782 m_iterator[i] = (*m_image)[i];
3783 m_end = m_iterator[0] + m_image->NumberOfPixels();
3803 return m_image !=
nullptr && !m_iterator.IsEmpty();
3821 return m_iterator[channel];
3829 operator bool() const noexcept
3831 return m_iterator[0] < m_end;
3838 const sample& operator [](
int channel )
const noexcept
3840 return *m_iterator[channel];
3849 for (
int i = 0; i < m_iterator.Length(); ++i )
3862 for (
int i = 0; i < m_iterator.Length(); ++i )
3873 for (
int i = 0; i < m_iterator.Length(); ++i )
3886 for (
int i = 0; i < m_iterator.Length(); ++i )
3900 for (
int i = 0; i < m_iterator.Length(); ++i )
3901 m_iterator[i] += delta;
3914 for (
int i = 0; i < m_iterator.Length(); ++i )
3915 m_iterator[i] -= delta;
3970 return i.m_iterator[0] - j.m_iterator[0];
3979 return i.m_iterator[0] == j.m_iterator[0];
3988 return i.m_iterator[0] < j.m_iterator[0];
3993 const image_type* m_image =
nullptr;
3994 iterator_type m_iterator;
3995 const sample* __restrict__ m_end =
nullptr;
4000 template <
class image_type,
class sample_po
inter>
4001 class roi_pixel_iterator_base
4007 image_type* m_image =
nullptr;
4008 iterator_type m_iterator;
4009 sample_pointer m_rowBegin =
nullptr;
4010 sample_pointer m_rowEnd =
nullptr;
4011 sample_pointer m_end =
nullptr;
4013 roi_pixel_iterator_base() =
default;
4015 roi_pixel_iterator_base( image_type& image,
const Rect& rect )
4019 if ( m_image->ParseRect( r ) )
4021 m_iterator = iterator_type( m_image->NumberOfChannels() );
4022 for (
int i = 0; i < m_iterator.Length(); ++i )
4023 m_iterator[i] = m_image->PixelAddress( r.
x0, r.
y0, i );
4024 m_rowBegin = m_iterator[0];
4025 m_rowEnd = m_rowBegin + r.
Width();
4026 m_end = m_rowEnd + ((r.
Height() - 1)*m_image->Width());
4030 roi_pixel_iterator_base(
const roi_pixel_iterator_base& ) =
default;
4032 roi_pixel_iterator_base& operator =(
const roi_pixel_iterator_base& ) =
default;
4034 void Increment() noexcept
4036 for (
int i = 0; i < m_iterator.Length(); ++i )
4038 if ( m_iterator[0] == m_rowEnd )
4040 int w = m_rowEnd - m_rowBegin;
4041 for (
int i = 0; i < m_iterator.Length(); ++i )
4042 m_iterator[i] += m_image->Width() - w;
4043 m_rowBegin += m_image->Width();
4044 m_rowEnd += m_image->Width();
4048 void Decrement() noexcept
4050 if ( m_iterator[0] == m_rowBegin )
4052 int w = m_rowEnd - m_rowBegin;
4053 for (
int i = 0; i < m_iterator.Length(); ++i )
4054 m_iterator[i] -= m_image->Width() - w;
4055 m_rowBegin -= m_image->Width();
4056 m_rowEnd -= m_image->Width();
4058 for (
int i = 0; i < m_iterator.Length(); ++i )
4062 void MoveBy(
int cols,
int rows ) noexcept
4064 int dx = m_iterator[0] - m_rowBegin;
4065 for (
int i = 0; i < m_iterator.Length(); ++i )
4066 m_iterator[i] -= dx;
4070 int w = m_rowEnd - m_rowBegin;
4077 int dy = rows * m_image->Width();
4078 for (
int i = 0; i < m_iterator.Length(); ++i )
4079 m_iterator[i] += dy + cols;
4115 using iterator_base = roi_pixel_iterator_base<GenericImage<P>,
sample*>;
4137 : iterator_base( image.EnsureUnique(), rect )
4157 return this->m_image !=
nullptr && !this->m_iterator.IsEmpty();
4165 return *this->m_image;
4174 return this->m_iterator[channel];
4183 operator bool() const noexcept
4185 return this->m_iterator[0] < this->m_end;
4192 sample& operator [](
int channel )
const noexcept
4194 return *this->m_iterator[channel];
4254 int w = this->m_rowEnd - this->m_rowBegin;
4255 iterator_base::MoveBy( delta%w, delta/w );
4270 int w = this->m_rowEnd - this->m_rowBegin;
4271 iterator_base::MoveBy( -delta%w, -delta/w );
4285 iterator_base::MoveBy( dx, dy );
4328 return i.m_iterator[0] == j.m_iterator[0];
4337 return i.m_iterator[0] < j.m_iterator[0];
4371 using iterator_base = roi_pixel_iterator_base<const GenericImage<P>,
const sample*>;
4393 : iterator_base( image, rect )
4413 return this->m_image !=
nullptr && !this->m_iterator.IsEmpty();
4422 return *this->m_image;
4431 return this->m_iterator[channel];
4440 operator bool() const noexcept
4442 return this->m_iterator[0] < this->m_end;
4449 const sample& operator [](
int channel )
const noexcept
4451 return *this->m_iterator[channel];
4511 int w = this->m_rowEnd - this->m_rowBegin;
4512 iterator_base::MoveBy( delta%w, delta/w );
4527 int w = this->m_rowEnd - this->m_rowBegin;
4528 iterator_base::MoveBy( -delta%w, -delta/w );
4542 iterator_base::MoveBy( dx, dy );
4585 return i.m_iterator[0] == j.m_iterator[0];
4594 return i.m_iterator[0] < j.m_iterator[0];
4600 template <
class image_type,
class iterator_base,
class sample_po
inter,
class filter_type>
4601 class filter_pixel_iterator_base :
public iterator_base
4605 filter_type m_filter;
4606 sample_pointer m_begin =
nullptr;
4608 filter_pixel_iterator_base() =
default;
4610 filter_pixel_iterator_base( image_type& image,
const filter_type& filter )
4611 : iterator_base( image )
4612 , m_filter( filter )
4613 , m_begin( iterator_base::m_iterator )
4615 JumpToNextValidSample();
4618 filter_pixel_iterator_base(
const iterator_base& i,
const filter_type& filter )
4619 : iterator_base( i )
4620 , m_filter( filter )
4621 , m_begin( iterator_base::m_iterator )
4623 JumpToNextValidSample();
4626 filter_pixel_iterator_base(
const filter_pixel_iterator_base& ) =
default;
4628 filter_pixel_iterator_base& operator =(
const filter_pixel_iterator_base& ) =
default;
4630 filter_pixel_iterator_base& operator =(
const iterator_base& i ) noexcept
4632 (void)iterator_base::operator =( i );
4633 JumpToNextValidSample();
4636 void JumpToNextValidSample() noexcept
4638 while ( this->m_iterator[0] < this->m_end && !this->m_filter( this->m_iterator ) )
4639 for (
int i = 0; i < this->m_iterator.Length(); ++i )
4640 ++this->m_iterator[i];
4643 void JumpToPrevValidSample() noexcept
4645 while ( this->m_iterator[0] > this->m_begin && !this->m_filter( this->m_iterator ) )
4646 for (
int i = 0; i < this->m_iterator.Length(); ++i )
4647 --this->m_iterator[i];
4690 public filter_pixel_iterator_base<GenericImage<P>, pixel_iterator, sample*, F>
4731 : iterator_base( image.EnsureUnique(), filter )
4740 : iterator_base( i, filter )
4760 (void)iterator_base::operator =( i );
4770 return this->m_image !=
nullptr && !this->m_iterator.IsEmpty();
4778 return *this->m_image;
4787 return this->m_filter;
4796 return this->m_filter;
4805 return this->m_iterator[channel];
4813 operator bool() const noexcept
4815 return this->m_iterator[0] < this->m_end;
4822 sample& operator [](
int channel )
const noexcept
4824 return *this->m_iterator[channel];
4834 for (
int i = 0; i < this->m_iterator.Length(); ++i )
4835 ++this->m_iterator[i];
4836 this->JumpToNextValidSample();
4848 for (
int i = 0; i < this->m_iterator.Length(); ++i )
4849 ++this->m_iterator[i];
4850 this->JumpToNextValidSample();
4861 for (
int i = 0; i < this->m_iterator.Length(); ++i )
4862 --this->m_iterator[i];
4863 this->JumpToPrevValidSample();
4875 for (
int i = 0; i < this->m_iterator.Length(); ++i )
4876 --this->m_iterator[i];
4877 this->JumpToPrevValidSample();
4890 for (
int i = 0; i < this->m_iterator.Length(); ++i )
4891 this->m_iterator[i] += delta;
4892 this->JumpToNextValidSample();
4905 for (
int i = 0; i < this->m_iterator.Length(); ++i )
4906 this->m_iterator[i] -= delta;
4907 this->JumpToPrevValidSample();
4921 for (
int i = 0; i < this->m_iterator.Length(); ++i )
4922 this->m_iterator[i] += d;
4924 this->JumpToNextValidSample();
4926 this->JumpToPrevValidSample();
4969 return i.m_iterator[0] == j.m_iterator[0];
4978 return i.m_iterator[0] < j.m_iterator[0];
5021 public filter_pixel_iterator_base<const GenericImage<P>, const_pixel_iterator, const sample*, F>
5062 : iterator_base( image, filter )
5071 : iterator_base( i, filter )
5091 (void)iterator_base::operator =( i );
5101 return this->m_image !=
nullptr && !this->m_iterator.IsEmpty();
5110 return *this->m_image;
5119 return this->m_filter;
5128 return this->m_filter;
5137 return this->m_iterator[channel];
5145 operator bool() const noexcept
5147 return this->m_iterator[0] < this->m_end;
5154 const sample& operator [](
int channel )
const noexcept
5156 return *this->m_iterator[channel];
5166 for (
int i = 0; i < this->m_iterator.Length(); ++i )
5167 ++this->m_iterator[i];
5168 this->JumpToNextValidSample();
5180 for (
int i = 0; i < this->m_iterator.Length(); ++i )
5181 ++this->m_iterator[i];
5182 this->JumpToNextValidSample();
5193 for (
int i = 0; i < this->m_iterator.Length(); ++i )
5194 --this->m_iterator[i];
5195 this->JumpToPrevValidSample();
5207 for (
int i = 0; i < this->m_iterator.Length(); ++i )
5208 --this->m_iterator[i];
5209 this->JumpToPrevValidSample();
5222 for (
int i = 0; i < this->m_iterator.Length(); ++i )
5223 this->m_iterator[i] += delta;
5224 this->JumpToNextValidSample();
5237 for (
int i = 0; i < this->m_iterator.Length(); ++i )
5238 this->m_iterator[i] -= delta;
5239 this->JumpToPrevValidSample();
5253 for (
int i = 0; i < this->m_iterator.Length(); ++i )
5254 this->m_iterator[i] += d;
5256 this->JumpToNextValidSample();
5258 this->JumpToPrevValidSample();
5301 return i.m_iterator[0] == j.m_iterator[0];
5310 return i.m_iterator[0] < j.m_iterator[0];
5316 template <
class image_type,
class sample_po
inter,
class filter_type>
5317 class roi_filter_pixel_iterator_base :
public roi_pixel_iterator_base<image_type, sample_pointer>
5321 using roi_iterator_base = roi_pixel_iterator_base<image_type, sample_pointer>;
5323 filter_type m_filter;
5324 sample_pointer m_begin =
nullptr;
5326 roi_filter_pixel_iterator_base() =
default;
5328 roi_filter_pixel_iterator_base( image_type& image,
const filter_type& filter,
const Rect& rect )
5329 : roi_iterator_base( image, rect )
5330 , m_filter( filter )
5331 , m_begin( roi_iterator_base::m_iterator )
5333 JumpToNextValidSample();
5336 roi_filter_pixel_iterator_base(
const roi_iterator_base& i,
const filter_type& filter )
5337 : roi_iterator_base( i )
5338 , m_filter( filter )
5339 , m_begin( roi_iterator_base::m_iterator )
5341 JumpToNextValidSample();
5344 roi_filter_pixel_iterator_base(
const roi_filter_pixel_iterator_base& ) =
default;
5346 roi_filter_pixel_iterator_base& operator =(
const roi_filter_pixel_iterator_base& ) =
default;
5348 roi_filter_pixel_iterator_base& operator =(
const roi_iterator_base& i ) noexcept
5350 (void)roi_iterator_base::operator =( i );
5351 JumpToNextValidSample();
5355 void JumpToNextValidSample() noexcept
5357 while ( this->m_iterator[0] < this->m_end && !this->m_filter( this->m_iterator ) )
5358 roi_iterator_base::Increment();
5361 void JumpToPrevValidSample() noexcept
5363 while ( this->m_iterator[0] > this->m_begin && !this->m_filter( this->m_iterator ) )
5364 roi_iterator_base::Decrement();
5406 using iterator_base = roi_filter_pixel_iterator_base<GenericImage<P>,
sample*, F>;
5431 : iterator_base( image.EnsureUnique(), filter, rect )
5440 : iterator_base( i, filter )
5459 (void)iterator_base::operator =( i );
5469 return this->m_image !=
nullptr && !this->m_iterator.IsEmpty();
5477 return *this->m_image;
5486 return this->m_filter;
5495 return this->m_filter;
5504 return this->m_iterator[channel];
5513 operator bool() const noexcept
5515 return this->m_iterator[0] < this->m_end;
5522 sample& operator [](
int channel )
const noexcept
5524 return *this->m_iterator[channel];
5535 this->JumpToNextValidSample();
5548 this->JumpToNextValidSample();
5560 this->JumpToPrevValidSample();
5573 this->JumpToPrevValidSample();
5588 int w = this->m_rowEnd - this->m_rowBegin;
5589 return MoveBy( delta%w, delta/w );
5603 int w = this->m_rowEnd - this->m_rowBegin;
5604 return MoveBy( -delta%w, -delta/w );
5617 sample* __restrict__ i0 = this->m_iterator[0];
5618 iterator_base::MoveBy( dx, dy );
5619 if ( this->m_iterator[0] >= i0 )
5620 this->JumpToNextValidSample();
5622 this->JumpToPrevValidSample();
5665 return i.m_iterator[0] == j.m_iterator[0];
5674 return i.m_iterator[0] < j.m_iterator[0];
5716 using iterator_base = roi_filter_pixel_iterator_base<const GenericImage<P>,
const sample*, F>;
5742 : iterator_base( image, filter, rect )
5751 : iterator_base( i, filter )
5771 (void)iterator_base::operator =( i );
5781 return this->m_image !=
nullptr && !this->m_iterator.IsEmpty();
5790 return *this->m_image;
5799 return this->m_filter;
5808 return this->m_filter;
5817 return this->m_iterator[channel];
5826 operator bool() const noexcept
5828 return this->m_iterator[0] < this->m_end;
5835 const sample& operator [](
int channel )
const noexcept
5837 return *this->m_iterator[channel];
5848 this->JumpToNextValidSample();
5861 this->JumpToNextValidSample();
5873 this->JumpToPrevValidSample();
5886 this->JumpToPrevValidSample();
5901 int w = this->m_rowEnd - this->m_rowBegin;
5902 return MoveBy( delta%w, delta/w );
5916 int w = this->m_rowEnd - this->m_rowBegin;
5917 return MoveBy( -delta%w, -delta/w );
5930 const sample* __restrict__ i0 = this->m_iterator[0];
5931 iterator_base::MoveBy( dx, dy );
5932 if ( this->m_iterator[0] >= i0 )
5933 this->JumpToNextValidSample();
5935 this->JumpToPrevValidSample();
5978 return i.m_iterator[0] == j.m_iterator[0];
5987 return i.m_iterator[0] < j.m_iterator[0];
5999 return pixel_traits::IsFloatSample();
6008 return pixel_traits::IsComplexSample();
6017 return P::BytesPerSample();
6026 return P::BitsPerSample();
6039 return image.BitsPerSample() == BitsPerSample() &&
6040 image.IsFloatSample() == IsFloatSample() &&
6041 image.IsComplexSample() == IsComplexSample();
6062 m_data =
new Data(
this );
6099 image.m_data->Attach(
this );
6100 m_data = image.m_data;
6101 m_status = image.m_status;
6106 m_data =
new Data(
this );
6107 (void)Assign( image );
6115 , m_data( image.m_data )
6117 image.m_data =
nullptr;
6135 m_data =
new Data(
this );
6136 (void)Assign( image );
6182 m_data =
new Data(
this );
6183 (void)Assign( image, rect, firstChannel, lastChannel );
6204 GenericImage(
int width,
int height, color_space colorSpace = ColorSpace::Gray )
6206 m_data =
new Data(
this );
6227 m_data =
new Data(
this );
6252 m_data =
new Data(
this, handle );
6283 GenericImage(
void*,
int width,
int height, color_space colorSpace = ColorSpace::Gray )
6308 if ( m_data !=
nullptr )
6335 return m_data->IsShared();
6350 return m_data->IsUnique();
6367 if ( m_data->IsShared() )
6371 local->m_data->Allocate( m_width, m_height, m_numberOfChannels, m_colorSpace );
6372 local->m_RGBWS = m_RGBWS;
6373 local->m_selected = m_selected;
6374 local->m_savedSelections = m_savedSelections;
6375 local->m_status = m_status;
6376 for (
int c = 0; c < m_numberOfChannels; ++c )
6377 P::Copy( (*local)[c], m_channelData( c ), NumberOfPixels() );
6379 local->m_data->Attach(
this );
6381 m_data = local->m_data;
6403 if ( !m_data->IsUnique() )
6405 Data* newData = m_data->Clone(
this );
6446 m_data->SynchronizeWithSharedImage();
6485 int numberOfChannels = 1,
6486 color_space colorSpace = ColorSpace::Gray )
6488 if ( !m_data->IsUnique() )
6490 Data* newData =
new Data(
this );
6494 m_data->Allocate( width, height, numberOfChannels, colorSpace );
6510 int numberOfChannels = 1,
6511 color_space colorSpace = ColorSpace::Gray )
6513 return AllocateData( rect.
Width(), rect.
Height(), numberOfChannels, colorSpace );
6529 if ( !m_data->IsEmpty() )
6530 if ( m_data->IsUnique() )
6531 m_data->Deallocate();
6534 Data* newData =
new Data(
this );
6598 int numberOfChannels = 1, color_space colorSpace = ColorSpace::Gray )
6600 if ( !m_data->IsUnique() )
6602 if ( m_data->IsShared() )
6603 throw Error(
"GenericImage::ImportData(): Invalid operation for an aliased shared image" );
6604 Data* newData =
new Data(
this );
6608 m_data->Import( data, width, height, numberOfChannels, colorSpace );
6649 if ( !m_data->IsUnique() )
6650 throw Error(
"GenericImage::ReleaseData(): Invalid operation for an aliased image" );
6651 sample** data = m_data->Release();
6664 return BytesPerSample() *
size_type( m_width );
6673 return BytesPerSample() * NumberOfPixels();
6684 return ChannelSize() *
size_type( m_numberOfChannels );
6704 return ChannelSize() * NumberOfAlphaChannels();
6723 PCL_PRECONDITION( 0 <= channel && channel < m_numberOfChannels )
6725 return m_channelData( channel );
6736 PCL_PRECONDITION( 0 <= channel && channel < m_numberOfChannels )
6737 return m_channelData( channel );
6743 operator bool() const noexcept
6745 return m_data !=
nullptr && !m_data->IsEmpty();
6760 PCL_PRECONDITION( 0 <= channel && channel < m_numberOfChannels )
6761 return PixelData( channel );
6770 const sample* operator [](
int channel )
const noexcept
6772 PCL_PRECONDITION( 0 <= channel && channel < m_numberOfChannels )
6773 return PixelData( channel );
6785 PCL_PRECONDITION( 0 < m_numberOfChannels )
6786 return PixelData( 0 );
6797 PCL_PRECONDITION( 0 < m_numberOfChannels )
6798 return PixelData( 0 );
6822 PCL_PRECONDITION( 0 <= channel && channel < m_numberOfChannels )
6823 PCL_PRECONDITION( 0 <= y && y < m_height )
6825 return m_channelData( channel ) + RowOffset( y );
6836 PCL_PRECONDITION( 0 <= channel && channel < m_numberOfChannels )
6837 PCL_PRECONDITION( 0 <= y && y < m_height )
6838 return m_channelData( channel ) + RowOffset( y );
6866 PCL_PRECONDITION( 0 <= channel && channel < m_numberOfChannels )
6867 PCL_PRECONDITION( 0 <= x && x < m_width )
6868 PCL_PRECONDITION( 0 <= y && y < m_height )
6870 return m_channelData( channel ) + PixelOffset( x, y );
6881 PCL_PRECONDITION( 0 <= channel && channel < m_numberOfChannels )
6882 PCL_PRECONDITION( 0 <= x && x < m_width )
6883 PCL_PRECONDITION( 0 <= y && y < m_height )
6884 return m_channelData( channel ) + PixelOffset( x, y );
6909 return PixelAddress( p.
x, p.
y, channel );
6921 return PixelAddress( p.
x, p.
y, channel );
6944 sample& operator ()(
int x,
int y,
int channel = 0 )
6946 return *PixelAddress( x, y, channel );
6965 sample operator ()(
int x,
int y,
int channel = 0 ) const noexcept
6967 return *PixelAddress( x, y, channel );
6989 return *PixelAddress( p, channel );
7007 return *PixelAddress( p, channel );
7019 return operator()( x, y, channel );
7031 return operator()( x, y, channel );
7043 return operator()( p, channel );
7056 return operator()( p, channel );
7151 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
7153 m_status = image.
Status();
7162 int n = 1 + lastChannel - firstChannel;
7171 if ( r == image.
Bounds() )
7172 for (
int c = 0; firstChannel <= lastChannel; ++c, ++firstChannel )
7173 P::Copy( m_channelData( c ), image[firstChannel], NumberOfPixels() );
7175 for (
int c = 0; firstChannel <= lastChannel; ++c, ++firstChannel )
7177 sample* f = m_channelData( c );
7179 for (
int y = 0; y < m_height; ++y, f += m_width, g += image.
Width() )
7180 P::Copy( f, g, m_width );
7187 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
7189 m_status = image.
Status();
7198 #define completeSelection (firstChannel == 0 && lastChannel == image.m_numberOfChannels-1 && r == image.Bounds())
7200 if ( m_data == image.m_data )
7203 if ( !completeSelection )
7205 GenericImage result( image, r, firstChannel, lastChannel );
7206 result.m_data->Attach(
this );
7208 m_data = result.m_data;
7216 if ( completeSelection )
7218 image.m_data->Attach(
this );
7220 m_data = image.m_data;
7225 #undef completeSelection
7227 int n = 1 + lastChannel - firstChannel;
7232 m_RGBWS = image.m_RGBWS;
7236 if ( r == image.
Bounds() )
7237 for (
int c = 0; firstChannel <= lastChannel; ++c, ++firstChannel )
7238 P::Copy( m_channelData( c ), image[firstChannel], NumberOfPixels() );
7240 for (
int c = 0; firstChannel <= lastChannel; ++c, ++firstChannel )
7242 sample* f = m_channelData( c );
7244 for (
int y = 0; y < m_height; ++y, f += m_width, g += image.m_width )
7245 P::Copy( f, g, m_width );
7260 return Assign( image );
7275 return Assign( image );
7278 #define TRANSFER_BODY() \
7279 if ( m_data != image.m_data ) \
7282 m_data = image.m_data; \
7283 (void)AbstractImage::operator =( image ); \
7284 image.m_data = nullptr; \
7320 #undef TRANSFER_BODY
7329 return Transfer( image );
7340 return Fill( scalar );
7348 x1.AbstractImage::Swap( x2 );
7354 #ifndef __PCL_NO_VECTOR_IMAGE_CONVERSION
7377 channel = m_channel;
7378 if ( y < 0 || y >= m_height || channel < 0 || channel >= m_numberOfChannels )
7381 P::Get( row.
Begin(), ScanLine( y, channel ), m_width );
7406 channel = m_channel;
7407 if ( x < 0 || x >= m_width || channel < 0 || channel >= m_numberOfChannels )
7410 const sample* v = PixelAddress( x, 0, channel );
7411 for (
int y = 0; y < m_height; ++y, v += m_width )
7421 return ColumnVector( x, channel );
7447 template <
typename T>
7448 void GetRow( T* buffer,
int y,
int channel = -1 )
const
7450 PCL_PRECONDITION( buffer != 0 )
7452 channel = m_channel;
7453 if ( y >= 0 && y < m_height && channel >= 0 && channel < m_numberOfChannels )
7454 P::Get( buffer, ScanLine( y, channel ), m_width );
7478 template <
typename T>
7481 PCL_PRECONDITION( buffer != 0 )
7483 channel = m_channel;
7484 if ( x >= 0 && x < m_width && channel >= 0 && channel < m_numberOfChannels )
7486 const sample* v = PixelAddress( x, 0, channel );
7487 for (
int y = 0; y < m_height; ++y, ++buffer, v += m_width )
7488 P::FromSample( *buffer, *v );
7513 template <
typename T>
7516 PCL_PRECONDITION( buffer != 0 )
7518 channel = m_channel;
7519 if ( y >= 0 && y < m_height && channel >= 0 && channel < m_numberOfChannels )
7520 P::Copy( ScanLine( y, channel ), buffer, m_width );
7545 template <
typename T>
7548 PCL_PRECONDITION( buffer != 0 )
7550 channel = m_channel;
7551 if ( x >= 0 && x < m_width && channel >= 0 && channel < m_numberOfChannels )
7553 sample* v = PixelAddress( x, 0, channel );
7554 for (
int y = 0; y < m_height; ++y, ++buffer, v += m_width )
7555 *v = P::ToSample( *buffer );
7573 if ( n > 0 && m_numberOfChannels > 0 )
7576 sample** oldData = m_pixelData;
7577 sample** newData =
nullptr;
7580 newData = m_allocator.AllocateChannelSlots( m_numberOfChannels+n );
7581 for (
int i = 0; i < m_numberOfChannels; ++i )
7582 newData[i] = oldData[i];
7583 for (
int i = 0; i < n; ++i )
7584 newData[m_numberOfChannels+i] = m_allocator.AllocatePixels( m_width, m_height );
7588 if ( newData !=
nullptr )
7590 for (
int i = 0; i < n; ++i )
7591 if ( newData[m_numberOfChannels+i] !=
nullptr )
7592 m_allocator.Deallocate( newData[m_numberOfChannels+i] );
7593 m_allocator.Deallocate( newData );
7598 m_allocator.SetSharedData( m_pixelData = newData );
7599 m_allocator.SetSharedGeometry( m_width, m_height, m_numberOfChannels += n );
7600 m_allocator.Deallocate( oldData );
7628 if ( data ==
nullptr )
7629 CreateAlphaChannels( 1 );
7630 else if ( m_numberOfChannels > 0 )
7633 sample** oldData = m_pixelData;
7634 sample** newData =
nullptr;
7637 newData = m_allocator.AllocateChannelSlots( m_numberOfChannels+1 );
7638 for (
int i = 0; i < m_numberOfChannels; ++i )
7639 newData[i] = oldData[i];
7640 newData[m_numberOfChannels] = data;
7644 if ( newData !=
nullptr )
7645 m_allocator.Deallocate( newData );
7649 m_allocator.SetSharedData( m_pixelData = newData );
7650 m_allocator.SetSharedGeometry( m_width, m_height, ++m_numberOfChannels );
7651 m_allocator.Deallocate( oldData );
7681 if ( IsShared() != image.
IsShared() )
7682 throw Error(
"GenericImage::ReleaseAlphaChannel(): Cannot release pixel data between local and shared images" );
7684 if ( channel < 0 || channel >= NumberOfAlphaChannels() )
7692 sample** newData =
nullptr;
7695 newData = image.m_allocator.AllocateChannelSlots( 1 );
7696 *newData = m_pixelData[c];
7700 if ( newData !=
nullptr )
7701 image.m_allocator.Deallocate( newData );
7707 image.m_pixelData = newData;
7708 image.m_width = m_width;
7709 image.m_height = m_height;
7710 image.m_numberOfChannels = 1;
7711 image.m_colorSpace = ColorSpace::Gray;
7712 image.m_data->UpdateSharedImage();
7715 m_pixelData[c] =
nullptr;
7716 ForgetAlphaChannel( channel );
7734 if ( channel >= 0 && channel < NumberOfAlphaChannels() )
7738 m_allocator.Deallocate( m_pixelData[c] );
7739 m_pixelData[c] =
nullptr;
7740 ForgetAlphaChannel( channel );
7764 if ( channel >= 0 && channel < NumberOfAlphaChannels() )
7767 sample** oldData = m_pixelData;
7768 sample** newData = m_allocator.AllocateChannelSlots( m_numberOfChannels-1 );
7771 int c = n0 + channel;
7773 for (
int i = 0; i < c; ++i )
7774 newData[i] = oldData[i];
7775 for (
int i = c, j = c; ++j < m_numberOfChannels; ++i )
7776 newData[i] = oldData[j];
7778 m_allocator.SetSharedData( m_pixelData = newData );
7779 m_allocator.SetSharedGeometry( m_width, m_height, --m_numberOfChannels );
7781 if ( m_channel >= n0 || m_lastChannel >= n0 )
7782 ResetChannelRange();
7784 m_allocator.Deallocate( oldData );
7797 int n = m_numberOfChannels;
7802 m_allocator.Deallocate( m_pixelData[--n] ), m_pixelData[n] =
nullptr;
7804 ForgetAlphaChannels();
7821 if ( m_numberOfChannels > n0 )
7824 sample** oldData = m_pixelData;
7825 sample** newData = m_allocator.AllocateChannelSlots( n0 );
7827 for (
int i = 0; i < n0; ++i )
7828 newData[i] = oldData[i];
7830 m_allocator.SetSharedData( m_pixelData = newData );
7831 m_allocator.SetSharedGeometry( m_width, m_height, m_numberOfChannels = n0 );
7833 if ( m_channel >= n0 || m_lastChannel >= n0 )
7834 ResetChannelRange();
7836 m_allocator.Deallocate( oldData );
7880 template <
typename T>
7884 if ( !ParseSelection( r, firstChannel, lastChannel ) )
7890 if ( m_status.IsInitializationEnabled() )
7891 m_status.Initialize(
"Filling image", N*(1 + lastChannel - firstChannel) );
7893 sample v = P::ToSample( scalar );
7895 if ( r == Bounds() )
7896 for (
int i = firstChannel; i <= lastChannel; ++i, m_status += N )
7897 P::Fill( m_pixelData[i], v, N );
7899 for (
int i = firstChannel, w = r.
Width(), h = r.
Height(); i <= lastChannel; ++i, m_status += N )
7903 for (
int j = 0; j < h; ++j, f += m_width )
7927 template <
typename T>
7929 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
7932 if ( !ParseSelection( r, firstChannel, lastChannel ) )
7938 if ( m_status.IsInitializationEnabled() )
7939 m_status.Initialize(
"Filling image", N*(1 + lastChannel - firstChannel) );
7941 if ( r == Bounds() )
7942 for (
int i = firstChannel, c = 0; i <= lastChannel; ++i, ++c, m_status += N )
7944 sample v = (c < values.
Length()) ? P::ToSample( values[c] ) : P::MinSampleValue();
7945 P::Fill( m_pixelData[i], v, N );
7948 for (
int i = firstChannel, c = 0, w = r.
Width(), h = r.
Height(); i <= lastChannel; ++i, ++c, m_status += N )
7951 sample v = (c < values.
Length()) ? P::ToSample( values[c] ) : P::MinSampleValue();
7953 for (
int j = 0; j < h; ++j, f += m_width )
7970 template <
typename T>
7973 GenericImage result( *
this, rect, firstChannel, lastChannel );
7974 (void)result.
Fill( scalar );
7989 template <
typename T>
7991 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
const
7993 GenericImage result( *
this, rect, firstChannel, lastChannel );
7994 (void)result.
Fill( values );
8014 return Fill( P::ToSample( 0.0 ), rect, firstChannel, lastChannel );
8033 return Fill( P::ToSample( 1.0 ), rect, firstChannel, lastChannel );
8051 return Fill( P::MinSampleValue(), rect, firstChannel, lastChannel );
8069 return Fill( P::MaxSampleValue(), rect, firstChannel, lastChannel );
8088 template <
typename T>
8092 if ( !ParseSelection( r, firstChannel, lastChannel ) )
8098 if ( m_status.IsInitializationEnabled() )
8099 m_status.Initialize(
"Inverting pixel samples", N*(1 + lastChannel - firstChannel) );
8101 sample v = P::ToSample( scalar );
8102 if ( r == Bounds() )
8103 for (
int i = firstChannel; i <= lastChannel; ++i, m_status += N )
8105 sample* __restrict__ f = m_pixelData[i];
8107 for (
size_type j = 0; j < N; ++j, ++f )
8111 for (
int i = firstChannel, w = r.
Width(), h = r.
Height(); i <= lastChannel; ++i, m_status += N )
8115 for (
int j = 0; j < h; ++j, f += m_width-w )
8118 for (
int k = 0; k < w; ++k, ++f )
8136 template <
typename T>
8139 GenericImage result( *
this, rect, firstChannel, lastChannel );
8140 (void)result.
Invert( scalar );
8163 return Invert( P::MaxSampleValue(), rect, firstChannel, lastChannel );
8179 GenericImage result( *
this, rect, firstChannel, lastChannel );
8212 if ( !ParseSelection( r, firstChannel, lastChannel ) )
8218 if ( m_status.IsInitializationEnabled() )
8219 m_status.Initialize(
"Bitwise Not", N*(1 + lastChannel - firstChannel) );
8221 if ( r == Bounds() )
8222 for (
int i = firstChannel; i <= lastChannel; ++i, m_status += N )
8224 sample* __restrict__ f = m_pixelData[i];
8226 for (
size_type j = 0; j < N; ++j, ++f )
8230 for (
int i = firstChannel, w = r.
Width(), h = r.
Height(); i <= lastChannel; ++i, m_status += N )
8234 for (
int j = 0; j < h; ++j, f += m_width-w )
8237 for (
int k = 0; k < w; ++k, ++f )
8261 template <
typename T>
8263 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
8266 if ( !ParseSelection( r, firstChannel, lastChannel ) )
8272 if ( m_status.IsInitializationEnabled() )
8273 m_status.Initialize(
"Truncating pixel samples", N*(1 + lastChannel - firstChannel) );
8275 sample b0 = P::ToSample( lowerBound );
8276 sample b1 = P::ToSample( upperBound );
8280 if ( r == Bounds() )
8281 for (
int i = firstChannel; i <= lastChannel; ++i, m_status += N )
8283 sample* __restrict__ f = m_pixelData[i];
8285 for (
size_type j = 0; j < N; ++j, ++f )
8292 for (
int i = firstChannel, w = r.
Width(), h = r.
Height(); i <= lastChannel; ++i, m_status += N )
8296 for (
int j = 0; j < h; ++j, f += m_width-w )
8299 for (
int k = 0; k < w; ++k, ++f )
8323 template <
typename T>
8325 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
const
8327 GenericImage result( *
this, rect, firstChannel, lastChannel );
8328 (void)result.
Truncate( lowerBound, upperBound );
8355 return Truncate( P::MinSampleValue(), P::MaxSampleValue(), rect, firstChannel, lastChannel );
8370 GenericImage result( *
this, rect, firstChannel, lastChannel );
8403 template <
typename T>
8405 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
8408 if ( !ParseSelection( r, firstChannel, lastChannel ) )
8412 size_type Ns = N*(1 + lastChannel - firstChannel);
8413 if ( m_status.IsInitializationEnabled() )
8414 m_status.Initialize(
"Rescaling pixel samples", Ns );
8416 sample b0 = P::ToSample( lowerBound );
8417 sample b1 = P::ToSample( upperBound );
8422 GetExtremePixelValues( v0, v1, r, firstChannel, lastChannel );
8423 if ( v0 == b0 && v1 == b1 )
8434 d = (double( b1 ) - double( b0 ))/(
double( v1 ) - double( v0 ));
8436 if ( r == Bounds() )
8437 for (
int i = firstChannel; i <= lastChannel; ++i, m_status += N )
8439 sample* __restrict__ f = m_pixelData[i];
8448 for (
size_type j = 0; j < N; ++j, ++f )
8449 *f = P::FloatToSample( d*(*f - v0) );
8454 for (
size_type j = 0; j < N; ++j, ++f )
8455 *f = P::FloatToSample( d*(*f - v0) + b0 );
8459 P::Fill( f, b0, N );
8465 for (
int i = firstChannel, w = r.
Width(), h = r.
Height(); i <= lastChannel; ++i, m_status += N )
8476 for (
int j = 0; j < h; ++j, f += m_width-w )
8479 for (
int k = 0; k < w; ++k, ++f )
8480 *f = P::FloatToSample( d*(*f - v0) );
8486 for (
int j = 0; j < h; ++j, f += m_width-w )
8489 for (
int k = 0; k < w; ++k, ++f )
8490 *f = P::FloatToSample( d*(*f - v0) + b0 );
8497 for (
int j = 0; j < h; ++j, f += m_width )
8498 P::Fill( f, b0, w );
8505 for (
int j = 0; j < h; ++j, f += m_width )
8526 template <
typename T>
8528 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
const
8530 GenericImage result( *
this, rect, firstChannel, lastChannel );
8531 (void)result.
Rescale( lowerBound, upperBound );
8553 return Rescale( P::MinSampleValue(), P::MaxSampleValue(), rect, firstChannel, lastChannel );
8568 GenericImage result( *
this, rect, firstChannel, lastChannel );
8607 template <
typename T>
8609 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
8612 if ( !ParseSelection( r, firstChannel, lastChannel ) )
8616 size_type Ns = N*(1 + lastChannel - firstChannel);
8617 if ( m_status.IsInitializationEnabled() )
8618 m_status.Initialize(
"Normalizing pixel samples", Ns );
8620 sample b0 = P::ToSample( lowerBound );
8621 sample b1 = P::ToSample( upperBound );
8626 GetExtremePixelValues( v0, v1, r, firstChannel, lastChannel );
8628 if ( v0 >= b0 && v1 <= b1 )
8639 d = (double( b1 ) - double( b0 ))/(
double( v1 ) - double( v0 ));
8641 if ( r == Bounds() )
8642 for (
int i = firstChannel; i <= lastChannel; ++i, m_status += N )
8644 sample* __restrict__ f = m_pixelData[i];
8653 for (
size_type j = 0; j < N; ++j, ++f )
8654 *f = P::FloatToSample( d*(*f - v0) );
8659 for (
size_type j = 0; j < N; ++j, ++f )
8660 *f = P::FloatToSample( d*(*f - v0) + b0 );
8664 P::Fill( f, b0, N );
8670 for (
int i = firstChannel, w = r.
Width(), h = r.
Height(); i <= lastChannel; ++i, m_status += N )
8681 for (
int j = 0; j < h; ++j, f += m_width-w )
8684 for (
int k = 0; k < w; ++k, ++f )
8685 *f = P::FloatToSample( d*(*f - v0) );
8691 for (
int j = 0; j < h; ++j, f += m_width-w )
8694 for (
int k = 0; k < w; ++k, ++f )
8695 *f = P::FloatToSample( d*(*f - v0) + b0 );
8702 for (
int j = 0; j < h; ++j, f += m_width )
8703 P::Fill( f, b0, w );
8710 for (
int j = 0; j < h; ++j, f += m_width )
8731 template <
typename T>
8733 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
const
8735 GenericImage result( *
this, rect, firstChannel, lastChannel );
8736 (void)result.
Normalize( lowerBound, upperBound );
8758 return Normalize( P::MinSampleValue(), P::MaxSampleValue(), rect, firstChannel, lastChannel );
8773 GenericImage result( *
this, rect, firstChannel, lastChannel );
8807 template <
typename T>
8809 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
8812 if ( !ParseSelection( r, firstChannel, lastChannel ) )
8818 if ( m_status.IsInitializationEnabled() )
8819 m_status.Initialize(
"Binarizing pixel samples", N*(1 + lastChannel - firstChannel) );
8821 sample t = P::ToSample( threshold );
8823 if ( r == Bounds() )
8824 for (
int i = firstChannel; i <= lastChannel; ++i, m_status += N )
8826 sample* __restrict__ f = m_pixelData[i];
8828 for (
size_type j = 0; j < N; ++j, ++f )
8829 *f = (*f < t) ? P::MinSampleValue() : P::MaxSampleValue();
8832 for (
int c = firstChannel, w = r.
Width(), h = r.
Height(); c <= lastChannel; ++c, m_status += N )
8836 for (
int j = 0; j < h; ++j, f += m_width-w )
8839 for (
int k = 0; k < w; ++k, ++f )
8840 *f = (*f < t) ? P::MinSampleValue() : P::MaxSampleValue();
8857 template <
typename T>
8859 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
const
8861 GenericImage result( *
this, rect, firstChannel, lastChannel );
8862 (void)result.
Binarize( threshold );
8884 return Binarize( (P::MinSampleValue() + P::MaxSampleValue())/2, rect, firstChannel, lastChannel );
8900 GenericImage result( *
this, rect, firstChannel, lastChannel );
8921 if ( !ParseSelection( r, firstChannel, lastChannel ) )
8927 if ( m_status.IsInitializationEnabled() )
8928 m_status.Initialize(
"Computing absolute value", N*(1 + lastChannel - firstChannel) );
8930 if ( r == Bounds() )
8931 for (
int i = firstChannel; i <= lastChannel; ++i, m_status += N )
8933 sample* __restrict__ f = m_pixelData[i];
8935 for (
size_type j = 0; j < N; ++j, ++f )
8939 for (
int i = firstChannel, w = r.
Width(), h = r.
Height(); i <= lastChannel; ++i, m_status += N )
8943 for (
int j = 0; j < h; ++j, f += m_width-w )
8946 for (
int k = 0; k < w; ++k, ++f )
8959 return SetAbsoluteValue( rect, firstChannel, lastChannel );
8974 GenericImage result( *
this, rect, firstChannel, lastChannel );
8986 template <
typename T>
8987 GenericImage& ApplyScalar( T scalar, image_op op = ImageOp::Mov,
8988 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
8990 if ( op == ImageOp::Div )
8991 if ( 1 + scalar == 1 )
8992 throw Error(
"Division by zero or insignificant scalar" );
8995 if ( !ParseSelection( r, firstChannel, lastChannel ) )
9001 if ( m_status.IsInitializationEnabled() )
9002 m_status.Initialize(
"Applying scalar: "
9004 +
' ' +
String( scalar ), N*(1 + lastChannel - firstChannel) );
9006 if ( r == Bounds() )
9007 for (
int i = firstChannel; i <= lastChannel; ++i, m_status += N )
9009 sample* __restrict__ f = m_pixelData[i];
9010 #define ITERATE( Op ) \
9012 for ( size_type j = 0; j < N; ++j, ++f ) \
9016 case ImageOp::Mov: ITERATE( Mov );
break;
9017 case ImageOp::Add: ITERATE( Add );
break;
9018 case ImageOp::Sub: ITERATE( Sub );
break;
9019 case ImageOp::Mul: ITERATE( Mul );
break;
9020 case ImageOp::Div: ITERATE( Div );
break;
9021 case ImageOp::Pow: ITERATE( Pow );
break;
9022 case ImageOp::Dif: ITERATE( Dif );
break;
9023 case ImageOp::Min: ITERATE( Min );
break;
9024 case ImageOp::Max: ITERATE( Max );
break;
9025 case ImageOp::Not: ITERATE( Not );
break;
9026 case ImageOp::Or: ITERATE( Or );
break;
9027 case ImageOp::Nor: ITERATE( Nor );
break;
9028 case ImageOp::And: ITERATE( And );
break;
9029 case ImageOp::Nand: ITERATE( Nand );
break;
9030 case ImageOp::Xor: ITERATE( Xor );
break;
9031 case ImageOp::Xnor: ITERATE( Xnor );
break;
9032 case ImageOp::ColorBurn: ITERATE( ColorBurn );
break;
9033 case ImageOp::LinearBurn: ITERATE( LinearBurn );
break;
9034 case ImageOp::Screen: ITERATE( Screen );
break;
9035 case ImageOp::ColorDodge: ITERATE( ColorDodge );
break;
9036 case ImageOp::Overlay: ITERATE( Overlay );
break;
9037 case ImageOp::SoftLight: ITERATE( SoftLight );
break;
9038 case ImageOp::HardLight: ITERATE( HardLight );
break;
9039 case ImageOp::VividLight: ITERATE( VividLight );
break;
9040 case ImageOp::LinearLight: ITERATE( LinearLight );
break;
9041 case ImageOp::PinLight: ITERATE( PinLight );
break;
9042 case ImageOp::Exclusion: ITERATE( Exclusion );
break;
9048 for (
int i = firstChannel, w = r.
Width(), h = r.
Height(); i <= lastChannel; ++i, m_status += N )
9050 sample* __restrict__ f = PixelAddress( r.
LeftTop(), i );
9051 #define ITERATE( Op ) \
9053 for ( int j = 0; j < h; ++j, f += m_width-w ) \
9056 for ( int k = 0; k < w; ++k, ++f ) \
9057 P::Op( *f, scalar ); \
9061 case ImageOp::Mov: ITERATE( Mov );
break;
9062 case ImageOp::Add: ITERATE( Add );
break;
9063 case ImageOp::Sub: ITERATE( Sub );
break;
9064 case ImageOp::Mul: ITERATE( Mul );
break;
9065 case ImageOp::Div: ITERATE( Div );
break;
9066 case ImageOp::Pow: ITERATE( Pow );
break;
9067 case ImageOp::Dif: ITERATE( Dif );
break;
9068 case ImageOp::Min: ITERATE( Min );
break;
9069 case ImageOp::Max: ITERATE( Max );
break;
9070 case ImageOp::Not: ITERATE( Not );
break;
9071 case ImageOp::Or: ITERATE( Or );
break;
9072 case ImageOp::Nor: ITERATE( Nor );
break;
9073 case ImageOp::And: ITERATE( And );
break;
9074 case ImageOp::Nand: ITERATE( Nand );
break;
9075 case ImageOp::Xor: ITERATE( Xor );
break;
9076 case ImageOp::Xnor: ITERATE( Xnor );
break;
9077 case ImageOp::ColorBurn: ITERATE( ColorBurn );
break;
9078 case ImageOp::LinearBurn: ITERATE( LinearBurn );
break;
9079 case ImageOp::Screen: ITERATE( Screen );
break;
9080 case ImageOp::ColorDodge: ITERATE( ColorDodge );
break;
9081 case ImageOp::Overlay: ITERATE( Overlay );
break;
9082 case ImageOp::SoftLight: ITERATE( SoftLight );
break;
9083 case ImageOp::HardLight: ITERATE( HardLight );
break;
9084 case ImageOp::VividLight: ITERATE( VividLight );
break;
9085 case ImageOp::LinearLight: ITERATE( LinearLight );
break;
9086 case ImageOp::PinLight: ITERATE( PinLight );
break;
9087 case ImageOp::Exclusion: ITERATE( Exclusion );
break;
9118 template <
typename T>
9120 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
9122 return ApplyScalar( scalar, op, rect, firstChannel, lastChannel );
9126 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
9129 return ApplyScalar( scalar, op, rect, firstChannel, lastChannel );
9130 return ApplyScalar( P::ToSample( scalar ), op, rect, firstChannel, lastChannel );
9133 GenericImage&
Apply(
double scalar, image_op op = ImageOp::Mov,
9134 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
9137 return ApplyScalar( scalar, op, rect, firstChannel, lastChannel );
9138 return ApplyScalar( P::ToSample( scalar ), op, rect, firstChannel, lastChannel );
9142 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
9145 return ApplyScalar( scalar, op, rect, firstChannel, lastChannel );
9146 return ApplyScalar( P::ToSample( scalar ), op, rect, firstChannel, lastChannel );
9150 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
9153 return ApplyScalar( scalar, op, rect, firstChannel, lastChannel );
9154 return ApplyScalar( P::ToSample( scalar ), op, rect, firstChannel, lastChannel );
9175 template <
typename T>
9177 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
const
9179 GenericImage result( *
this, rect, firstChannel, lastChannel );
9180 (void)result.
Apply( scalar, op );
9232 const Point& point =
Point( int_max ),
int channel = -1,
9233 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
9239 if ( !ParseChannel( channel ) )
9243 if ( p.
x == int_max || p.
y == int_max )
9248 if ( (r.
x0 -= p.
x) >= r.
x1 )
9252 else if ( p.
x >= m_width )
9257 if ( (r.
y0 -= p.
y) >= r.
y1 )
9261 else if ( p.
y >= m_height )
9267 lastChannel =
pcl::Min( lastChannel, firstChannel + m_numberOfChannels - channel - 1 );
9272 if ( m_status.IsInitializationEnabled() )
9273 m_status.Initialize(
"Applying image, op=" +
ImageOp::Id( op ), N*(1 + lastChannel - firstChannel) );
9275 if ( r == Bounds() && r == image.
Bounds() )
9276 for (
int i = channel, j = firstChannel; j <= lastChannel; ++i, ++j, m_status += N )
9278 sample* __restrict__ f = m_pixelData[i];
9279 const typename P1::sample* __restrict__ g = image[j];
9281 #define ITERATE( Op ) \
9283 for ( size_type k = 0; k < N; ++k, ++f, ++g ) \
9291 P::CopyMin( f, g, N );
9294 P::CopyMax( f, g, N );
9299 case ImageOp::Add: ITERATE( Add );
break;
9300 case ImageOp::Sub: ITERATE( Sub );
break;
9301 case ImageOp::Mul: ITERATE( Mul );
break;
9303 for (
size_type j = 0; j < N; ++j, ++f, ++g )
9307 *f = P::MaxSampleValue();
9309 case ImageOp::Pow: ITERATE( Pow );
break;
9310 case ImageOp::Dif: ITERATE( Dif );
break;
9311 case ImageOp::Not: ITERATE( Not );
break;
9312 case ImageOp::Or: ITERATE( Or );
break;
9313 case ImageOp::Nor: ITERATE( Nor );
break;
9314 case ImageOp::And: ITERATE( And );
break;
9315 case ImageOp::Nand: ITERATE( Nand );
break;
9316 case ImageOp::Xor: ITERATE( Xor );
break;
9317 case ImageOp::Xnor: ITERATE( Xnor );
break;
9318 case ImageOp::ColorBurn: ITERATE( ColorBurn );
break;
9319 case ImageOp::LinearBurn: ITERATE( LinearBurn );
break;
9320 case ImageOp::Screen: ITERATE( Screen );
break;
9321 case ImageOp::ColorDodge: ITERATE( ColorDodge );
break;
9322 case ImageOp::Overlay: ITERATE( Overlay );
break;
9323 case ImageOp::SoftLight: ITERATE( SoftLight );
break;
9324 case ImageOp::HardLight: ITERATE( HardLight );
break;
9325 case ImageOp::VividLight: ITERATE( VividLight );
break;
9326 case ImageOp::LinearLight: ITERATE( LinearLight );
break;
9327 case ImageOp::PinLight: ITERATE( PinLight );
break;
9328 case ImageOp::Exclusion: ITERATE( Exclusion );
break;
9336 for (
int i = channel, j = firstChannel, w = r.
Width(), h = r.
Height(); j <= lastChannel; ++i, ++j, m_status += N )
9338 sample* __restrict__ f = PixelAddress( p, i );
9341 #define ITERATE( Op ) \
9343 for ( int k = 0; k < h; ++k, f += m_width-w, g += image.Width()-w ) \
9346 for ( int l = 0; l < w; ++l, ++f, ++g ) \
9352 for (
int k = 0; k < h; ++k, f += m_width, g += image.
Width() )
9356 for (
int k = 0; k < h; ++k, f += m_width, g += image.
Width() )
9357 P::CopyMin( f, g, w );
9360 for (
int k = 0; k < h; ++k, f += m_width, g += image.
Width() )
9361 P::CopyMax( f, g, w );
9363 case ImageOp::Add: ITERATE( Add );
break;
9364 case ImageOp::Sub: ITERATE( Sub );
break;
9365 case ImageOp::Mul: ITERATE( Mul );
break;
9368 for (
int k = 0; k < h; ++k, f += m_width-w, g += image.
Width()-w )
9371 for (
int l = 0; l < w; ++l, ++f, ++g )
9375 *f = P::MaxSampleValue();
9378 case ImageOp::Pow: ITERATE( Pow );
break;
9379 case ImageOp::Dif: ITERATE( Dif );
break;
9380 case ImageOp::Not: ITERATE( Not );
break;
9381 case ImageOp::Or: ITERATE( Or );
break;
9382 case ImageOp::Nor: ITERATE( Nor );
break;
9383 case ImageOp::And: ITERATE( And );
break;
9384 case ImageOp::Nand: ITERATE( Nand );
break;
9385 case ImageOp::Xor: ITERATE( Xor );
break;
9386 case ImageOp::Xnor: ITERATE( Xnor );
break;
9387 case ImageOp::ColorBurn: ITERATE( ColorBurn );
break;
9388 case ImageOp::LinearBurn: ITERATE( LinearBurn );
break;
9389 case ImageOp::Screen: ITERATE( Screen );
break;
9390 case ImageOp::ColorDodge: ITERATE( ColorDodge );
break;
9391 case ImageOp::Overlay: ITERATE( Overlay );
break;
9392 case ImageOp::SoftLight: ITERATE( SoftLight );
break;
9393 case ImageOp::HardLight: ITERATE( HardLight );
break;
9394 case ImageOp::VividLight: ITERATE( VividLight );
break;
9395 case ImageOp::LinearLight: ITERATE( LinearLight );
break;
9396 case ImageOp::PinLight: ITERATE( PinLight );
break;
9397 case ImageOp::Exclusion: ITERATE( Exclusion );
break;
9421 const Point& point =
Point( int_max ),
int channel = -1,
9422 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
const
9424 int c0 = (channel < 0) ? m_channel : channel;
9428 (void)result.Apply( image, op,
Point( 0 ), 0, rect, firstChannel, lastChannel );
9468 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 );
9490 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
const
9492 GenericImage result( *
this, rect, firstChannel, lastChannel );
9493 (void)result.
Apply( transformation );
9519 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
const;
9524 #ifndef __PCL_IMAGE_NO_BITMAP
9579 if ( p.
x == int_max || p.
y == int_max )
9584 if ( (r.
x0 -= p.
x) >= r.
x1 )
9588 else if ( p.
x >= m_width )
9593 if ( (r.
y0 -= p.
y) >= r.
y1 )
9597 else if ( p.
y >= m_height )
9603 bool hasAlpha = HasAlphaChannels();
9611 if ( m_status.IsInitializationEnabled() )
9614 sample* __restrict__ fR =
nullptr;
9615 sample* __restrict__ fG =
nullptr;
9616 sample* __restrict__ fB =
nullptr;
9617 sample* __restrict__ fA =
nullptr;
9619 for (
int i = 0; i < h; ++i, ++p.
y, m_status += w )
9621 fR = PixelAddress( p, 0 );
9622 fG = PixelAddress( p, 1 );
9623 fB = PixelAddress( p, 2 );
9625 fA = PixelAddress( p, 3 );
9629 for (
int j = 0; j < w; ++j, ++fR, ++fG, ++fB, ++fA, ++g )
9633 uint8 A = Alpha( rgba );
9637 P::Mov( *fR, Red( rgba ) );
9638 P::Mov( *fG, Green( rgba ) );
9639 P::Mov( *fB, Blue( rgba ) );
9646 P::Mov( *fR, Red( rgba ) );
9647 P::Mov( *fG, Green( rgba ) );
9648 P::Mov( *fB, Blue( rgba ) );
9652 double k = PTLUT->pDLUTA[A];
9653 double k1 = PTLUT->p1DLUT8[A];
9655 P::FromSample( v, *fR ), P::Mov( *fR, k*Red( rgba ) + k1*v );
9656 P::FromSample( v, *fG ), P::Mov( *fG, k*Green( rgba ) + k1*v );
9657 P::FromSample( v, *fB ), P::Mov( *fB, k*Blue( rgba ) + k1*v );
9665 if ( m_status.IsInitializationEnabled() )
9668 sample* __restrict__ fK =
nullptr;
9669 sample* __restrict__ fA =
nullptr;
9671 for (
int i = 0; i < h; ++i, ++p.
y, m_status += w )
9673 fK = PixelAddress( p, 0 );
9675 fA = PixelAddress( p, 1 );
9679 for (
int j = 0; j < w; ++j, ++fK, ++fA, ++g )
9682 uint8 R = Red( rgba );
9683 uint8 G = Green( rgba );
9684 uint8 B = Blue( rgba );
9685 uint8 A = Alpha( rgba );
9692 P::Mov( *fK, K/255 );
9698 P::Mov( *fK, K/255 );
9702 P::FromSample( v, *fK );
9703 P::Mov( *fK, PTLUT->pDLUTA[A]*K + PTLUT->p1DLUT8[A]*v );
9727 GenericImage result( *
this, Bounds(), 0, m_numberOfChannels-1 );
9728 (void)result.
Blend( bitmap, point, rect );
9746 template <
typename T>
9749 return Apply( scalar, ImageOp::Mov, rect, firstChannel, lastChannel );
9755 template <
typename T>
9758 return Move( scalar, rect, firstChannel, lastChannel );
9771 template <
typename T>
9774 return Apply( scalar, ImageOp::Add, rect, firstChannel, lastChannel );
9780 template <
typename T>
9783 return Add( scalar );
9796 template <
typename T>
9799 GenericImage result( *
this, rect, firstChannel, lastChannel );
9800 (void)result.
Add( scalar );
9814 template <
typename T>
9817 return Apply( scalar, ImageOp::Sub, rect, firstChannel, lastChannel );
9823 template <
typename T>
9826 return Subtract( scalar, rect, firstChannel, lastChannel );
9832 template <
typename T>
9835 return Subtract( scalar );
9848 template <
typename T>
9851 GenericImage result( *
this, rect, firstChannel, lastChannel );
9866 template <
typename T>
9869 return Apply( scalar, ImageOp::Mul, rect, firstChannel, lastChannel );
9875 template <
typename T>
9878 return Multiply( scalar, rect, firstChannel, lastChannel );
9884 template <
typename T>
9887 return Multiply( scalar );
9900 template <
typename T>
9903 GenericImage result( *
this, rect, firstChannel, lastChannel );
9921 template <
typename T>
9924 return Apply( scalar, ImageOp::Div, rect, firstChannel, lastChannel );
9930 template <
typename T>
9933 return Divide( scalar, rect, firstChannel, lastChannel );
9939 template <
typename T>
9942 return Divide( scalar );
9958 template <
typename T>
9961 GenericImage result( *
this, rect, firstChannel, lastChannel );
9962 (void)result.
Divide( scalar );
9976 template <
typename T>
9979 return Apply( scalar, ImageOp::Pow, rect, firstChannel, lastChannel );
9985 template <
typename T>
9988 return Raise( scalar, rect, firstChannel, lastChannel );
9994 template <
typename T>
9997 return Raise( scalar );
10010 template <
typename T>
10013 GenericImage result( *
this, rect, firstChannel, lastChannel );
10014 (void)result.
Raise( scalar );
10029 template <
typename T>
10032 return Apply( scalar, ImageOp::Dif, rect, firstChannel, lastChannel );
10038 template <
typename T>
10041 return SetAbsoluteDifference( scalar, rect, firstChannel, lastChannel );
10055 template <
typename T>
10058 GenericImage result( *
this, rect, firstChannel, lastChannel );
10073 template <
typename T>
10076 return Apply( scalar, ImageOp::Min, rect, firstChannel, lastChannel );
10082 template <
typename T>
10085 return SetMinimum( scalar, rect, firstChannel, lastChannel );
10099 template <
typename T>
10102 GenericImage result( *
this, rect, firstChannel, lastChannel );
10117 template <
typename T>
10120 return Apply( scalar, ImageOp::Max, rect, firstChannel, lastChannel );
10126 template <
typename T>
10129 return SetMaximum( scalar, rect, firstChannel, lastChannel );
10143 template <
typename T>
10146 GenericImage result( *
this, rect, firstChannel, lastChannel );
10162 template <
typename T>
10165 return Apply( scalar, ImageOp::Or, rect, firstChannel, lastChannel );
10179 template <
typename T>
10182 return Apply( scalar, ImageOp::And, rect, firstChannel, lastChannel );
10196 template <
typename T>
10199 return Apply( scalar, ImageOp::Xor, rect, firstChannel, lastChannel );
10213 template <
typename T>
10216 return Apply( scalar, ImageOp::Nor, rect, firstChannel, lastChannel );
10230 template <
typename T>
10233 return Apply( scalar, ImageOp::Nand, rect, firstChannel, lastChannel );
10247 template <
typename T>
10250 return Apply( scalar, ImageOp::Xnor, rect, firstChannel, lastChannel );
10265 template <
class P1>
10267 const Point& point =
Point( int_max ),
int channel = -1,
10268 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10270 return Apply( image, ImageOp::Mov, point, channel, rect, firstChannel, lastChannel );
10276 template <
class P1>
10278 const Point& point =
Point( int_max ),
int channel = -1,
10279 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10281 return Move( image, point, channel, rect, firstChannel, lastChannel );
10294 template <
class P1>
10296 const Point& point =
Point( int_max ),
int channel = -1,
10297 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10299 return Apply( image, ImageOp::Add, point, channel, rect, firstChannel, lastChannel );
10305 template <
class P1>
10308 return Add( image );
10321 template <
class P1>
10323 const Point& point =
Point( int_max ),
int channel = -1,
10324 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10326 return Apply( image, ImageOp::Sub, point, channel, rect, firstChannel, lastChannel );
10332 template <
class P1>
10334 const Point& point =
Point( int_max ),
int channel = -1,
10335 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10337 return Subtract( image, point, channel, rect, firstChannel, lastChannel );
10343 template <
class P1>
10346 return Subtract( image );
10359 template <
class P1>
10361 const Point& point =
Point( int_max ),
int channel = -1,
10362 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10364 return Apply( image, ImageOp::Mul, point, channel, rect, firstChannel, lastChannel );
10370 template <
class P1>
10372 const Point& point =
Point( int_max ),
int channel = -1,
10373 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10375 return Multiply( image, point, channel, rect, firstChannel, lastChannel );
10381 template <
class P1>
10384 return Multiply( image );
10401 template <
class P1>
10403 const Point& point =
Point( int_max ),
int channel = -1,
10404 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10406 return Apply( image, ImageOp::Div, point, channel, rect, firstChannel, lastChannel );
10412 template <
class P1>
10414 const Point& point =
Point( int_max ),
int channel = -1,
10415 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10417 return Divide( image, point, channel, rect, firstChannel, lastChannel );
10423 template <
class P1>
10426 return Divide( image );
10440 template <
class P1>
10442 const Point& point =
Point( int_max ),
int channel = -1,
10443 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10445 return Apply( image, ImageOp::Pow, point, channel, rect, firstChannel, lastChannel );
10451 template <
class P1>
10453 const Point& point =
Point( int_max ),
int channel = -1,
10454 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10456 return Raise( image, point, channel, rect, firstChannel, lastChannel );
10462 template <
class P1>
10465 return Raise( image );
10479 template <
class P1>
10481 const Point& point =
Point( int_max ),
int channel = -1,
10482 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10484 return Apply( image, ImageOp::Dif, point, channel, rect, firstChannel, lastChannel );
10490 template <
class P1>
10492 const Point& point =
Point( int_max ),
int channel = -1,
10493 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10495 return SetAbsoluteDifference( image, point, channel, rect, firstChannel, lastChannel );
10509 template <
class P1>
10511 const Point& point =
Point( int_max ),
int channel = -1,
10512 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10514 return Apply( image, ImageOp::Min, point, channel, rect, firstChannel, lastChannel );
10520 template <
class P1>
10522 const Point& point =
Point( int_max ),
int channel = -1,
10523 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10525 return SetMinimum( image, point, channel, rect, firstChannel, lastChannel );
10539 template <
class P1>
10541 const Point& point =
Point( int_max ),
int channel = -1,
10542 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10544 return Apply( image, ImageOp::Max, point, channel, rect, firstChannel, lastChannel );
10550 template <
class P1>
10552 const Point& point =
Point( int_max ),
int channel = -1,
10553 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10555 return SetMaximum( image, point, channel, rect, firstChannel, lastChannel );
10569 template <
class P1>
10571 const Point& point =
Point( int_max ),
int channel = -1,
10572 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10574 return Apply( image, ImageOp::Or, point, channel, rect, firstChannel, lastChannel );
10588 template <
class P1>
10590 const Point& point =
Point( int_max ),
int channel = -1,
10591 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10593 return Apply( image, ImageOp::And, point, channel, rect, firstChannel, lastChannel );
10607 template <
class P1>
10609 const Point& point =
Point( int_max ),
int channel = -1,
10610 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10612 return Apply( image, ImageOp::Xor, point, channel, rect, firstChannel, lastChannel );
10626 template <
class P1>
10628 const Point& point =
Point( int_max ),
int channel = -1,
10629 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10631 return Apply( image, ImageOp::Nor, point, channel, rect, firstChannel, lastChannel );
10645 template <
class P1>
10647 const Point& point =
Point( int_max ),
int channel = -1,
10648 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10650 return Apply( image, ImageOp::Nand, point, channel, rect, firstChannel, lastChannel );
10664 template <
class P1>
10666 const Point& point =
Point( int_max ),
int channel = -1,
10667 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10669 return Apply( image, ImageOp::Xnor, point, channel, rect, firstChannel, lastChannel );
10711 template <
class P1>
10713 const Point& point =
Point( int_max ),
int channel = -1,
10714 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10720 if ( !ParseChannel( channel ) )
10724 if ( p.
x == int_max || p.
y == int_max )
10729 if ( (r.
x0 -= p.
x) >= r.
x1 )
10733 else if ( p.
x >= m_width )
10738 if ( (r.
y0 -= p.
y) >= r.
y1 )
10742 else if ( p.
y >= m_height )
10748 lastChannel =
pcl::Min( lastChannel, firstChannel + m_numberOfChannels - channel - 1 );
10754 if ( m_status.IsInitializationEnabled() )
10755 m_status.Initialize(
"Exchanging pixel samples", N*(1 + lastChannel - firstChannel) );
10757 if ( r == Bounds() && r == image.
Bounds() )
10758 for (
int i = channel, j = firstChannel; j <= lastChannel; ++i, ++j, m_status += N )
10760 sample* __restrict__ f = m_pixelData[i];
10761 typename P1::sample* __restrict__ g = image[j];
10763 for (
size_type k = 0; k < N; ++k, ++f, ++g )
10766 P1::FromSample( *f, *g );
10767 P::FromSample( *g, t );
10771 for (
int i = channel, j = firstChannel, w = r.
Width(), h = r.
Height(); j <= lastChannel; ++i, ++j, m_status += N )
10773 sample* __restrict__ f = PixelAddress( p, i );
10776 for (
int k = 0; k < h; ++k, f += m_width-w, g += image.
Width()-w )
10779 for (
int l = 0; l < w; ++l, ++f, ++g )
10782 P1::FromSample( *f, *g );
10783 P::FromSample( *g, t );
10794 template <
class P1>
10796 const Point& point =
Point( int_max ),
int channel = -1,
10797 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
10799 return Exchange( image, point, channel, rect, firstChannel, lastChannel );
10824 int maxProcessors = 0 )
const
10827 if ( !ParseSelection( r, firstChannel, lastChannel ) )
10831 if ( m_status.IsInitializationEnabled() )
10832 m_status.Initialize(
"Computing minimum pixel sample value", N );
10835 bool useAffinity = m_parallel && Thread::IsRootThread();
10837 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
10838 threads.
Add(
new MinThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
10839 if ( threads.
Length() > 1 )
10842 for ( MinThread& thread : threads )
10843 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
10844 for ( MinThread& thread : threads )
10850 sample min = P::MinSampleValue();
10852 if ( threads[i].count > 0 )
10854 min = threads[i].min;
10855 while ( ++i < threads.
Length() )
10856 if ( threads[i].count > 0 )
10857 if ( threads[i].min < min )
10858 min = threads[i].min;
10873 int maxProcessors = 0 )
const
10875 return MinimumSampleValue( rect, firstChannel, lastChannel, maxProcessors );
10898 int firstChannel = -1,
int lastChannel = -1,
int maxProcessors = 0 )
const
10901 if ( !ParseSelection( r, firstChannel, lastChannel ) )
10905 if ( m_status.IsInitializationEnabled() )
10906 m_status.Initialize(
"Computing maximum pixel sample value", N );
10909 bool useAffinity = m_parallel && Thread::IsRootThread();
10911 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
10912 threads.
Add(
new MaxThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
10913 if ( threads.
Length() > 1 )
10916 for ( MaxThread& thread : threads )
10917 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
10918 for ( MaxThread& thread : threads )
10924 sample max = P::MinSampleValue();
10926 if ( threads[i].count > 0 )
10928 max = threads[i].max;
10929 while ( ++i < threads.
Length() )
10930 if ( threads[i].count > 0 )
10931 if ( max < threads[i].max )
10932 max = threads[i].max;
10947 int maxProcessors = 0 )
const
10949 return MaximumSampleValue( rect, firstChannel, lastChannel, maxProcessors );
10978 template <
typename T>
10980 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
10981 int maxProcessors = 0 )
const
10984 if ( !ParseSelection( r, firstChannel, lastChannel ) )
10987 P::FromSample( min, P::MinSampleValue() );
10993 if ( m_status.IsInitializationEnabled() )
10994 m_status.Initialize(
"Computing extreme pixel sample values", N );
10997 bool useAffinity = m_parallel && Thread::IsRootThread();
10999 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
11000 threads.
Add(
new MinMaxThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
11001 if ( threads.
Length() > 1 )
11004 for ( MinMaxThread& thread : threads )
11005 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
11006 for ( MinMaxThread& thread : threads )
11012 sample vmin = P::MinSampleValue();
11013 sample vmax = P::MinSampleValue();
11015 if ( threads[i].count > 0 )
11017 vmin = threads[i].min;
11018 vmax = threads[i].max;
11019 while ( ++i < threads.
Length() )
11020 if ( threads[i].count > 0 )
11022 if ( threads[i].min < vmin )
11023 vmin = threads[i].min;
11024 if ( vmax < threads[i].max )
11025 vmax = threads[i].max;
11032 P::FromSample( min, vmin );
11033 P::FromSample( max, vmax );
11042 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
11043 int maxProcessors = 0 )
const
11045 GetExtremeSampleValues( min, max, rect, firstChannel, lastChannel, maxProcessors );
11075 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
11076 int maxProcessors = 0 )
const
11079 if ( !ParseSelection( r, firstChannel, lastChannel ) )
11083 return P::MinSampleValue();
11087 if ( m_status.IsInitializationEnabled() )
11088 m_status.Initialize(
"Locating minimum pixel sample value", N );
11091 bool useAffinity = m_parallel && Thread::IsRootThread();
11093 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
11094 threads.
Add(
new MinPosThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
11095 if ( threads.
Length() > 1 )
11098 for ( MinPosThread& thread : threads )
11099 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
11100 for ( MinPosThread& thread : threads )
11107 sample min = P::MinSampleValue();
11109 if ( threads[i].count > 0 )
11111 min = threads[i].min;
11112 xmin = threads[i].pmin.x;
11113 ymin = threads[i].pmin.y;
11114 while ( ++i < threads.
Length() )
11115 if ( threads[i].count > 0 )
11116 if ( threads[i].min < min )
11118 min = threads[i].min;
11119 xmin = threads[i].pmin.x;
11120 ymin = threads[i].pmin.y;
11153 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
11154 int maxProcessors = 0 )
const
11156 return LocateMinimumSampleValue( pmin.
x, pmin.
y, rect, firstChannel, lastChannel, maxProcessors );
11165 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
11166 int maxProcessors = 0 )
const
11168 return LocateMinimumSampleValue( xmin, ymin, rect, firstChannel, lastChannel, maxProcessors );
11177 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
11178 int maxProcessors = 0 )
const
11180 return LocateMinimumSampleValue( pmin, rect, firstChannel, lastChannel, maxProcessors );
11210 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
11211 int maxProcessors = 0 )
const
11214 if ( !ParseSelection( r, firstChannel, lastChannel ) )
11218 return P::MaxSampleValue();
11222 if ( m_status.IsInitializationEnabled() )
11223 m_status.Initialize(
"Locating maximum pixel sample value", N );
11226 bool useAffinity = m_parallel && Thread::IsRootThread();
11228 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
11229 threads.
Add(
new MaxPosThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
11230 if ( threads.
Length() > 1 )
11233 for ( MaxPosThread& thread : threads )
11234 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
11235 for ( MaxPosThread& thread : threads )
11242 sample max = P::MinSampleValue();
11244 if ( threads[i].count > 0 )
11246 max = threads[i].max;
11247 xmax = threads[i].pmax.x;
11248 ymax = threads[i].pmax.y;
11249 while ( ++i < threads.
Length() )
11250 if ( threads[i].count > 0 )
11251 if ( max < threads[i].max )
11253 max = threads[i].max;
11254 xmax = threads[i].pmax.x;
11255 ymax = threads[i].pmax.y;
11288 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
11289 int maxProcessors = 0 )
const
11291 return LocateMaximumSampleValue( pmax.
x, pmax.
y, rect, firstChannel, lastChannel, maxProcessors );
11300 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
11301 int maxProcessors = 0 )
const
11303 return LocateMaximumSampleValue( xmax, ymax, rect, firstChannel, lastChannel, maxProcessors );
11312 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
11313 int maxProcessors = 0 )
const
11315 return LocateMaximumSampleValue( pmax, rect, firstChannel, lastChannel, maxProcessors );
11354 template <
typename T>
11356 int& xmax,
int& ymax, T& max,
11357 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
11358 int maxProcessors = 0 )
const
11361 if ( !ParseSelection( r, firstChannel, lastChannel ) )
11364 xmin = ymin = xmax = ymax = 0;
11365 P::FromSample( min, P::MinSampleValue() );
11371 if ( m_status.IsInitializationEnabled() )
11372 m_status.Initialize(
"Locating extreme pixel sample values", N );
11375 bool useAffinity = m_parallel && Thread::IsRootThread();
11377 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
11378 threads.
Add(
new MinMaxPosThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
11379 if ( threads.
Length() > 1 )
11382 for ( MinMaxPosThread& thread : threads )
11383 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
11384 for ( MinMaxPosThread& thread : threads )
11390 xmin = ymin = xmax = ymax = -1;
11391 sample vmin = P::MinSampleValue();
11392 sample vmax = P::MinSampleValue();
11394 if ( threads[i].count > 0 )
11396 vmin = threads[i].min;
11397 xmin = threads[i].pmin.x;
11398 ymin = threads[i].pmin.y;
11399 vmax = threads[i].max;
11400 xmax = threads[i].pmax.x;
11401 ymax = threads[i].pmax.y;
11402 while ( ++i < threads.
Length() )
11403 if ( threads[i].count > 0 )
11405 if ( threads[i].min < vmin )
11407 vmin = threads[i].min;
11408 xmin = threads[i].pmin.x;
11409 ymin = threads[i].pmin.y;
11411 if ( vmax < threads[i].max )
11413 vmax = threads[i].max;
11414 xmax = threads[i].pmax.x;
11415 ymax = threads[i].pmax.y;
11423 P::FromSample( min, vmin );
11424 P::FromSample( max, vmax );
11454 template <
typename T>
11456 Point& pmax, T& max,
11457 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
11458 int maxProcessors = 0 )
const
11460 LocateExtremeSampleValues( pmin.
x, pmin.
y, min,
11461 pmax.
x, pmax.
y, max,
11462 rect, firstChannel, lastChannel, maxProcessors );
11491 int maxProcessors = 0 )
const
11494 if ( !ParseSelection( r, firstChannel, lastChannel ) )
11498 if ( m_status.IsInitializationEnabled() )
11499 m_status.Initialize(
"Counting pixel samples", N );
11501 if ( !this->IsRangeClippingEnabled() )
11508 bool useAffinity = m_parallel && Thread::IsRootThread();
11510 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
11511 threads.
Add(
new CountThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
11512 if ( threads.
Length() > 1 )
11515 for ( CountThread& thread : threads )
11516 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
11517 for ( CountThread& thread : threads )
11524 for (
const CountThread& thread : threads )
11525 count += thread.count;
11560 double Mean(
const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
11561 int maxProcessors = 0 )
const
11564 if ( !ParseSelection( r, firstChannel, lastChannel ) )
11568 if ( m_status.IsInitializationEnabled() )
11569 m_status.Initialize(
"Computing mean pixel sample value", N );
11572 bool useAffinity = m_parallel && Thread::IsRootThread();
11574 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
11575 threads.
Add(
new SumThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
11576 if ( threads.
Length() > 1 )
11579 for ( SumThread& thread : threads )
11580 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
11581 for ( SumThread& thread : threads )
11590 for (
const SumThread& thread : threads )
11592 double y = thread.s - e;
11633 double Median(
const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
11634 int maxProcessors = 0 )
const
11637 if ( !ParseSelection( r, firstChannel, lastChannel ) )
11641 if ( m_status.IsInitializationEnabled() )
11642 m_status.Initialize(
"Computing median pixel sample value", N );
11644 if ( N <= __PCL_MEDIAN_HISTOGRAM_OVERHEAD )
11646 SmpThread S( *
this, r, firstChannel, lastChannel, 0, r.
Height() );
11653 double m = double( *
pcl::Select( S.samples.Begin(), S.samples.At( S.n ), S.n >> 1 ) )/double( P::MaxSampleValue() );
11659 m = (m + double( *
pcl::Select( S.samples.Begin(), S.samples.At( S.n ), (S.n >> 1)-1 ) )/double( P::MaxSampleValue() ))/2;
11665 bool useAffinity = m_parallel && Thread::IsRootThread();
11671 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
11672 threads <<
new MinMaxThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) );
11674 if ( threads.
Length() > 1 )
11677 for ( MinMaxThread& thread : threads )
11678 thread.Start( ThreadPriority::DefaultMax, useAffinity ? i++ : -1 );
11679 for ( MinMaxThread& thread : threads )
11685 sample slow = 0, shigh = 0;
11687 if ( threads[i].count > 0 )
11689 slow = threads[i].min;
11690 shigh = threads[i].max;
11691 count = threads[i].count;
11692 while ( ++i < threads.
Length() )
11693 if ( threads[i].count > 0 )
11695 if ( threads[i].min < slow )
11696 slow = threads[i].min;
11697 if ( shigh < threads[i].max )
11698 shigh = threads[i].max;
11699 count += threads[i].count;
11706 low = double( slow );
11707 high = double( shigh );
11710 const double eps = P::IsComplexSample() ? 2*std::numeric_limits<double>::epsilon() :
11711 (P::IsFloatSample() ? 2*std::numeric_limits<typename P::component>::epsilon() :
11712 0.5/
Pow2(
double( P::BitsPerSample() ) ));
11718 if ( high - low < eps )
11721 return low/double( P::MaxSampleValue() );
11725 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
11726 threads <<
new HistogramThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ), low, high );
11728 double mh = 0, l0 = low;
11731 for (
size_type n = 0, n2 = count >> 1, step = 0, it = 0;; ++it )
11734 if ( it == 0 && step )
11738 if ( threads.
Length() > 1 )
11741 for ( HistogramThread& thread : threads )
11742 thread.Start( ThreadPriority::DefaultMax, useAffinity ? i++ : -1 );
11743 for ( HistogramThread& thread : threads )
11753 if ( (count & 1) == 0 )
11757 for (
int i = 0; ; n += H[i++] )
11758 if ( n + H[i] > n2 )
11760 double range = high - low;
11761 high = (range * (i + 1))/(__PCL_MEDIAN_HISTOGRAM_LENGTH - 1) + low;
11762 low = (range * i)/(__PCL_MEDIAN_HISTOGRAM_LENGTH - 1) + low;
11763 if ( high - low < eps )
11769 return low/double( P::MaxSampleValue() );
11775 return (low + mh)/2/double( P::MaxSampleValue() );
11821 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
11822 int maxProcessors = 0 )
const
11824 if ( k < 0 || k > 1 )
11828 if ( !ParseSelection( r, firstChannel, lastChannel ) )
11832 if ( m_status.IsInitializationEnabled() )
11833 m_status.Initialize(
"Computing order statistic", N );
11835 if ( N <= __PCL_MEDIAN_HISTOGRAM_OVERHEAD )
11837 SmpThread S( *
this, r, firstChannel, lastChannel, 0, r.
Height() );
11842 return double( *
pcl::Select( S.samples.Begin(), S.samples.At( S.n ),
distance_type( k*(S.n - 1) ) ) )/double( P::MaxSampleValue() );
11846 bool useAffinity = m_parallel && Thread::IsRootThread();
11852 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
11853 threads <<
new MinMaxThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) );
11855 if ( threads.
Length() > 1 )
11858 for ( MinMaxThread& thread : threads )
11859 thread.Start( ThreadPriority::DefaultMax, useAffinity ? i++ : -1 );
11860 for ( MinMaxThread& thread : threads )
11866 sample slow = 0, shigh = 0;
11868 if ( threads[i].count > 0 )
11870 slow = threads[i].min;
11871 shigh = threads[i].max;
11872 count = threads[i].count;
11873 while ( ++i < threads.
Length() )
11874 if ( threads[i].count > 0 )
11876 if ( threads[i].min < slow )
11877 slow = threads[i].min;
11878 if ( shigh < threads[i].max )
11879 shigh = threads[i].max;
11880 count += threads[i].count;
11887 low = double( slow );
11888 high = double( shigh );
11891 const double eps = P::IsComplexSample() ? 2*std::numeric_limits<double>::epsilon() :
11892 (P::IsFloatSample() ? 2*std::numeric_limits<typename P::component>::epsilon() :
11893 0.5/
Pow2(
double( P::BitsPerSample() ) ));
11899 if ( k == 0 || high - low < eps )
11902 return low/double( P::MaxSampleValue() );
11907 return high/double( P::MaxSampleValue() );
11913 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
11914 threads <<
new HistogramThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ), low, high );
11918 if ( threads.
Length() > 1 )
11921 for ( HistogramThread& thread : threads )
11922 thread.Start( ThreadPriority::DefaultMax, useAffinity ? i++ : -1 );
11923 for ( HistogramThread& thread : threads )
11933 for (
int i = 0; ; n += H[i++] )
11934 if ( n + H[i] > index )
11936 double range = high - low;
11937 high = (range * (i + 1))/(__PCL_MEDIAN_HISTOGRAM_LENGTH - 1) + low;
11938 low = (range * i)/(__PCL_MEDIAN_HISTOGRAM_LENGTH - 1) + low;
11939 if ( high - low < eps )
11943 return low/double( P::MaxSampleValue() );
11985 int maxProcessors = 0 )
const
11988 if ( !ParseSelection( r, firstChannel, lastChannel ) )
11992 if ( m_status.IsInitializationEnabled() )
11993 m_status.Initialize(
"Computing variance", N );
11996 bool useAffinity = m_parallel && Thread::IsRootThread();
11998 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
11999 sumThreads.
Add(
new SumThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
12000 if ( sumThreads.
Length() > 1 )
12003 for ( SumThread& thread : sumThreads )
12004 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
12005 for ( SumThread& thread : sumThreads )
12009 sumThreads[0].Run();
12014 for (
const SumThread& thread : sumThreads )
12016 double y = thread.s - e;
12030 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
12031 varThreads.
Add(
new VarThread( *
this, mean, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
12032 if ( varThreads.
Length() > 1 )
12035 for ( VarThread& thread : varThreads )
12036 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
12037 for ( VarThread& thread : varThreads )
12041 varThreads[0].Run();
12043 double var = 0, eps = 0;
12044 for (
const VarThread& thread : varThreads )
12045 var += thread.var, eps += thread.eps;
12049 return (var - eps*eps/n)/(n - 1);
12084 double StdDev(
const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
12085 int maxProcessors = 0 )
const
12087 return pcl::Sqrt(
Variance( rect, firstChannel, lastChannel, maxProcessors ) );
12130 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
12131 int maxProcessors = 0 )
const
12134 if ( !ParseSelection( r, firstChannel, lastChannel ) )
12138 if ( m_status.IsInitializationEnabled() )
12139 m_status.Initialize(
"Computing average absolute deviation", N );
12142 bool useAffinity = m_parallel && Thread::IsRootThread();
12144 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
12145 threads.
Add(
new SumAbsDevThread( *
this, center, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
12146 if ( threads.
Length() > 1 )
12149 for ( SumAbsDevThread& thread : threads )
12150 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
12151 for ( SumAbsDevThread& thread : threads )
12160 for (
const SumAbsDevThread& thread : threads )
12162 double y = thread.s - e;
12199 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
12200 int maxProcessors = 0 )
const
12203 if ( !ParseSelection( r, firstChannel, lastChannel ) )
12207 if ( m_status.IsInitializationEnabled() )
12208 m_status.Initialize(
"Computing two-sided average absolute deviation", N );
12211 bool useAffinity = m_parallel && Thread::IsRootThread();
12213 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
12214 threads.
Add(
new TwoSidedSumAbsDevThread( *
this, center, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
12215 if ( threads.
Length() > 1 )
12218 for ( TwoSidedSumAbsDevThread& thread : threads )
12219 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
12220 for ( TwoSidedSumAbsDevThread& thread : threads )
12226 double s0 = 0, s1 = 0;
12227 double e0 = 0, e1 = 0;
12229 for (
const TwoSidedSumAbsDevThread& thread : threads )
12231 double y = thread.s0 - e0;
12236 y = thread.s1 - e1;
12247 return { (n0 > 0) ? s0/n0 : 0.0,
12248 (n1 > 0) ? s1/n1 : 0.0 };
12286 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
12287 int maxProcessors = 0 )
const
12290 if ( !ParseSelection( r, firstChannel, lastChannel ) )
12294 if ( m_status.IsInitializationEnabled() )
12295 m_status.Initialize(
"Computing median absolute deviation", N );
12297 if ( N <= __PCL_MEDIAN_HISTOGRAM_OVERHEAD )
12299 AbsDevSmpThread S( *
this, center, r, firstChannel, lastChannel, 0, r.
Height() );
12306 double m = *
pcl::Select( S.values.Begin(), S.values.At( S.n ), S.n >> 1 );
12312 m = (m + *
pcl::Select( S.values.Begin(), S.values.At( S.n ), (S.n >> 1)-1 ))/2;
12318 bool useAffinity = m_parallel && Thread::IsRootThread();
12324 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
12325 threads <<
new ExtremeAbsDevThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ), center );
12327 if ( threads.
Length() > 1 )
12330 for ( ExtremeAbsDevThread& thread : threads )
12331 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
12332 for ( ExtremeAbsDevThread& thread : threads )
12339 if ( threads[i].count > 0 )
12341 low = threads[i].minAbsDev;
12342 high = threads[i].maxAbsDev;
12343 count += threads[i].count;
12344 while ( ++i < threads.
Length() )
12345 if ( threads[i].count > 0 )
12347 if ( threads[i].minAbsDev < low )
12348 low = threads[i].minAbsDev;
12349 if ( threads[i].maxAbsDev > high )
12350 high = threads[i].maxAbsDev;
12351 count += threads[i].count;
12359 const double eps = 2*std::numeric_limits<double>::epsilon();
12360 if ( count == 0 || high - low < eps )
12367 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
12368 threads <<
new AbsDevHistogramThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ), center, low, high );
12370 double mh = 0, l0 = low;
12373 for (
size_type n = 0, n2 = count >> 1, step = 0, it = 0;; ++it )
12376 if ( it == 0 && step )
12380 if ( threads.
Length() > 1 )
12383 for ( AbsDevHistogramThread& thread : threads )
12384 thread.Start( ThreadPriority::DefaultMax, useAffinity ? i++ : -1 );
12385 for ( AbsDevHistogramThread& thread : threads )
12395 if ( (count & 1) == 0 )
12399 for (
int i = 0; ; n += H[i++] )
12400 if ( n + H[i] > n2 )
12402 double range = high - low;
12403 high = (range * (i + 1))/(__PCL_MEDIAN_HISTOGRAM_LENGTH - 1) + low;
12404 low = (range * i)/(__PCL_MEDIAN_HISTOGRAM_LENGTH - 1) + low;
12405 if ( high - low < eps )
12417 return (low + mh)/2;
12452 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
12453 int maxProcessors = 0 )
const
12456 if ( !ParseSelection( r, firstChannel, lastChannel ) )
12460 if ( m_status.IsInitializationEnabled() )
12461 m_status.Initialize(
"Computing two-sided median absolute deviation", N );
12463 if ( N <= __PCL_MEDIAN_HISTOGRAM_OVERHEAD )
12465 TwoSidedAbsDevSmpThread S( *
this, center, r, firstChannel, lastChannel, 0, r.
Height() );
12473 bool useAffinity = m_parallel && Thread::IsRootThread();
12475 double minLow = 0, minHigh = 0, maxLow = 0, maxHigh = 0;
12479 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
12480 threads <<
new TwoSidedExtremeAbsDevThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ), center );
12482 if ( threads.
Length() > 1 )
12485 for ( TwoSidedExtremeAbsDevThread& thread : threads )
12486 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
12487 for ( TwoSidedExtremeAbsDevThread& thread : threads )
12494 if ( threads[i].nLow > 0 )
12496 minLow = threads[i].minAbsDevLow;
12497 maxLow = threads[i].maxAbsDevLow;
12498 nLow = threads[i].nLow;
12499 while ( ++i < threads.
Length() )
12500 if ( threads[i].nLow > 0 )
12502 if ( threads[i].minAbsDevLow < minLow )
12503 minLow = threads[i].minAbsDevLow;
12504 if ( threads[i].maxAbsDevLow > maxLow )
12505 maxLow = threads[i].maxAbsDevLow;
12506 nLow += threads[i].nLow;
12512 if ( threads[i].nHigh > 0 )
12514 minHigh = threads[i].minAbsDevHigh;
12515 maxHigh = threads[i].maxAbsDevHigh;
12516 nHigh = threads[i].nHigh;
12517 while ( ++i < threads.
Length() )
12518 if ( threads[i].nHigh > 0 )
12520 if ( threads[i].minAbsDevHigh < minHigh )
12521 minHigh = threads[i].minAbsDevHigh;
12522 if ( threads[i].maxAbsDevHigh > maxHigh )
12523 maxHigh = threads[i].maxAbsDevHigh;
12524 nHigh += threads[i].nHigh;
12533 double sideLow, sideHigh;
12535 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
12536 threads <<
new TwoSidedAbsDevHistogramThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ), center, side, sideLow, sideHigh );
12538 const double eps = 2*std::numeric_limits<double>::epsilon();
12540 for ( side = 0; side < 2; ++side )
12549 sideLow = side ? minHigh : minLow;
12550 sideHigh = side ? maxHigh : maxLow;
12551 if ( sideHigh - sideLow < eps )
12557 double mh = 0, h0 = sideHigh;
12560 for (
size_type count = 0, n2 = n >> 1, step = 0, it = 0;; ++it )
12563 if ( it == 0 && step )
12567 if ( threads.
Length() > 1 )
12570 for ( TwoSidedAbsDevHistogramThread& thread : threads )
12571 thread.Start( ThreadPriority::DefaultMax, useAffinity ? i++ : -1 );
12572 for ( TwoSidedAbsDevHistogramThread& thread : threads )
12582 if ( (n & 1) == 0 )
12586 for (
int i = 0; ; count += H[i++] )
12587 if ( count + H[i] > n2 )
12589 double range = sideHigh - sideLow;
12590 sideHigh = (range * (i + 1))/(__PCL_MEDIAN_HISTOGRAM_LENGTH - 1) + sideLow;
12591 sideLow = (range * i)/(__PCL_MEDIAN_HISTOGRAM_LENGTH - 1) + sideLow;
12592 if ( sideHigh - sideLow < eps )
12596 mad[side] = sideLow;
12597 goto __madNextSide;
12601 mad[side] = (sideLow + mh)/2;
12602 goto __madNextSide;
12622 return { mad[0], mad[1] };
12670 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
12671 int maxProcessors = 0 )
const
12674 if ( !ParseSelection( r, firstChannel, lastChannel ) )
12678 double kd = k * sigma;
12679 if ( kd < 0 || 1 + kd == 1 )
12685 if ( m_status.IsInitializationEnabled() )
12686 m_status.Initialize(
"Computing biweight midvariance", N );
12689 bool useAffinity = m_parallel && Thread::IsRootThread();
12691 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
12692 threads.
Add(
new BWMVThread( *
this, center, kd, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
12693 if ( threads.
Length() > 1 )
12696 for ( BWMVThread& thread : threads )
12697 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
12698 for ( BWMVThread& thread : threads )
12704 double num = 0, den = 0;
12706 for (
const BWMVThread& thread : threads )
12718 return (n >= 2 && 1 + den != 1) ? (reducedLength ? nr : n)*num/den : 0.0;
12750 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
12751 int maxProcessors = 0 )
const
12754 if ( !ParseSelection( r, firstChannel, lastChannel ) )
12758 double kd0 = k * sigma.
low;
12759 double kd1 = k * sigma.
high;
12760 if ( kd0 < 0 || 1 + kd0 == 1 || kd1 < 0 || 1 + kd1 == 1 )
12766 if ( m_status.IsInitializationEnabled() )
12767 m_status.Initialize(
"Computing two-sided biweight midvariance", N );
12770 bool useAffinity = m_parallel && Thread::IsRootThread();
12772 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
12773 threads.
Add(
new TwoSidedBWMVThread( *
this, center, kd0, kd1, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
12774 if ( threads.
Length() > 1 )
12777 for ( TwoSidedBWMVThread& thread : threads )
12778 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
12779 for ( TwoSidedBWMVThread& thread : threads )
12785 double num0 = 0, den0 = 0, num1 = 0, den1 = 0;
12786 size_type n0 = 0, n1 = 0, nr0 = 0, nr1 = 0;
12787 for (
const TwoSidedBWMVThread& thread : threads )
12789 num0 += thread.num0;
12790 den0 += thread.den0;
12791 num1 += thread.num1;
12792 den1 += thread.den1;
12805 return { (n0 >= 2 && 1 + den0 != 1) ? (reducedLength ? nr0 : n0)*num0/den0 : 0.0,
12806 (n1 >= 2 && 1 + den1 != 1) ? (reducedLength ? nr1 : n1)*num1/den1 : 0.0 };
12853 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
12854 int maxProcessors = 0 )
const
12857 if ( !ParseSelection( r, firstChannel, lastChannel ) )
12861 if ( m_status.IsInitializationEnabled() )
12862 m_status.Initialize(
"Computing percentage bend midvariance", N );
12865 bool useAffinity = m_parallel && Thread::IsRootThread();
12867 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
12868 threads.
Add(
new DSmpThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
12869 if ( threads.
Length() > 1 )
12872 for ( DSmpThread& thread : threads )
12873 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
12874 for ( DSmpThread& thread : threads )
12881 for ( DSmpThread& thread : threads )
12882 if ( !thread.values.IsEmpty() )
12884 values.
Add( thread.values.Begin(), thread.values.At( thread.n ) );
12885 thread.values.Clear();
12938 double Sn(
const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
int maxProcessors = 0 )
const
12941 if ( !ParseSelection( r, firstChannel, lastChannel ) )
12945 if ( m_status.IsInitializationEnabled() )
12946 m_status.Initialize(
"Computing Sn scale estimate", N );
12949 bool useAffinity = m_parallel && Thread::IsRootThread();
12951 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
12952 threads.
Add(
new DSmpThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
12953 if ( threads.
Length() > 1 )
12956 for ( DSmpThread& thread : threads )
12957 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
12958 for ( DSmpThread& thread : threads )
12965 for ( DSmpThread& thread : threads )
12966 if ( !thread.values.IsEmpty() )
12968 values.
Add( thread.values.Begin(), thread.values.At( thread.n ) );
12969 thread.values.Clear();
13021 double Qn(
const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
int maxProcessors = 0 )
const
13024 if ( !ParseSelection( r, firstChannel, lastChannel ) )
13028 if ( m_status.IsInitializationEnabled() )
13029 m_status.Initialize(
"Computing Qn scale estimate", N );
13032 bool useAffinity = m_parallel && Thread::IsRootThread();
13034 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
13035 threads.
Add(
new DSmpThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
13036 if ( threads.
Length() > 1 )
13039 for ( DSmpThread& thread : threads )
13040 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
13041 for ( DSmpThread& thread : threads )
13048 for ( DSmpThread& thread : threads )
13049 if ( !thread.values.IsEmpty() )
13051 values.
Add( thread.values.Begin(), thread.values.At( thread.n ) );
13052 thread.values.Clear();
13099 double Norm(
const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1,
13100 int maxProcessors = 0 )
const
13103 if ( !ParseSelection( r, firstChannel, lastChannel ) )
13107 if ( m_status.IsInitializationEnabled() )
13108 m_status.Initialize(
"Computing norm", N );
13111 bool useAffinity = m_parallel && Thread::IsRootThread();
13113 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
13114 threads.
Add(
new SumThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
13115 if ( threads.
Length() > 1 )
13118 for ( SumThread& thread : threads )
13119 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
13120 for ( SumThread& thread : threads )
13128 for (
const SumThread& thread : threads )
13130 double y = thread.s - e;
13138 return (1 + s != 1) ? s : 0.0;
13172 int maxProcessors = 0 )
const
13175 if ( !ParseSelection( r, firstChannel, lastChannel ) )
13179 if ( m_status.IsInitializationEnabled() )
13180 m_status.Initialize(
"Computing modulus", N );
13183 bool useAffinity = m_parallel && Thread::IsRootThread();
13185 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
13186 threads.
Add(
new SumAbsThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
13187 if ( threads.
Length() > 1 )
13190 for ( SumAbsThread& thread : threads )
13191 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
13192 for ( SumAbsThread& thread : threads )
13200 for (
const SumAbsThread& thread : threads )
13202 double y = thread.s - e;
13210 return (1 + s != 1) ? s : 0.0;
13242 int maxProcessors = 0 )
const
13245 if ( !ParseSelection( r, firstChannel, lastChannel ) )
13249 if ( m_status.IsInitializationEnabled() )
13250 m_status.Initialize(
"Computing sum of squares", N );
13253 bool useAffinity = m_parallel && Thread::IsRootThread();
13255 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
13256 threads.
Add(
new SumSqrThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
13257 if ( threads.
Length() > 1 )
13260 for ( SumSqrThread& thread : threads )
13261 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
13262 for ( SumSqrThread& thread : threads )
13270 for (
const SumSqrThread& thread : threads )
13272 double y = thread.s - e;
13280 return (1 + s != 1) ? s : 0.0;
13312 int maxProcessors = 0 )
const
13315 if ( !ParseSelection( r, firstChannel, lastChannel ) )
13319 if ( m_status.IsInitializationEnabled() )
13320 m_status.Initialize(
"Computing mean of squares", N );
13323 bool useAffinity = m_parallel && Thread::IsRootThread();
13325 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
13326 threads.
Add(
new SumSqrThread( *
this, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
13327 if ( threads.
Length() > 1 )
13330 for ( SumSqrThread& thread : threads )
13331 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
13332 for ( SumSqrThread& thread : threads )
13341 for (
const SumSqrThread& thread : threads )
13343 double y = thread.s - e;
13397 int maxProcessors = 0 )
const
13399 PCL_PRECONDITION( maxDegree > 0 )
13400 maxDegree =
pcl::Max( 1, maxDegree );
13403 if ( !ParseSelection( r, firstChannel, lastChannel ) )
13407 if ( m_status.IsInitializationEnabled() )
13408 m_status.Initialize(
"Computing norms", N );
13411 bool useAffinity = m_parallel && Thread::IsRootThread();
13413 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
13414 threads.
Add(
new NormThread( *
this, maxDegree, r, firstChannel, lastChannel, n, n +
int( L[i] ) ) );
13415 if ( threads.
Length() > 1 )
13418 for ( NormThread& thread : threads )
13419 thread.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
13420 for ( NormThread& thread : threads )
13426 Vector R( 0.0, maxDegree );
13427 Vector e( 0.0, maxDegree );
13428 for (
const NormThread& thread : threads )
13429 for (
int i = 0; i < maxDegree; ++i )
13431 double y = thread.R[i] - e[i];
13432 double t = R[i] + y;
13433 e[i] = (t - R[i]) - y;
13436 for (
int i = 0; i < maxDegree; ++i )
13437 if ( 1 + R[i] == 1 )
13459 if ( !ParseChannel( channel ) )
13461 return pcl::Hash64( m_channelData( channel ), ChannelSize(), seed );
13478 if ( !ParseChannel( channel ) )
13480 return pcl::Hash32( m_channelData( channel ), ChannelSize(), seed );
13489 return Hash64( channel, seed );
13514 if ( !ParseSelection( r, firstChannel, lastChannel ) )
13518 int numberOfChannels = 1 + lastChannel - firstChannel;
13520 if ( m_status.IsInitializationEnabled() )
13521 m_status.Initialize(
"Writing to raw-storage image stream", N*numberOfChannels );
13526 file.
WriteUI32( (firstChannel == 0 && lastChannel >= 2) ? m_colorSpace : ColorSpace::Gray );
13528 if ( r == Bounds() )
13530 for (
int i = firstChannel; i <= lastChannel; ++i, m_status += N )
13531 file.
Write( (
const void*)m_pixelData[i],
fsize_type( ChannelSize() ) );
13535 for (
int i = firstChannel, w = r.
Width(), h = r.
Height(); i <= lastChannel; ++i )
13538 for (
int j = 0; j < h; ++j, p += m_width, m_status += w )
13539 file.
Write( (
const void*)p, w*BytesPerSample() );
13557 const Rect& rect =
Rect( 0 ),
int firstChannel = -1,
int lastChannel = -1 )
const
13559 File file = File::CreateFileForWriting( filePath );
13560 return Write( file, rect, firstChannel, lastChannel );
13601 int width, height, numberOfChannels, colorSpace;
13604 file.
ReadUI32( numberOfChannels );
13607 AllocateData( width, height, numberOfChannels, color_space( colorSpace ) );
13614 if ( m_status.IsInitializationEnabled() )
13615 m_status.Initialize(
"Reading from raw-storage image stream", N*m_numberOfChannels );
13616 for (
int i = 0; i < m_numberOfChannels; ++i, m_status += N )
13617 file.
Read( (
void*)m_pixelData[i],
fsize_type( ChannelSize() ) );
13636 File file = File::OpenFileForReading( filePath );
13637 return Read( file );
13672 template <
typename T>
13675 if ( left == 0 && top == 0 && right == 0 && bottom == 0 )
13678 if ( m_width+left+right <= 0 || m_height+top+bottom <= 0 )
13684 Rect r( -left, -top, m_width+right, m_height+bottom );
13685 int width = r.
Width();
13686 int height = r.
Height();
13688 if ( !Intersects( r ) )
13689 return AllocateData( width, height, m_numberOfChannels, m_colorSpace ).Fill( fillValues );
13695 if ( m_status.IsInitializationEnabled() )
13696 m_status.Initialize(
String().Format(
"Crop margins: %+d, %+d, %+d, %+d",
13697 left, top, right, bottom ), N*m_numberOfChannels );
13699 sample** newData =
nullptr;
13703 newData = m_allocator.AllocateChannelSlots( m_numberOfChannels );
13705 for (
int c = 0; c < m_numberOfChannels; ++c, m_status += N )
13707 sample* __restrict__ f = newData[c] = m_allocator.AllocatePixels( N );
13708 sample v = (c < fillValues.
Length()) ? P::ToSample( fillValues[c] ) : P::MinSampleValue();
13710 for (
int i = r.
y0, j; i < r.
y1; )
13712 for ( ; i < 0; ++i )
13715 for (
int j = 0; j < width; ++j )
13720 for ( j = r.
x0; j < 0; ++j )
13723 for (
const sample* f0 = PixelAddress( j, i, c ); j < r.
x1; )
13726 if ( ++j == m_width )
13729 for ( ; j < r.
x1; ++j )
13734 if ( ++i == m_height )
13735 for ( ; i < r.
y1; ++i )
13738 for (
int j = 0; j < width; ++j )
13746 for (
int c = 0; c < m_numberOfChannels; ++c )
13748 m_allocator.Deallocate( m_pixelData[c] );
13749 m_pixelData[c] = newData[c];
13751 m_allocator.Deallocate( newData );
13754 m_allocator.SetSharedGeometry( m_width = width, m_height = height, m_numberOfChannels );
13762 m_data->Deallocate();
13769 if ( newData !=
nullptr )
13771 for (
int i = 0; i < m_numberOfChannels; ++i )
13772 if ( newData[i] !=
nullptr )
13773 m_allocator.Deallocate( newData[i] ), newData[i] =
nullptr;
13774 m_allocator.Deallocate( newData );
13793 return CropBy( left, top, right, bottom,
sample_vector() );
13806 template <
typename T>
13810 return CropBy( -r.
x0, -r.
y0, r.
x1 - m_width, r.
y1 - m_height, fillValues );
13839 template <
typename T>
13842 return CropTo(
Rect( x0, y0, x1, y1 ), fillValues );
13871 template <
typename T>
13874 return CropTo( m_rectangle, fillValues );
13914 template <
typename T>
13917 return CropBy( dx, dy, -dx, -dy, fillValues );
13942 template <
typename T>
13945 return ShiftBy( x, y, fillValues );
13974 template <
typename T>
13977 return ShiftBy( p.
x, p.
y, fillValues );
14000 template <
typename T>
14003 int dx2 = (width - m_width) >> 1;
14004 int dy2 = (height - m_height) >> 1;
14005 return CropBy( dx2, dy2, width-m_width-dx2, height-m_height-dy2, fillValues );
14029 template <
typename T>
14032 int dx = width - m_width;
14033 int dy = height - m_height;
14034 return CropBy( 0, 0, dx, dy, fillValues );
14058 template <
typename T>
14061 int dx = width - m_width;
14062 int dy = height - m_height;
14063 return CropBy( dx, 0, 0, dy, fillValues );
14087 template <
typename T>
14090 int dx = width - m_width;
14091 int dy = height - m_height;
14092 return CropBy( 0, dy, dx, 0, fillValues );
14109 return ShiftToBottomLeft( width, height,
sample_vector() );
14116 template <
typename T>
14119 int dx = width - m_width;
14120 int dy = height - m_height;
14121 return CropBy( dx, dy, 0, 0, fillValues );
14138 return ShiftToBottomRight( width, height,
sample_vector() );
14151 template <
typename T>
14154 return ShiftTo( m_point, fillValues );
14214 if ( colorSpace == m_colorSpace )
14222 if ( m_status.IsInitializationEnabled() )
14223 m_status.Initialize(
"In-place color space conversion: "
14228 int n = m_numberOfChannels;
14230 if ( m_colorSpace == ColorSpace::Gray )
14232 sample** oldData = m_pixelData;
14233 sample** newData =
nullptr;
14238 newData = m_allocator.AllocateChannelSlots( 2+n );
14241 newData[0] = oldData[0];
14244 newData[1] = m_allocator.AllocatePixels( N );
14245 ::memcpy( newData[1], oldData[0], ChannelSize() );
14246 newData[2] = m_allocator.AllocatePixels( N );
14247 ::memcpy( newData[2], oldData[0], ChannelSize() );
14250 for (
int i = 1; i < n; ++i )
14251 newData[i+2] = oldData[i];
14255 m_pixelData = newData;
14257 m_numberOfChannels += 2;
14258 m_colorSpace = ColorSpace::RGB;
14259 m_data->UpdateSharedImage();
14261 ResetChannelRange();
14263 m_allocator.Deallocate( oldData );
14267 m_data->Deallocate();
14274 if ( newData !=
nullptr )
14276 newData[0] =
nullptr;
14277 if ( newData[1] !=
nullptr )
14278 m_allocator.Deallocate( newData[1] ), newData[1] =
nullptr;
14279 if ( newData[2] !=
nullptr )
14280 m_allocator.Deallocate( newData[2] ), newData[2] =
nullptr;
14281 m_allocator.Deallocate( newData );
14286 if ( colorSpace == ColorSpace::RGB )
14297 m_parallel ? ((maxProcessors > 0) ? maxProcessors : m_maxProcessors) : 1 );
14300 for (
size_type i = 0, n = 0; i < L.Length(); n += L[i++] )
14301 threads.
Add(
new ColorSpaceConversionThread( *
this, data, colorSpace, n, n + L[i] ) );
14302 RunThreads( threads, data );
14307 if ( colorSpace == ColorSpace::Gray )
14309 sample** oldData = m_pixelData;
14310 sample** newData =
nullptr;
14314 newData = m_allocator.AllocateChannelSlots( n-2 );
14315 newData[0] = oldData[0];
14316 for (
int i = 3; i < n; ++i )
14317 newData[i-2] = oldData[i];
14319 m_pixelData = newData;
14321 m_numberOfChannels -= 2;
14322 m_colorSpace = ColorSpace::Gray;
14323 m_data->UpdateSharedImage();
14325 ResetChannelRange();
14327 m_allocator.Deallocate( oldData[1] );
14328 m_allocator.Deallocate( oldData[2] );
14329 m_allocator.Deallocate( oldData );
14333 m_data->Deallocate();
14335 if ( newData !=
nullptr )
14336 m_allocator.Deallocate( newData );
14342 m_allocator.SetSharedColor( m_colorSpace = colorSpace, m_RGBWS );
14415 template <
class P1>
14419 if ( !ParseRect( r ) )
14425 Y.AllocateData( r );
14426 if ( !Y.IsShared() )
14427 Y.SetRGBWorkingSpace( m_RGBWS );
14431 if ( m_colorSpace == ColorSpace::Gray || m_colorSpace == ColorSpace::CIEXYZ )
14433 if ( m_status.IsInitializationEnabled() )
14434 m_status.Initialize(
"Transferring pixel data", N );
14437 int cY = (m_colorSpace == ColorSpace::Gray) ? 0 : 1;
14438 if ( r == Bounds() )
14440 const sample* __restrict__ f = m_pixelData[cY];
14441 P1::Copy( g, f, N );
14445 const sample* __restrict__ f = PixelAddress( r.
LeftTop(), cY );
14446 for (
int i = 0; i < Y.Height(); ++i, f += m_width, g += Y.Width() )
14447 P1::Copy( g, f, Y.Width() );
14454 if ( m_status.IsInitializationEnabled() )
14455 m_status.Initialize(
"Computing CIE Y component", N );
14457 Array<size_type> L = OptimalThreadRows( Y.Height(), Y.Width(), maxProcessors );
14460 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
14461 threads.
Add(
new GetLuminanceThread<P1>( Y, *
this, data, r, n, n +
int( L[i] ) ) );
14462 RunThreads( threads, data );
14478 void GetLuminance(
ImageVariant& Y,
const Rect& rect =
Rect( 0 ),
int maxProcessors = 0 )
const;
14547 template <
class P1>
14551 if ( !ParseRect( r ) )
14557 L.AllocateData( r );
14558 if ( !L.IsShared() )
14559 L.SetRGBWorkingSpace( m_RGBWS );
14563 if ( m_colorSpace == ColorSpace::Gray || m_colorSpace == ColorSpace::CIELab || m_colorSpace == ColorSpace::CIELch )
14565 if ( m_status.IsInitializationEnabled() )
14566 m_status.Initialize(
"Transferring pixel data", N );
14569 if ( r == Bounds() )
14571 const sample* __restrict__ f = *m_pixelData;
14572 P1::Copy( g, f, N );
14576 const sample* __restrict__ f = PixelAddress( r.
LeftTop() );
14577 for (
int i = 0; i < L.Height(); ++i, f += m_width, g += L.Width() )
14578 P1::Copy( g, f, L.Width() );
14585 if ( m_status.IsInitializationEnabled() )
14586 m_status.Initialize(
"Computing CIE L* component", N );
14588 Array<size_type> R = OptimalThreadRows( L.Height(), L.Width(), maxProcessors );
14591 for (
int i = 0, n = 0; i < int( R.Length() ); n += int( R[i++] ) )
14592 threads.
Add(
new GetLightnessThread<P1>( L, *
this, data, r, n, n +
int( R[i] ) ) );
14593 RunThreads( threads, data );
14609 void GetLightness(
ImageVariant& L,
const Rect& rect =
Rect( 0 ),
int maxProcessors = 0 )
const;
14670 template <
class P1>
14674 if ( !ParseRect( r ) )
14680 I.AllocateData( r );
14681 if ( !I.IsShared() )
14682 I.SetRGBWorkingSpace( m_RGBWS );
14686 if ( m_colorSpace == ColorSpace::Gray || m_colorSpace == ColorSpace::HSI )
14688 if ( m_status.IsInitializationEnabled() )
14689 m_status.Initialize(
"Transferring pixel data", N );
14692 int cI = (m_colorSpace == ColorSpace::Gray) ? 0 : 2;
14693 if ( r == Bounds() )
14695 const sample* __restrict__ f = m_pixelData[cI];
14696 P1::Copy( g, f, N );
14700 const sample* __restrict__ f = PixelAddress( r.
LeftTop(), cI );
14701 for (
int i = 0; i < I.Height(); ++i, f += m_width, g += I.Width() )
14702 P1::Copy( g, f, I.Width() );
14709 if ( m_status.IsInitializationEnabled() )
14710 m_status.Initialize(
"Computing intensity component", N );
14712 Array<size_type> L = OptimalThreadRows( I.Height(), I.Width(), maxProcessors );
14715 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
14716 threads.
Add(
new GetIntensityThread<P1>( I, *
this, data, r, n, n +
int( L[i] ) ) );
14717 RunThreads( threads, data );
14733 void GetIntensity(
ImageVariant& I,
const Rect& rect =
Rect( 0 ),
int maxProcessors = 0 )
const;
14796 template <
class P1>
14799 int maxProcessors = 0 )
14802 if ( !Y.ParseRect( r ) )
14806 if ( p.
x == int_max || p.
y == int_max )
14811 if ( (r.
x0 -= p.
x) >= r.
x1 )
14815 else if ( p.
x >= m_width )
14820 if ( (r.
y0 -= p.
y) >= r.
y1 )
14824 else if ( p.
y >= m_height )
14834 if ( m_colorSpace == ColorSpace::Gray &&
14835 (Y.ColorSpace() == ColorSpace::Gray || Y.ColorSpace() == ColorSpace::CIEXYZ) )
14837 if ( m_status.IsInitializationEnabled() )
14838 m_status.Initialize(
"Transferring pixel data", N );
14840 int c0 = (Y.ColorSpace() == ColorSpace::Gray) ? 0 : 1;
14842 sample* __restrict__ f = PixelAddress( p );
14843 for (
int i = 0, w = r.
Width(), h = r.
Height(); i < h; ++i, f += m_width, g += Y.Width(), m_status += w )
14844 P::Copy( f, g, w );
14848 if ( m_status.IsInitializationEnabled() )
14849 m_status.Initialize(
"Importing CIE Y component", N );
14854 for (
int i = 0, n = 0; i < int( L.Length() ); n += int( L[i++] ) )
14855 threads.
Add(
new SetLuminanceThread<P1>( *
this, Y, data, p, r, n, n +
int( L[i] ) ) );
14856 RunThreads( threads, data );
14876 int maxProcessors = 0 );
14937 template <
class P1>
14940 int maxProcessors = 0 )
14943 if ( !L.ParseRect( r ) )
14947 if ( p.
x == int_max || p.
y == int_max )
14952 if ( (r.
x0 -= p.
x) >= r.
x1 )
14956 else if ( p.
x >= m_width )
14961 if ( (r.
y0 -= p.
y) >= r.
y1 )
14965 else if ( p.
y >= m_height )
14975 if ( m_colorSpace == ColorSpace::Gray &&
14976 (L.ColorSpace() == ColorSpace::Gray ||
14977 L.ColorSpace() == ColorSpace::CIELab || L.ColorSpace() == ColorSpace::CIELch) )
14979 if ( m_status.IsInitializationEnabled() )
14980 m_status.Initialize(
"Transferring pixel data", N );
14983 sample* __restrict__ f = PixelAddress( p );
14984 for (
int i = 0, w = r.
Width(), h = r.
Height(); i < h; ++i, f += m_width, g += L.Width(), m_status += w )
14985 P::Copy( f, g, w );
14989 if ( m_status.IsInitializationEnabled() )
14990 m_status.Initialize(
"Importing CIE L* component", N );
14995 for (
int i = 0, n = 0; i < int( R.Length() ); n += int( R[i++] ) )
14996 threads.
Add(
new SetLightnessThread<P1>( *
this, L, data, p, r, n, n +
int( R[i] ) ) );
14997 RunThreads( threads, data );
15017 int maxProcessors = 0 );
15059 const Rect& rect =
Rect( 0 ),
int channel = -1,
15063 if ( !ParseSelection( r, channel ) )
15065 if ( r == Bounds() )
15066 return compressor.
Compress( m_channelData( channel ), ChannelSize(), perf );
15089 sample** data =
nullptr;
15101 pixel_allocator allocator;
15118 LinkWithClientImage( image );
15124 Data( GenericImage* image,
void* handle )
15125 : allocator( handle )
15127 SynchronizeWithSharedImage();
15128 LinkWithClientImage( image );
15134 Data( GenericImage* image,
int width,
int height,
int numberOfChannels,
int colorSpace )
15135 : allocator( width, height, numberOfChannels, colorSpace )
15137 SynchronizeWithSharedImage();
15138 LinkWithClientImage( image );
15141 void Attach( GenericImage* image )
15143 ReferenceCounter::Attach();
15144 LinkWithClientImage( image );
15155 bool IsShared() const noexcept
15157 return allocator.IsShared();
15160 bool IsEmpty() const noexcept
15162 return data ==
nullptr;
15165 void Allocate(
int width,
int height,
int numberOfChannels, color_space colorSpace )
15167 if ( width <= 0 || height <= 0 || numberOfChannels <= 0 )
15174 throw Error(
"GenericImage::Data::Allocate(): Insufficient number of channels" );
15176 if ( data !=
nullptr )
15180 if ( numberOfChannels != geometry.numberOfChannels )
15182 sample** newData =
nullptr;
15183 int m =
pcl::Min( geometry.numberOfChannels, numberOfChannels );
15187 newData = allocator.AllocateChannelSlots( numberOfChannels );
15188 for (
int i = 0; i < m; ++i )
15189 newData[i] = data[i];
15190 for (
int i = m; i < numberOfChannels; ++i )
15191 newData[i] = allocator.AllocatePixels( width, height );
15195 for (
int i = m; i < geometry.numberOfChannels; ++i )
15196 if ( data[i] !=
nullptr )
15197 allocator.Deallocate( data[i] ), data[i] =
nullptr;
15198 allocator.Deallocate( data );
15210 if ( newData !=
nullptr )
15212 for (
int i = m; i < numberOfChannels; ++i )
15213 if ( newData[i] !=
nullptr )
15214 allocator.Deallocate( newData[i] ), newData[i] =
nullptr;
15215 allocator.Deallocate( newData );
15223 sample** newData =
nullptr;
15227 newData = allocator.AllocateChannelSlots( numberOfChannels );
15228 for (
int i = 0; i < numberOfChannels; ++i )
15229 newData[i] = allocator.AllocatePixels( width, height );
15233 for (
int i = 0; i < geometry.numberOfChannels; ++i )
15234 if ( data[i] !=
nullptr )
15235 allocator.Deallocate( data[i] ), data[i] =
nullptr;
15236 allocator.Deallocate( data );
15248 if ( newData !=
nullptr )
15250 for (
int i = 0; i < numberOfChannels; ++i )
15251 if ( newData[i] !=
nullptr )
15252 allocator.Deallocate( newData[i] ), newData[i] =
nullptr;
15253 allocator.Deallocate( newData );
15263 data = allocator.AllocateChannelSlots( numberOfChannels );
15264 for (
int i = 0; i < numberOfChannels; ++i )
15265 data[i] = allocator.AllocatePixels( width, height );
15269 if ( data !=
nullptr )
15271 for (
int i = 0; i < numberOfChannels; ++i )
15272 if ( data[i] !=
nullptr )
15273 allocator.Deallocate( data[i] ), data[i] =
nullptr;
15274 allocator.Deallocate( data );
15281 geometry.width = width;
15282 geometry.height = height;
15283 geometry.numberOfChannels = numberOfChannels;
15285 color.colorSpace = colorSpace;
15287 UpdateSharedImage();
15290 void Import( sample** newData,
int width,
int height,
int numberOfChannels, color_space colorSpace )
15292 if ( newData != data )
15296 if ( newData !=
nullptr && width > 0 && height > 0 && numberOfChannels > 0 )
15299 throw Error(
"GenericImage::Data::Import(): Insufficient number of channels" );
15303 geometry.width = width;
15304 geometry.height = height;
15305 geometry.numberOfChannels = numberOfChannels;
15307 color.colorSpace = colorSpace;
15309 UpdateSharedImage();
15316 sample** oldData = data;
15318 UpdateSharedImage();
15324 if ( data !=
nullptr )
15326 for (
int i = 0; i < geometry.numberOfChannels; ++i )
15327 if ( data[i] !=
nullptr )
15328 allocator.Deallocate( data[i] ), data[i] =
nullptr;
15329 allocator.Deallocate( data );
15331 UpdateSharedImage();
15335 Data* Clone( GenericImage* image )
const
15337 Data* clone =
nullptr;
15344 clone->data = clone->allocator.AllocateChannelSlots( geometry.numberOfChannels );
15345 for (
int i = 0; i < geometry.numberOfChannels; ++i )
15347 clone->data[i] = clone->allocator.AllocatePixels( geometry.width, geometry.height );
15348 P::Copy( clone->data[i], data[i], geometry.NumberOfPixels() );
15351 clone->geometry.Assign( geometry );
15352 clone->color.Assign( color );
15355 clone->LinkWithClientImage( image );
15360 if ( clone !=
nullptr )
15362 clone->Deallocate();
15376 void UpdateSharedImage()
15378 allocator.SetSharedData( data );
15379 allocator.SetSharedGeometry( geometry.width, geometry.height, geometry.numberOfChannels );
15380 allocator.SetSharedColor( color.colorSpace, color.RGBWS );
15383 void SynchronizeWithSharedImage()
15385 data = allocator.GetSharedData();
15386 allocator.GetSharedGeometry( geometry.width, geometry.height, geometry.numberOfChannels );
15387 allocator.GetSharedColor( color.colorSpace, color.RGBWS );
15394 void LinkWithClientImage( GenericImage* image )
15396 if ( image !=
nullptr )
15398 image->m_geometry = &geometry;
15399 image->m_color = &color;
15408 Data* m_data =
nullptr;
15414 void DetachFromData()
15416 if ( !m_data->Detach() )
15422 class RectThreadBase :
public Thread
15426 RectThreadBase(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
15431 , m_firstRow( firstRow )
15432 , m_endRow( endRow )
15436 virtual void Run() = 0;
15440 const GenericImage& m_image;
15441 const Rect& m_rect;
15443 int m_firstRow, m_endRow;
15445 bool HasSimpleSelection()
const
15447 return m_rect.Width() == m_image.Width()
15448 && !m_image.IsLowRangeClippingEnabled()
15449 && !m_image.IsHighRangeClippingEnabled();
15452 template <
class F>
void Execute( F process ) noexcept
15454 int w = m_rect.Width();
15455 int dw = m_image.Width() - w;
15461 if ( m_image.IsLowRangeClippingEnabled() )
15463 sample clipLow = P::ToSample( m_image.RangeClipLow() );
15464 if ( m_image.IsHighRangeClippingEnabled() )
15466 sample clipHigh = P::ToSample( m_image.RangeClipHigh() );
15467 for (
int i = m_ch1; i <= m_ch2; ++i )
15469 const sample* __restrict__ f = m_image.PixelAddress( 0, m_rect.y0+m_firstRow, i );
15471 for (
size_type j = 0; j < n; ++j, ++f )
15472 if ( clipLow < *f )
15473 if ( *f < clipHigh )
15479 for (
int i = m_ch1; i <= m_ch2; ++i )
15481 const sample* __restrict__ f = m_image.PixelAddress( 0, m_rect.y0+m_firstRow, i );
15483 for (
size_type j = 0; j < n; ++j, ++f )
15484 if ( clipLow < *f )
15489 else if ( m_image.IsHighRangeClippingEnabled() )
15491 sample clipHigh = P::ToSample( m_image.RangeClipHigh() );
15492 for (
int i = m_ch1; i <= m_ch2; ++i )
15494 const sample* __restrict__ f = m_image.PixelAddress( 0, m_rect.y0+m_firstRow, i );
15496 for (
size_type j = 0; j < n; ++j, ++f )
15497 if ( *f < clipHigh )
15504 for (
int i = m_ch1; i <= m_ch2; ++i )
15506 const sample* __restrict__ f = m_image.PixelAddress( 0, m_rect.y0+m_firstRow, i );
15508 for (
size_type j = 0; j < n; ++j, ++f )
15515 if ( m_image.IsLowRangeClippingEnabled() )
15517 sample clipLow = P::ToSample( m_image.RangeClipLow() );
15518 if ( m_image.IsHighRangeClippingEnabled() )
15520 sample clipHigh = P::ToSample( m_image.RangeClipHigh() );
15521 for (
int i = m_ch1; i <= m_ch2; ++i )
15523 const sample* __restrict__ f = m_image.PixelAddress( m_rect.x0, m_rect.y0+m_firstRow, i );
15524 for (
int j = m_firstRow; j < m_endRow; ++j, f += dw )
15527 for (
int k = 0; k < w; ++k, ++f )
15528 if ( clipLow < *f )
15529 if ( *f < clipHigh )
15536 for (
int i = m_ch1; i <= m_ch2; ++i )
15538 const sample* __restrict__ f = m_image.PixelAddress( m_rect.x0, m_rect.y0+m_firstRow, i );
15539 for (
int j = m_firstRow; j < m_endRow; ++j, f += dw )
15542 for (
int k = 0; k < w; ++k, ++f )
15543 if ( clipLow < *f )
15549 else if ( m_image.IsHighRangeClippingEnabled() )
15551 sample clipHigh = P::ToSample( m_image.RangeClipHigh() );
15552 for (
int i = m_ch1; i <= m_ch2; ++i )
15554 const sample* __restrict__ f = m_image.PixelAddress( m_rect.x0, m_rect.y0+m_firstRow, i );
15555 for (
int j = m_firstRow; j < m_endRow; ++j, f += dw )
15558 for (
int k = 0; k < w; ++k, ++f )
15559 if ( *f < clipHigh )
15566 for (
int i = m_ch1; i <= m_ch2; ++i )
15568 const sample* __restrict__ f = m_image.PixelAddress( m_rect.x0, m_rect.y0+m_firstRow, i );
15569 for (
int j = m_firstRow; j < m_endRow; ++j, f += dw )
15572 for (
int k = 0; k < w; ++k, ++f )
15583 class CountThread :
public RectThreadBase
15589 CountThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
15590 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
15599 int w = this->m_rect.Width();
15600 int dw = this->m_image.Width() - w;
15602 if ( this->m_image.IsLowRangeClippingEnabled() )
15604 sample clipLow = P::ToSample( this->m_image.RangeClipLow() );
15605 if ( this->m_image.IsHighRangeClippingEnabled() )
15607 sample clipHigh = P::ToSample( this->m_image.RangeClipHigh() );
15608 for (
int i = this->m_ch1; i <= this->m_ch2; ++i )
15610 const sample* __restrict__ f = this->m_image.PixelAddress( this->m_rect.x0, this->m_rect.y0+this->m_firstRow, i );
15611 for (
int j = this->m_firstRow; j < this->m_endRow; ++j, f += dw )
15614 for (
int k = 0; k < w; ++k, ++f )
15615 if ( clipLow < *f )
15616 if ( *f < clipHigh )
15623 for (
int i = this->m_ch1; i <= this->m_ch2; ++i )
15625 const sample* __restrict__ f = this->m_image.PixelAddress( this->m_rect.x0, this->m_rect.y0+this->m_firstRow, i );
15626 for (
int j = this->m_firstRow; j < this->m_endRow; ++j, f += dw )
15629 for (
int k = 0; k < w; ++k, ++f )
15630 if ( clipLow < *f )
15636 else if ( this->m_image.IsHighRangeClippingEnabled() )
15638 sample clipHigh = P::ToSample( this->m_image.RangeClipHigh() );
15639 for (
int i = this->m_ch1; i <= this->m_ch2; ++i )
15641 const sample* __restrict__ f = this->m_image.PixelAddress( this->m_rect.x0, this->m_rect.y0+this->m_firstRow, i );
15642 for (
int j = this->m_firstRow; j < this->m_endRow; ++j, f += dw )
15645 for (
int k = 0; k < w; ++k, ++f )
15646 if ( *f < clipHigh )
15658 class MinThread :
public RectThreadBase
15665 MinThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
15666 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
15672 min = P::HighestSampleValue();
15674 this->Execute( [=](
const sample* __restrict__ f )
15685 class MaxThread :
public RectThreadBase
15692 MaxThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
15693 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
15699 max = P::LowestSampleValue();
15701 this->Execute( [=](
const sample* __restrict__ f )
15712 class MinMaxThread :
public RectThreadBase
15720 MinMaxThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
15721 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
15727 min = P::HighestSampleValue();
15728 max = P::LowestSampleValue();
15730 this->Execute( [=](
const sample* __restrict__ f )
15743 class ExtremePosThreadBase :
public RectThreadBase
15751 ExtremePosThreadBase(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
15752 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
15759 m_amin = m_amax =
nullptr;
15765 for (
int i = this->m_ch1; i <= this->m_ch2; ++i )
15766 if ( m_amin >= this->m_image[i] && m_amin < (this->m_image[i] + this->m_image.NumberOfPixels()) )
15769 pmin.x = (m_amin - this->m_image[i]) % this->m_image.Width();
15770 pmin.y = (m_amin - this->m_image[i]) / this->m_image.Width();
15774 for (
int i = this->m_ch1; i <= this->m_ch2; ++i )
15775 if ( m_amax >= this->m_image[i] && m_amax < (this->m_image[i] + this->m_image.NumberOfPixels()) )
15778 pmax.x = (m_amax - this->m_image[i]) % this->m_image.Width();
15779 pmax.y = (m_amax - this->m_image[i]) / this->m_image.Width();
15787 const sample* m_amin;
15788 const sample* m_amax;
15790 virtual void DoExecute() = 0;
15795 class MinPosThread :
public ExtremePosThreadBase
15801 MinPosThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
15802 : ExtremePosThreadBase( image, rect, ch1, ch2, firstRow, endRow )
15808 void DoExecute()
override
15810 min = P::HighestSampleValue();
15811 this->Execute( [=](
const sample* __restrict__ f )
15814 min = *(this->m_amin = f);
15822 class MaxPosThread :
public ExtremePosThreadBase
15828 MaxPosThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
15829 : ExtremePosThreadBase( image, rect, ch1, ch2, firstRow, endRow )
15835 void DoExecute()
override
15837 max = P::LowestSampleValue();
15838 this->Execute( [=](
const sample* __restrict__ f )
15841 max = *(this->m_amax = f);
15849 class MinMaxPosThread :
public ExtremePosThreadBase
15855 MinMaxPosThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
15856 : ExtremePosThreadBase( image, rect, ch1, ch2, firstRow, endRow )
15862 void DoExecute()
override
15864 min = P::HighestSampleValue();
15865 max = P::LowestSampleValue();
15866 this->Execute( [=](
const sample* __restrict__ f )
15869 min = *(this->m_amin = f);
15871 max = *(this->m_amax = f);
15879 class SumThread :
public RectThreadBase
15886 SumThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
15887 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
15902 void SumStep(
double x ) noexcept
15911 virtual void DoExecute()
15913 this->Execute( [=](
const sample* __restrict__ f )
15915 double v; P::FromSample( v, *f );
15923 class SumSqrThread :
public SumThread
15927 SumSqrThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
15928 : SumThread( image, rect, ch1, ch2, firstRow, endRow )
15934 void DoExecute()
override
15936 this->Execute( [=](
const sample* __restrict__ f )
15938 double v; P::FromSample( v, *f );
15939 this->SumStep( v*v );
15946 class SumAbsThread :
public SumThread
15950 SumAbsThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
15951 : SumThread( image, rect, ch1, ch2, firstRow, endRow )
15957 void DoExecute()
override
15959 this->Execute( [=](
const sample* __restrict__ f )
15961 double v; P::FromSample( v, *f );
15969 class NormThread :
public RectThreadBase
15976 NormThread(
const GenericImage& image,
int degree,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
15977 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
15987 this->Execute( [=](
const sample* __restrict__ f )
15989 double v; P::FromSample( v, *f );
15990 for (
int i = 0;; )
15993 if ( ++i == R.Length() )
16005 void NormStep(
int i,
double x ) noexcept
16007 double y = x - e[i];
16008 double t = R[i] + y;
16009 e[i] = (t - R[i]) - y;
16016 class HistogramThread :
public RectThreadBase
16022 HistogramThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow,
16023 const double& low,
const double& high )
16024 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
16025 , H( __PCL_MEDIAN_HISTOGRAM_LENGTH )
16035 if ( this->HasSimpleSelection() )
16038 for (
int i = this->m_ch1; i <= this->m_ch2; ++i )
16039 Build( H, this->m_image.PixelAddress( 0, this->m_rect.y0+this->m_firstRow, i ), n, m_low, m_high );
16043 m_range = m_high - m_low;
16044 if ( 1 + m_range != 1 )
16046 const double scale = (__PCL_MEDIAN_HISTOGRAM_LENGTH - 1)/m_range;
16047 this->Execute( [=](
const sample* __restrict__ f )
16049 const int k =
TruncInt( scale*(*f - m_low) );
16050 if ( k >= 0 && k < __PCL_MEDIAN_HISTOGRAM_LENGTH )
16059 const double& m_low;
16060 const double& m_high;
16063 template <
typename T1>
16064 static void Build(
SzVector& H,
const T1* __restrict__ A,
size_type N,
double low,
double high )
16066 const double range = high - low;
16067 if ( 1 + range != 1 )
16069 const double scale = (__PCL_MEDIAN_HISTOGRAM_LENGTH - 1)/range;
16073 const int k =
TruncInt( scale*(A[i] - low) );
16074 if ( k >= 0 && k < __PCL_MEDIAN_HISTOGRAM_LENGTH )
16083 static void Build(
SzVector& H,
const float* __restrict__ A,
size_type N,
double low,
double high )
16085 const double range = high - low;
16086 if ( 1 + range == 1 )
16089 const float s = float( (__PCL_MEDIAN_HISTOGRAM_LENGTH - 1)/range );
16090 const float l = float( low );
16091 const __m256 S = _mm256_set1_ps( s );
16092 const __m256 L = _mm256_set1_ps( l );
16093 const size_type stepLength = 0x40000000u;
16095 for (
size_type p = 0; p < N; p += stepLength )
16097 const float* __restrict__ V = A + p;
16098 const int n = int(
pcl::Min( stepLength, N - p ) );
16099 const int n8 = n >> 3;
16101 if ( ((ptrdiff_t)V) & 31 )
16102 for (
int i = 0; i < n8; ++i )
16104 __m256 v = _mm256_loadu_ps( (
const float* __restrict__)(V + i*8) );
16105 __m256i K = _mm256_cvttps_epi32( _mm256_mul_ps( _mm256_sub_ps( v, L ), S ) );
16106 for (
int j = 0; j < 8; ++j )
16108 const int k = ((
const int* __restrict__)&K)[j];
16109 if ( k >= 0 && k < __PCL_MEDIAN_HISTOGRAM_LENGTH )
16114 for (
int i = 0; i < n8; ++i )
16116 __m256i K = _mm256_cvttps_epi32( _mm256_mul_ps( _mm256_sub_ps( ((
const __m256* __restrict__)V)[i], L ), S ) );
16117 for (
int j = 0; j < 8; ++j )
16119 const int k = ((
const int* __restrict__)&K)[j];
16120 if ( k >= 0 && k < __PCL_MEDIAN_HISTOGRAM_LENGTH )
16125 for (
int i = n8 << 3; i < n; ++i )
16127 const int k =
TruncInt( s * (V[i] - l) );
16128 if ( k >= 0 && k < __PCL_MEDIAN_HISTOGRAM_LENGTH )
16135 static void Build(
SzVector& H,
const double* __restrict__ A,
size_type N,
double low,
double high )
16137 const double range = high - low;
16138 if ( 1 + range == 1 )
16141 const double s = (__PCL_MEDIAN_HISTOGRAM_LENGTH - 1)/range;
16142 const __m256d S = _mm256_set1_pd( s );
16143 const __m256d L = _mm256_set1_pd( low );
16144 const size_type stepLength = 0x40000000u;
16146 for (
size_type p = 0; p < N; p += stepLength )
16148 const double* __restrict__ V = A + p;
16149 const int n = int(
pcl::Min( stepLength, N - p ) );
16150 const int n4 = n >> 2;
16152 if ( ((ptrdiff_t)V) & 31 )
16153 for (
int i = 0; i < n4; ++i )
16155 __m256d v = _mm256_loadu_pd( (
const double* __restrict__)(V + i*4) );
16156 __m128i K = _mm256_cvttpd_epi32( _mm256_mul_pd( _mm256_sub_pd( v, L ), S ) );
16157 for (
int j = 0; j < 4; ++j )
16159 const int k = ((
const int* __restrict__)&K)[j];
16160 if ( k >= 0 && k < __PCL_MEDIAN_HISTOGRAM_LENGTH )
16165 for (
int i = 0; i < n4; ++i )
16167 __m128i K = _mm256_cvttpd_epi32( _mm256_mul_pd( _mm256_sub_pd( ((
const __m256d* __restrict__)V)[i], L ), S ) );
16168 for (
int j = 0; j < 4; ++j )
16170 const int k = ((
const int* __restrict__)&K)[j];
16171 if ( k >= 0 && k < __PCL_MEDIAN_HISTOGRAM_LENGTH )
16176 for (
int i = n4 << 2; i < n; ++i )
16178 const int k =
TruncInt( s * (V[i] - low) );
16179 if ( k >= 0 && k < __PCL_MEDIAN_HISTOGRAM_LENGTH )
16190 class ExtremeAbsDevThread :
public RectThreadBase
16194 double minAbsDev, maxAbsDev;
16197 ExtremeAbsDevThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow,
double center )
16198 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
16199 , m_center( center )
16205 minAbsDev = std::numeric_limits<double>::max();
16208 this->Execute( [=](
const sample* __restrict__ f )
16210 double d; P::FromSample( d, *f );
16212 if ( d < minAbsDev )
16214 if ( d > maxAbsDev )
16227 class TwoSidedExtremeAbsDevThread :
public RectThreadBase
16231 double minAbsDevLow, minAbsDevHigh;
16232 double maxAbsDevLow, maxAbsDevHigh;
16235 TwoSidedExtremeAbsDevThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow,
double center )
16236 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
16237 , m_center( center )
16243 minAbsDevLow = minAbsDevHigh = std::numeric_limits<double>::max();
16244 maxAbsDevLow = maxAbsDevHigh = 0;
16246 this->Execute( [=](
const sample* __restrict__ f )
16248 double x; P::FromSample( x, *f );
16249 if ( x <= m_center )
16251 double d = m_center - x;
16252 if ( d < minAbsDevLow )
16254 if ( d > maxAbsDevLow )
16260 double d = x - m_center;
16261 if ( d < minAbsDevHigh )
16263 if ( d > maxAbsDevHigh )
16277 class AbsDevHistogramThread :
public RectThreadBase
16283 AbsDevHistogramThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow,
16284 double center,
const double& low,
const double& high )
16285 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
16286 , H( __PCL_MEDIAN_HISTOGRAM_LENGTH )
16287 , m_center( center )
16296 m_range = m_high - m_low;
16299 #ifdef __PCL_MACOSX
16300 if ( 1 + m_range != 1 )
16302 this->Execute( [=](
const sample* __restrict__ f )
16304 double d; P::FromSample( d, *f );
16308 ++H[
TruncInt( (__PCL_MEDIAN_HISTOGRAM_LENGTH - 1) * (d - m_low)/m_range )];
16315 const double& m_low;
16316 const double& m_high;
16322 class TwoSidedAbsDevHistogramThread :
public RectThreadBase
16328 TwoSidedAbsDevHistogramThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow,
16329 double center,
const int& side,
const double& low,
const double& high )
16330 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
16331 , H( __PCL_MEDIAN_HISTOGRAM_LENGTH )
16332 , m_center( center )
16342 m_range = m_high - m_low;
16345 #ifdef __PCL_MACOSX
16346 if ( 1 + m_range != 1 )
16348 this->Execute( [=](
const sample* __restrict__ f )
16350 double x; P::FromSample( x, *f );
16351 if ( m_side > 0 == x > m_center )
16353 double d = m_side ? x - m_center : m_center - x;
16356 ++H[
TruncInt( (__PCL_MEDIAN_HISTOGRAM_LENGTH - 1) * (d - m_low)/m_range )];
16365 const double& m_low;
16366 const double& m_high;
16372 class VarThread :
public RectThreadBase
16378 VarThread(
const GenericImage& image,
double mean,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
16379 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
16387 this->Execute( [=](
const sample* __restrict__ f )
16389 double d; P::FromSample( d, *f );
16403 class SumAbsDevThread :
public SumThread
16407 SumAbsDevThread(
const GenericImage& image,
double center,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
16408 : SumThread( image, rect, ch1, ch2, firstRow, endRow )
16409 , m_center( center )
16417 void DoExecute()
override
16419 this->Execute( [=](
const sample* __restrict__ f )
16421 double v; P::FromSample( v, *f );
16422 this->SumStep(
pcl::Abs( v - m_center ) );
16429 class TwoSidedSumAbsDevThread :
public RectThreadBase
16436 TwoSidedSumAbsDevThread(
const GenericImage& image,
double center,
16437 const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
16438 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
16439 , m_center( center )
16447 this->Execute( [=](
const sample* __restrict__ f )
16449 double v; P::FromSample( v, *f );
16450 if ( v <= m_center )
16452 s0 += m_center - v;
16457 s1 += v - m_center;
16470 class BWMVThread :
public RectThreadBase
16477 BWMVThread(
const GenericImage& image,
double center,
double kd,
16478 const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
16479 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
16480 , m_center( center )
16489 this->Execute( [=](
const sample* __restrict__ f )
16492 double xc; P::FromSample( xc, *f ); xc -= m_center;
16493 double y = xc/m_kd;
16497 double y21 = 1 - y2;
16498 num += xc*xc * y21*y21*y21*y21;
16499 den += y21 * (1 - 5*y2);
16513 class TwoSidedBWMVThread :
public RectThreadBase
16521 TwoSidedBWMVThread(
const GenericImage& image,
double center,
double kd0,
double kd1,
16522 const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
16523 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
16524 , m_center( center )
16532 num0 = den0 = num1 = den1 = 0;
16533 n0 = n1 = nr0 = nr1 = 0;
16534 this->Execute( [=](
const sample* __restrict__ f )
16536 double xc; P::FromSample( xc, *f ); xc -= m_center;
16537 bool low = xc <= 0;
16543 double y = xc/(low ? m_kd0 : m_kd1);
16547 double y21 = 1 - y2;
16548 double num = xc*xc * y21*y21*y21*y21;
16549 double den = y21 * (1 - 5*y2);
16575 class SmpThread :
public RectThreadBase
16579 Array<sample> samples;
16582 SmpThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
16583 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
16586 *
size_type( this->m_endRow - this->m_firstRow )
16587 * (1 + this->m_ch2 - this->m_ch1);
16588 samples = Array<sample>( N );
16594 this->Execute( [=](
const sample* __restrict__ f )
16603 class DSmpThread :
public RectThreadBase
16607 Array<double> values;
16610 DSmpThread(
const GenericImage& image,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
16611 : RectThreadBase( image, rect, ch1, ch2, firstRow, endRow )
16614 *
size_type( this->m_endRow - this->m_firstRow )
16615 * (1 + this->m_ch2 - this->m_ch1);
16616 values = Array<double>( N );
16627 virtual void DoExecute()
16629 this->Execute( [=](
const sample* __restrict__ f )
16631 P::FromSample( values[n++], *f );
16638 class AbsDevSmpThread :
public DSmpThread
16642 AbsDevSmpThread(
const GenericImage& image,
double center,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
16643 : DSmpThread( image, rect, ch1, ch2, firstRow, endRow )
16644 , m_center( center )
16652 void DoExecute()
override
16654 this->Execute( [=](
const sample* __restrict__ f )
16656 double d; P::FromSample( d, *f );
16657 this->values[this->n++] =
pcl::Abs( d - m_center );
16664 class TwoSidedAbsDevSmpThread :
public DSmpThread
16670 TwoSidedAbsDevSmpThread(
const GenericImage& image,
double center,
const Rect& rect,
int ch1,
int ch2,
int firstRow,
int endRow )
16671 : DSmpThread( image, rect, ch1, ch2, firstRow, endRow )
16672 , m_center( center )
16680 void DoExecute()
override
16682 p = this->values.Begin();
16683 q = this->values.End();
16684 this->Execute( [=](
const sample* __restrict__ f )
16686 double x; P::FromSample( x, *f );
16687 if ( x <= m_center )
16688 *p++ = m_center - x;
16690 *--q = x - m_center;
16698 class ColorSpaceConversionThread :
public Thread
16702 ColorSpaceConversionThread( GenericImage& image, ThreadData& data,
16706 , m_toColorSpace( toColorSpace )
16716 const RGBColorSystem& rgbws = m_image.RGBWorkingSpace();
16718 typename P::sample* f0 = m_image[0] + m_begin;
16719 typename P::sample* f1 = m_image[1] + m_begin;
16720 typename P::sample* f2 = m_image[2] + m_begin;
16721 typename P::sample* fN = m_image[0] + m_end;
16723 for ( ; f0 < fN; ++f0, ++f1, ++f2 )
16725 RGBColorSystem::sample r0, r1, r2;
16726 P::FromSample( r0, *f0 );
16727 P::FromSample( r1, *f1 );
16728 P::FromSample( r2, *f2 );
16730 switch ( m_image.ColorSpace() )
16732 case ColorSpace::RGB :
16733 switch ( m_toColorSpace )
16735 case ColorSpace::Gray :
16736 rgbws.RGBToGray( r0, r0, r1, r2 );
16738 case ColorSpace::HSV :
16739 rgbws.RGBToHSV( r0, r1, r2, r0, r1, r2 );
16741 case ColorSpace::HSI :
16742 rgbws.RGBToHSI( r0, r1, r2, r0, r1, r2 );
16744 case ColorSpace::CIEXYZ :
16745 rgbws.RGBToCIEXYZ( r0, r1, r2, r0, r1, r2 );
16747 case ColorSpace::CIELab :
16748 rgbws.RGBToCIELab( r0, r1, r2, r0, r1, r2 );
16750 case ColorSpace::CIELch :
16751 rgbws.RGBToCIELch( r0, r1, r2, r0, r1, r2 );
16757 case ColorSpace::HSV :
16758 rgbws.HSVToRGB( r0, r1, r2, r0, r1, r2 );
16759 switch ( m_toColorSpace )
16761 case ColorSpace::Gray :
16762 rgbws.RGBToGray( r0, r0, r1, r2 );
16764 case ColorSpace::RGB :
16766 case ColorSpace::HSI :
16767 rgbws.RGBToHSI( r0, r1, r2, r0, r1, r2 );
16769 case ColorSpace::CIEXYZ :
16770 rgbws.RGBToCIEXYZ( r0, r1, r2, r0, r1, r2 );
16772 case ColorSpace::CIELab :
16773 rgbws.RGBToCIELab( r0, r1, r2, r0, r1, r2 );
16775 case ColorSpace::CIELch :
16776 rgbws.RGBToCIELch( r0, r1, r2, r0, r1, r2 );
16782 case ColorSpace::HSI :
16783 rgbws.HSIToRGB( r0, r1, r2, r0, r1, r2 );
16784 switch ( m_toColorSpace )
16786 case ColorSpace::Gray :
16787 rgbws.RGBToGray( r0, r0, r1, r2 );
16789 case ColorSpace::RGB :
16791 case ColorSpace::HSV :
16792 rgbws.RGBToHSV( r0, r1, r2, r0, r1, r2 );
16794 case ColorSpace::CIEXYZ :
16795 rgbws.RGBToCIEXYZ( r0, r1, r2, r0, r1, r2 );
16797 case ColorSpace::CIELab :
16798 rgbws.RGBToCIELab( r0, r1, r2, r0, r1, r2 );
16800 case ColorSpace::CIELch :
16801 rgbws.RGBToCIELch( r0, r1, r2, r0, r1, r2 );
16807 case ColorSpace::CIEXYZ :
16808 switch ( m_toColorSpace )
16810 case ColorSpace::Gray :
16811 rgbws.CIEXYZToRGB( r0, r1, r2, r0, r1, r2 );
16812 rgbws.RGBToGray( r0, r0, r1, r2 );
16814 case ColorSpace::RGB :
16815 rgbws.CIEXYZToRGB( r0, r1, r2, r0, r1, r2 );
16817 case ColorSpace::HSV :
16818 rgbws.CIEXYZToRGB( r0, r1, r2, r0, r1, r2 );
16819 rgbws.RGBToHSV( r0, r1, r2, r0, r1, r2 );
16821 case ColorSpace::HSI :
16822 rgbws.CIEXYZToRGB( r0, r1, r2, r0, r1, r2 );
16823 rgbws.RGBToHSI( r0, r1, r2, r0, r1, r2 );
16825 case ColorSpace::CIELab :
16826 rgbws.CIEXYZToCIELab( r0, r1, r2, r0, r1, r2 );
16828 case ColorSpace::CIELch :
16829 rgbws.CIEXYZToCIELab( r0, r1, r2, r0, r1, r2 );
16830 rgbws.CIELabToCIELch( r0, r1, r2, r0, r1, r2 );
16836 case ColorSpace::CIELab :
16837 switch ( m_toColorSpace )
16839 case ColorSpace::Gray :
16840 rgbws.CIELabToRGB( r0, r1, r2, r0, r1, r2 );
16841 rgbws.RGBToGray( r0, r0, r1, r2 );
16843 case ColorSpace::RGB :
16844 rgbws.CIELabToRGB( r0, r1, r2, r0, r1, r2 );
16846 case ColorSpace::HSV :
16847 rgbws.CIELabToRGB( r0, r1, r2, r0, r1, r2 );
16848 rgbws.RGBToHSV( r0, r1, r2, r0, r1, r2 );
16850 case ColorSpace::HSI :
16851 rgbws.CIELabToRGB( r0, r1, r2, r0, r1, r2 );
16852 rgbws.RGBToHSI( r0, r1, r2, r0, r1, r2 );
16854 case ColorSpace::CIEXYZ :
16855 rgbws.CIELabToCIEXYZ( r0, r1, r2, r0, r1, r2 );
16857 case ColorSpace::CIELch :
16858 rgbws.CIELabToCIELch( r0, r1, r2, r0, r1, r2 );
16864 case ColorSpace::CIELch :
16865 switch ( m_toColorSpace )
16867 case ColorSpace::Gray :
16868 rgbws.CIELchToRGB( r0, r1, r2, r0, r1, r2 );
16869 rgbws.RGBToGray( r0, r0, r1, r2 );
16871 case ColorSpace::RGB :
16872 rgbws.CIELchToRGB( r0, r1, r2, r0, r1, r2 );
16874 case ColorSpace::HSV :
16875 rgbws.CIELchToRGB( r0, r1, r2, r0, r1, r2 );
16876 rgbws.RGBToHSV( r0, r1, r2, r0, r1, r2 );
16878 case ColorSpace::HSI :
16879 rgbws.CIELchToRGB( r0, r1, r2, r0, r1, r2 );
16880 rgbws.RGBToHSI( r0, r1, r2, r0, r1, r2 );
16882 case ColorSpace::CIEXYZ :
16883 rgbws.CIELchToCIELab( r0, r1, r2, r0, r1, r2 );
16884 rgbws.CIELabToCIEXYZ( r0, r1, r2, r0, r1, r2 );
16886 case ColorSpace::CIELab :
16887 rgbws.CIELchToCIELab( r0, r1, r2, r0, r1, r2 );
16897 *f0 = P::ToSample( r0 );
16899 if ( m_toColorSpace != ColorSpace::Gray )
16901 *f1 = P::ToSample( r1 );
16902 *f2 = P::ToSample( r2 );
16911 GenericImage& m_image;
16912 ThreadData& m_data;
16913 color_space m_toColorSpace;
16919 template <
class P1>
16920 class GetLuminanceThread :
public Thread
16924 GetLuminanceThread( GenericImage<P1>& luminance,
const GenericImage& image, ThreadData& data,
16925 const Rect& rect,
int firstRow,
int endRow )
16926 : m_luminance( luminance )
16930 , m_firstRow( firstRow )
16931 , m_endRow( endRow )
16939 const RGBColorSystem& rgbws = m_image.RGBWorkingSpace();
16941 const typename P::sample* f0 = m_image.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 0 );
16942 const typename P::sample* f1 = m_image.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 1 );
16943 const typename P::sample* f2 = m_image.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 2 );
16945 typename P1::sample* fY = m_luminance.ScanLine( m_firstRow );
16947 for (
int y = m_firstRow, dw = m_image.Width()-m_rect.Width();
16949 ++y, f0 += dw, f1 += dw, f2 += dw )
16951 const typename P::sample* fN = f0 + m_rect.Width();
16953 for ( ; f0 < fN; ++f0, ++f1, ++f2, ++fY )
16955 RGBColorSystem::sample r0, r1, r2, rY;
16956 P::FromSample( r0, *f0 );
16957 P::FromSample( r1, *f1 );
16958 P::FromSample( r2, *f2 );
16960 switch ( m_image.ColorSpace() )
16962 case ColorSpace::RGB:
16963 case ColorSpace::HSV:
16964 case ColorSpace::HSI:
16965 switch ( m_image.ColorSpace() )
16967 case ColorSpace::HSV:
16968 rgbws.HSVToRGB( r0, r1, r2, r0, r1, r2 );
16970 case ColorSpace::HSI:
16971 rgbws.HSIToRGB( r0, r1, r2, r0, r1, r2 );
16976 rY = rgbws.CIEY( r0, r1, r2 );
16979 case ColorSpace::CIELch:
16980 rgbws.CIELchToCIELab( r0, r1, r2, r0, r1, r2 );
16982 case ColorSpace::CIELab:
16983 rgbws.CIELabToCIEXYZ( r0, rY, r2, r0, r1, r2 );
16991 *fY = P1::ToSample( rY );
17000 GenericImage<P1>& m_luminance;
17001 const GenericImage& m_image;
17002 ThreadData& m_data;
17003 const Rect& m_rect;
17004 int m_firstRow, m_endRow;
17009 template <
class P1>
17010 class GetLightnessThread :
public Thread
17014 GetLightnessThread( GenericImage<P1>& lightness,
const GenericImage& image, ThreadData& data,
17015 const Rect& rect,
int firstRow,
int endRow )
17016 : m_lightness( lightness )
17020 , m_firstRow( firstRow )
17021 , m_endRow( endRow )
17029 const RGBColorSystem& rgbws = m_image.RGBWorkingSpace();
17031 const typename P::sample* f0 = m_image.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 0 );
17032 const typename P::sample* f1 = m_image.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 1 );
17033 const typename P::sample* f2 = m_image.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 2 );
17035 typename P1::sample* fL = m_lightness.ScanLine( m_firstRow );
17037 for (
int y = m_firstRow, dw = m_image.Width()-m_rect.Width();
17039 ++y, f0 += dw, f1 += dw, f2 += dw )
17041 const typename P::sample* fN = f0 + m_rect.Width();
17043 for ( ; f0 < fN; ++f0, ++f1, ++f2, ++fL )
17045 RGBColorSystem::sample r0, r1, r2, rL;
17046 P::FromSample( r0, *f0 );
17047 P::FromSample( r1, *f1 );
17048 P::FromSample( r2, *f2 );
17050 switch ( m_image.ColorSpace() )
17052 case ColorSpace::RGB:
17053 case ColorSpace::HSV:
17054 case ColorSpace::HSI:
17055 case ColorSpace::CIEXYZ:
17056 switch ( m_image.ColorSpace() )
17058 case ColorSpace::HSV:
17059 rgbws.HSVToRGB( r0, r1, r2, r0, r1, r2 );
17061 case ColorSpace::HSI:
17062 rgbws.HSIToRGB( r0, r1, r2, r0, r1, r2 );
17064 case ColorSpace::CIEXYZ:
17065 rgbws.CIEXYZToRGB( r0, r1, r2, r0, r1, r2 );
17070 rL = rgbws.CIEL( r0, r1, r2 );
17078 *fL = P1::ToSample( rL );
17087 GenericImage<P1>& m_lightness;
17088 const GenericImage& m_image;
17089 ThreadData& m_data;
17090 const Rect& m_rect;
17091 int m_firstRow, m_endRow;
17096 template <
class P1>
17097 class GetIntensityThread :
public Thread
17101 GetIntensityThread( GenericImage<P1>& luminance,
const GenericImage& image, ThreadData& data,
17102 const Rect& rect,
int firstRow,
int endRow )
17103 : m_intensity( luminance )
17107 , m_firstRow( firstRow )
17108 , m_endRow( endRow )
17116 const RGBColorSystem& rgbws = m_image.RGBWorkingSpace();
17118 const typename P::sample* f0 = m_image.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 0 );
17119 const typename P::sample* f1 = m_image.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 1 );
17120 const typename P::sample* f2 = m_image.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 2 );
17122 typename P1::sample* fI = m_intensity.ScanLine( m_firstRow );
17124 for (
int y = m_firstRow, dw = m_image.Width()-m_rect.Width();
17126 ++y, f0 += dw, f1 += dw, f2 += dw )
17128 const typename P::sample* fN = f0 + m_rect.Width();
17130 for ( ; f0 < fN; ++f0, ++f1, ++f2, ++fI )
17132 RGBColorSystem::sample r0, r1, r2;
17133 P::FromSample( r0, *f0 );
17134 P::FromSample( r1, *f1 );
17135 P::FromSample( r2, *f2 );
17137 switch ( m_image.ColorSpace() )
17139 case ColorSpace::RGB:
17141 case ColorSpace::HSV:
17142 rgbws.HSVToRGB( r0, r1, r2, r0, r1, r2 );
17144 case ColorSpace::CIEXYZ:
17145 rgbws.CIEXYZToRGB( r0, r1, r2, r0, r1, r2 );
17147 case ColorSpace::CIELab:
17148 rgbws.CIELabToRGB( r0, r1, r2, r0, r1, r2 );
17150 case ColorSpace::CIELch:
17151 rgbws.CIELchToRGB( r0, r1, r2, r0, r1, r2 );
17157 *fI = P1::ToSample( rgbws.Intensity( r0, r1, r2 ) );
17166 GenericImage<P1>& m_intensity;
17167 const GenericImage& m_image;
17168 ThreadData& m_data;
17169 const Rect& m_rect;
17170 int m_firstRow, m_endRow;
17175 template <
class P1>
17176 class SetLuminanceThread :
public Thread
17180 SetLuminanceThread( GenericImage& image,
const GenericImage<P1>& luminance, ThreadData& data,
17181 const Point& target,
const Rect& rect,
int firstRow,
int endRow )
17183 , m_luminance( luminance )
17185 , m_target( target )
17187 , m_firstRow( firstRow )
17188 , m_endRow( endRow )
17196 const RGBColorSystem& sourceRGBWS = m_luminance.RGBWorkingSpace();
17197 const RGBColorSystem& targetRGBWS = m_image.RGBWorkingSpace();
17199 typename P::sample* f0 = m_image.PixelAddress( m_target.x, m_target.y + m_firstRow, 0 );
17200 typename P::sample* f1 = m_image.PixelAddress( m_target.x, m_target.y + m_firstRow, 1 );
17201 typename P::sample* f2 = m_image.PixelAddress( m_target.x, m_target.y + m_firstRow, 2 );
17203 if ( m_luminance.ColorSpace() == ColorSpace::Gray || m_luminance.ColorSpace() == ColorSpace::CIEXYZ )
17205 int cY = (m_luminance.ColorSpace() == ColorSpace::Gray) ? 0 : 1;
17206 const typename P1::sample* fY = m_luminance.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, cY );
17208 for (
int y = m_firstRow, dw = m_image.Width()-m_rect.Width(), dwY = m_luminance.Width()-m_rect.Width();
17210 ++y, f0 += dw, f1 += dw, f2 += dw, fY += dwY )
17212 const typename P::sample* fN = f0 + m_rect.Width();
17214 for ( ; f0 < fN; ++f0, ++f1, ++f2, ++fY )
17216 RGBColorSystem::sample r0, r1, r2, rY;
17217 P::FromSample( r0, *f0 );
17218 P::FromSample( r1, *f1 );
17219 P::FromSample( r2, *f2 );
17220 P1::FromSample( rY, *fY );
17222 switch ( m_image.ColorSpace() )
17224 case ColorSpace::RGB:
17225 case ColorSpace::HSV:
17226 case ColorSpace::HSI:
17227 switch ( m_image.ColorSpace() )
17229 case ColorSpace::HSV:
17230 targetRGBWS.HSVToRGB( r0, r1, r2, r0, r1, r2 );
17232 case ColorSpace::HSI:
17233 targetRGBWS.HSIToRGB( r0, r1, r2, r0, r1, r2 );
17238 targetRGBWS.RGBToCIEab( r1, r2, r0, r1, r2 );
17239 targetRGBWS.CIELabToRGB( r0, r1, r2, sourceRGBWS.CIEYToCIEL( rY ), r1, r2 );
17240 switch ( m_image.ColorSpace() )
17242 case ColorSpace::HSV:
17243 targetRGBWS.RGBToHSV( r0, r1, r2, r0, r1, r2 );
17245 case ColorSpace::HSI:
17246 targetRGBWS.RGBToHSI( r0, r1, r2, r0, r1, r2 );
17253 case ColorSpace::CIEXYZ:
17254 targetRGBWS.CIEXYZToCIELab( r0, r1, r2, r0, r1, r2 );
17255 targetRGBWS.CIELabToCIEXYZ( r0, r1, r2, sourceRGBWS.CIEYToCIEL( rY ), r1, r2 );
17258 case ColorSpace::CIELab:
17259 case ColorSpace::CIELch:
17260 r0 = sourceRGBWS.CIEYToCIEL( rY );
17267 *f0 = P::ToSample( r0 );
17268 *f1 = P::ToSample( r1 );
17269 *f2 = P::ToSample( r2 );
17277 const typename P1::sample* g0 = m_luminance.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 0 );
17278 const typename P1::sample* g1 = m_luminance.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 1 );
17279 const typename P1::sample* g2 = m_luminance.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 2 );
17281 for (
int y = m_firstRow, dw = m_image.Width()-m_rect.Width(), dwY = m_luminance.Width()-m_rect.Width();
17283 ++y, f0 += dw, f1 += dw, f2 += dw, g0 += dwY, g1 += dwY, g2 += dwY )
17285 const typename P::sample* fN = f0 + m_rect.Width();
17287 for ( ; f0 < fN; ++f0, ++f1, ++f2, ++g0, ++g1, ++g2 )
17289 typename RGBColorSystem::sample r0, r1, r2, s0, s1, s2;
17290 P::FromSample( r0, *f0 );
17291 P::FromSample( r1, *f1 );
17292 P::FromSample( r2, *f2 );
17293 P1::FromSample( s0, *g0 );
17294 P1::FromSample( s1, *g1 );
17295 P1::FromSample( s2, *g2 );
17297 switch ( m_image.ColorSpace() )
17299 case ColorSpace::RGB:
17300 case ColorSpace::HSV:
17301 case ColorSpace::HSI:
17302 case ColorSpace::CIEXYZ:
17303 case ColorSpace::CIELab:
17304 case ColorSpace::CIELch:
17305 switch ( m_image.ColorSpace() )
17307 case ColorSpace::RGB:
17308 case ColorSpace::HSV:
17309 case ColorSpace::HSI:
17310 switch ( m_image.ColorSpace() )
17312 case ColorSpace::HSV:
17313 targetRGBWS.HSVToRGB( r0, r1, r2, r0, r1, r2 );
17315 case ColorSpace::HSI:
17316 targetRGBWS.HSIToRGB( r0, r1, r2, r0, r1, r2 );
17321 targetRGBWS.RGBToCIEab( r1, r2, r0, r1, r2 );
17323 case ColorSpace::CIEXYZ:
17324 targetRGBWS.CIEXYZToCIELab( r0, r1, r2, r0, r1, r2 );
17326 case ColorSpace::CIELab:
17327 case ColorSpace::CIELch:
17333 switch ( m_luminance.ColorSpace() )
17335 case ColorSpace::RGB:
17336 case ColorSpace::HSV:
17337 case ColorSpace::HSI:
17338 switch ( m_luminance.ColorSpace() )
17340 case ColorSpace::HSV:
17341 sourceRGBWS.HSVToRGB( s0, s1, s2, s0, s1, s2 );
17343 case ColorSpace::HSI:
17344 sourceRGBWS.HSIToRGB( s0, s1, s2, s0, s1, s2 );
17349 r0 = sourceRGBWS.CIEL( s0, s1, s2 );
17351 case ColorSpace::CIEXYZ:
17352 sourceRGBWS.CIEXYZToCIELab( r0, s1, s2, s0, s1, s2 );
17354 case ColorSpace::CIELab:
17355 case ColorSpace::CIELch:
17362 switch ( m_image.ColorSpace() )
17364 case ColorSpace::RGB:
17365 case ColorSpace::HSV:
17366 case ColorSpace::HSI:
17367 targetRGBWS.CIELabToRGB( r0, r1, r2, r0, r1, r2 );
17368 switch ( m_image.ColorSpace() )
17370 case ColorSpace::HSV:
17371 targetRGBWS.RGBToHSV( r0, r1, r2, r0, r1, r2 );
17373 case ColorSpace::HSI:
17374 targetRGBWS.RGBToHSI( r0, r1, r2, r0, r1, r2 );
17380 case ColorSpace::CIEXYZ:
17381 targetRGBWS.CIELabToCIEXYZ( r0, r1, r2, r0, r1, r2 );
17383 case ColorSpace::CIELab:
17384 case ColorSpace::CIELch:
17395 *f0 = P::ToSample( r0 );
17396 *f1 = P::ToSample( r1 );
17397 *f2 = P::ToSample( r2 );
17407 GenericImage& m_image;
17408 const GenericImage<P1>& m_luminance;
17409 ThreadData& m_data;
17410 const Point& m_target;
17411 const Rect& m_rect;
17412 int m_firstRow, m_endRow;
17417 template <
class P1>
17418 class SetLightnessThread :
public Thread
17422 SetLightnessThread( GenericImage& image,
const GenericImage<P1>& lightness, ThreadData& data,
17423 const Point& target,
const Rect& rect,
int firstRow,
int endRow )
17425 , m_lightness( lightness )
17427 , m_target( target )
17429 , m_firstRow( firstRow )
17430 , m_endRow( endRow )
17438 const RGBColorSystem& sourceRGBWS = m_lightness.RGBWorkingSpace();
17439 const RGBColorSystem& targetRGBWS = m_image.RGBWorkingSpace();
17441 typename P::sample* f0 = m_image.PixelAddress( m_target.x, m_target.y + m_firstRow, 0 );
17442 typename P::sample* f1 = m_image.PixelAddress( m_target.x, m_target.y + m_firstRow, 1 );
17443 typename P::sample* f2 = m_image.PixelAddress( m_target.x, m_target.y + m_firstRow, 2 );
17445 if ( m_lightness.ColorSpace() == ColorSpace::Gray ||
17446 m_lightness.ColorSpace() == ColorSpace::CIELab || m_lightness.ColorSpace() == ColorSpace::CIELch )
17448 const typename P1::sample* fL = m_lightness.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 0 );
17450 for (
int y = m_firstRow, dw = m_image.Width()-m_rect.Width(), dwL = m_lightness.Width()-m_rect.Width();
17452 ++y, f0 += dw, f1 += dw, f2 += dw, fL += dwL )
17454 const typename P::sample* fN = f0 + m_rect.Width();
17456 for ( ; f0 < fN; ++f0, ++f1, ++f2, ++fL )
17458 RGBColorSystem::sample r0, r1, r2, rL;
17459 P::FromSample( r0, *f0 );
17460 P::FromSample( r1, *f1 );
17461 P::FromSample( r2, *f2 );
17462 P1::FromSample( rL, *fL );
17464 switch ( m_image.ColorSpace() )
17466 case ColorSpace::RGB:
17467 case ColorSpace::HSV:
17468 case ColorSpace::HSI:
17469 switch ( m_image.ColorSpace() )
17471 case ColorSpace::HSV:
17472 targetRGBWS.HSVToRGB( r0, r1, r2, r0, r1, r2 );
17474 case ColorSpace::HSI:
17475 targetRGBWS.HSIToRGB( r0, r1, r2, r0, r1, r2 );
17480 targetRGBWS.RGBToCIEab( r1, r2, r0, r1, r2 );
17481 targetRGBWS.CIELabToRGB( r0, r1, r2, rL, r1, r2 );
17482 switch ( m_image.ColorSpace() )
17484 case ColorSpace::HSV:
17485 targetRGBWS.RGBToHSV( r0, r1, r2, r0, r1, r2 );
17487 case ColorSpace::HSI:
17488 targetRGBWS.RGBToHSI( r0, r1, r2, r0, r1, r2 );
17495 case ColorSpace::CIEXYZ:
17496 r1 = targetRGBWS.CIELToCIEY( rL );
17499 case ColorSpace::CIELab:
17500 case ColorSpace::CIELch:
17508 *f0 = P::ToSample( r0 );
17509 *f1 = P::ToSample( r1 );
17510 *f2 = P::ToSample( r2 );
17518 const typename P1::sample* g0 = m_lightness.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 0 );
17519 const typename P1::sample* g1 = m_lightness.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 1 );
17520 const typename P1::sample* g2 = m_lightness.PixelAddress( m_rect.x0, m_rect.y0 + m_firstRow, 2 );
17522 for (
int y = m_firstRow, dw = m_image.Width()-m_rect.Width(), dwL = m_lightness.Width()-m_rect.Width();
17524 ++y, f0 += dw, f1 += dw, f2 += dw, g0 += dwL, g1 += dwL, g2 += dwL )
17526 const typename P::sample* fN = f0 + m_rect.Width();
17528 for ( ; f0 < fN; ++f0, ++f1, ++f2, ++g0, ++g1, ++g2 )
17530 typename RGBColorSystem::sample r0, r1, r2, s0, s1, s2;
17531 P::FromSample( r0, *f0 );
17532 P::FromSample( r1, *f1 );
17533 P::FromSample( r2, *f2 );
17534 P1::FromSample( s0, *g0 );
17535 P1::FromSample( s1, *g1 );
17536 P1::FromSample( s2, *g2 );
17538 switch ( m_image.ColorSpace() )
17540 case ColorSpace::RGB:
17541 case ColorSpace::HSV:
17542 case ColorSpace::HSI:
17543 case ColorSpace::CIEXYZ:
17544 case ColorSpace::CIELab:
17545 case ColorSpace::CIELch:
17546 switch ( m_image.ColorSpace() )
17548 case ColorSpace::RGB:
17549 case ColorSpace::HSV:
17550 case ColorSpace::HSI:
17551 switch ( m_image.ColorSpace() )
17553 case ColorSpace::HSV:
17554 targetRGBWS.HSVToRGB( r0, r1, r2, r0, r1, r2 );
17556 case ColorSpace::HSI:
17557 targetRGBWS.HSIToRGB( r0, r1, r2, r0, r1, r2 );
17562 targetRGBWS.RGBToCIEab( r1, r2, r0, r1, r2 );
17564 case ColorSpace::CIEXYZ:
17565 targetRGBWS.CIEXYZToCIELab( r0, r1, r2, r0, r1, r2 );
17567 case ColorSpace::CIELch:
17568 targetRGBWS.CIELchToCIELab( r0, r1, r2, r0, r1, r2 );
17574 switch ( m_lightness.ColorSpace() )
17576 case ColorSpace::RGB:
17577 case ColorSpace::HSV:
17578 case ColorSpace::HSI:
17579 switch ( m_lightness.ColorSpace() )
17581 case ColorSpace::HSV:
17582 sourceRGBWS.HSVToRGB( s0, s1, s2, s0, s1, s2 );
17584 case ColorSpace::HSI:
17585 sourceRGBWS.HSIToRGB( s0, s1, s2, s0, s1, s2 );
17590 r0 = sourceRGBWS.CIEL( s0, s1, s2 );
17592 case ColorSpace::CIEXYZ:
17593 r0 = sourceRGBWS.CIEYToCIEL( s1 );
17599 switch ( m_image.ColorSpace() )
17601 case ColorSpace::RGB:
17602 case ColorSpace::HSV:
17603 case ColorSpace::HSI:
17604 targetRGBWS.CIELabToRGB( r0, r1, r2, r0, r1, r2 );
17605 switch ( m_image.ColorSpace() )
17607 case ColorSpace::HSV:
17608 targetRGBWS.RGBToHSV( r0, r1, r2, r0, r1, r2 );
17610 case ColorSpace::HSI:
17611 targetRGBWS.RGBToHSI( r0, r1, r2, r0, r1, r2 );
17617 case ColorSpace::CIEXYZ:
17618 targetRGBWS.CIELabToCIEXYZ( r0, r1, r2, r0, r1, r2 );
17620 case ColorSpace::CIELch:
17621 targetRGBWS.CIELabToCIELch( r0, r1, r2, r0, r1, r2 );
17631 *f0 = P::ToSample( r0 );
17632 *f1 = P::ToSample( r1 );
17633 *f2 = P::ToSample( r2 );
17643 GenericImage& m_image;
17644 const GenericImage<P1>& m_lightness;
17645 ThreadData& m_data;
17646 const Point& m_target;
17647 const Rect& m_rect;
17648 int m_firstRow, m_endRow;
17653 #ifdef __PCL_BUILDING_PIXINSIGHT_APPLICATION
17654 friend class pi::SharedImage;
17659 #undef m_channelData
17663 #undef m_numberOfChannels
17664 #undef m_colorSpace
17667 #undef m_lastChannel
17672 #undef m_clippedLow
17673 #undef m_clippedHigh
17686 template <
class P,
typename T>
inline
17690 (void)(result += scalar);
17702 template <
class P,
typename T>
inline
17705 return image + scalar;
17713 template <
class P,
typename T>
inline
17717 (void)(result -= scalar);
17726 template <
class P,
typename T>
inline
17730 (void)(result *= scalar);
17743 template <
class P,
typename T>
inline
17746 return image * scalar;
17754 template <
class P,
typename T>
inline
17758 (void)(result /= scalar);
17767 template <
class P,
typename T>
inline
17771 (void)(result ^= scalar);
17793 template <
class P1,
class P2>
inline
17797 (void)(result += image2);
17813 template <
class P1,
class P2>
inline
17817 (void)(result -= image2);
17833 template <
class P1,
class P2>
inline
17837 (void)(result *= image2);
17854 template <
class P1,
class P2>
inline
17858 (void)(result /= image2);
17875 template <
class P1,
class P2>
inline
17879 (void)(result ^= image2);
17885 #ifndef __PCL_NO_IMAGE_INSTANTIATE
17898 using FImage = GenericImage<FloatPixelTraits>;
17907 using DImage = GenericImage<DoublePixelTraits>;
17937 using UInt8Image = GenericImage<UInt8PixelTraits>;
17947 using UInt16Image = GenericImage<UInt16PixelTraits>;
17957 using UInt32Image = GenericImage<UInt32PixelTraits>;
17987 #ifndef __PCL_NO_IMAGE_VARIANT_AUTO
17989 #ifndef __PCL_ImageVariant_h
Base class of all two-dimensional images in PCL.
int LastSelectedChannel() const noexcept
bool IsCompletelySelected() const noexcept
int FirstSelectedChannel() const noexcept
void ResetSelections() const noexcept
StatusMonitor & Status() const noexcept
bool ParseSelection(Rect &rect, int &firstChannel, int &lastChannel) const noexcept
Client-side interface to a PixInsight Bitmap object.
32-bit floating point complex image.
Abstract base class of data compression algorithm implementations.
subblock_list Compress(const void *data, size_type size, Performance *perf=nullptr) const
Image cropping/expansion algorithm
64-bit floating point complex image.
64-bit floating point real image.
A simple exception with an associated error message.
32-bit floating point complex image.
32-bit floating point real image.
A platform-independent interface to the local file system.
virtual void Write(const void *buffer, fsize_type len)
void WriteUI32(const T &x)
virtual void Read(void *buffer, fsize_type len)
Immutable filter pixel iterator.
const_filter_pixel_iterator(const const_filter_pixel_iterator &)=default
typename image_type::sample sample
const_filter_pixel_iterator & MoveBy(int dx, int dy) noexcept
const_filter_pixel_iterator(const image_type &image, const F &filter)
const_filter_pixel_iterator(const const_pixel_iterator &i, const F &filter)
const filter_type & Filter() const noexcept
typename image_type::pixel_traits pixel_traits
bool IsValid() const noexcept
const image_type & Image() const noexcept
const sample * Position(int channel) const noexcept
filter_type & Filter() noexcept
const_filter_pixel_iterator()=default
Immutable filter pixel sample iterator.
const_filter_sample_iterator()=default
filter_type & Filter() noexcept
const_filter_sample_iterator(const image_type &image, const F &filter, int channel=-1)
const_filter_sample_iterator & MoveBy(int dx, int dy) noexcept
const image_type & Image() const noexcept
bool IsValid() const noexcept
const_filter_sample_iterator(const image_type &image, const F &filter, const sample *i, const sample *j)
typename image_type::sample sample
const sample * Position() const noexcept
const filter_type & Filter() const noexcept
const_filter_sample_iterator(const const_filter_sample_iterator &)=default
typename image_type::pixel_traits pixel_traits
const_filter_sample_iterator(const sample_iterator &i, const F &filter)
const_filter_sample_iterator(const filter_sample_iterator< F > &i)
const_filter_sample_iterator(const const_sample_iterator &i, const F &filter)
Immutable pixel iterator.
const image_type & Image() const noexcept
const_pixel_iterator(const image_type &image)
typename image_type::sample sample
const_pixel_iterator(const const_pixel_iterator &)=default
const_pixel_iterator()=default
bool IsValid() const noexcept
const_pixel_iterator & MoveBy(int dx, int dy) noexcept
typename image_type::pixel_traits pixel_traits
const sample * Position(int channel) const noexcept
Immutable region-of-interest, filter pixel iterator.
const_roi_filter_pixel_iterator(const const_roi_pixel_iterator &i, const F &filter)
const_roi_filter_pixel_iterator(const image_type &image, const F &filter, const Rect &rect=Rect(0))
const_roi_filter_pixel_iterator(const const_roi_filter_pixel_iterator &)=default
const image_type & Image() const noexcept
typename image_type::sample sample
const filter_type & Filter() const noexcept
const sample * Position(int channel) const noexcept
const_roi_filter_pixel_iterator()=default
typename image_type::pixel_traits pixel_traits
filter_type & Filter() noexcept
bool IsValid() const noexcept
const_roi_filter_pixel_iterator & MoveBy(int dx, int dy) noexcept
Immutable region-of-interest, filter pixel sample iterator.
const sample * Position() const noexcept
const_roi_filter_sample_iterator(const image_type &image, const F &filter, const sample *i, const sample *j)
const_roi_filter_sample_iterator()=default
bool IsValid() const noexcept
const_roi_filter_sample_iterator(const const_roi_sample_iterator &i, const F &filter)
const_roi_filter_sample_iterator(const const_roi_filter_sample_iterator &)=default
const filter_type & Filter() const noexcept
typename image_type::pixel_traits pixel_traits
const_roi_filter_sample_iterator(const image_type &image, const F &filter, const Rect &rect=Rect(0), int channel=-1)
const image_type & Image() const noexcept
typename image_type::sample sample
filter_type & Filter() noexcept
const_roi_filter_sample_iterator & MoveBy(int dx, int dy) noexcept
Immutable region-of-interest pixel iterator.
const_roi_pixel_iterator()=default
typename image_type::sample sample
const_roi_pixel_iterator & MoveBy(int dx, int dy) noexcept
const sample * Position(int channel) const noexcept
const image_type & Image() const noexcept
const_roi_pixel_iterator(const const_roi_pixel_iterator &)=default
const_roi_pixel_iterator(const image_type &image, const Rect &rect=Rect(0))
bool IsValid() const noexcept
typename image_type::pixel_traits pixel_traits
Immutable region-of-interest pixel sample iterator.
const_roi_sample_iterator(const const_roi_sample_iterator &)=default
const_roi_sample_iterator(const image_type &image, const Rect &rect=Rect(0), int channel=-1)
const sample * Position() const noexcept
bool IsValid() const noexcept
const_roi_sample_iterator(const image_type &image, const sample *i, const sample *j)
const_roi_sample_iterator()=default
const_roi_sample_iterator & MoveBy(int dx, int dy) noexcept
const image_type & Image() const noexcept
const_roi_sample_iterator(const roi_sample_iterator &i)
typename image_type::sample sample
typename image_type::pixel_traits pixel_traits
Immutable pixel sample iterator.
const_sample_iterator(const image_type &image, int channel=-1)
const_sample_iterator()=default
const_sample_iterator(const sample_iterator &i)
typename image_type::sample sample
typename image_type::pixel_traits pixel_traits
const_sample_iterator & MoveBy(int dx, int dy) noexcept
bool IsValid() const noexcept
const image_type & Image() const noexcept
const_sample_iterator(const image_type &image, const sample *i, const sample *j)
const_sample_iterator(const const_sample_iterator &)=default
const sample * Position() const noexcept
Mutable filter pixel iterator.
filter_pixel_iterator()=default
typename image_type::pixel_traits pixel_traits
bool IsValid() const noexcept
filter_pixel_iterator & MoveBy(int dx, int dy) noexcept
sample * Position(int channel) const noexcept
filter_pixel_iterator(const pixel_iterator &i, const F &filter)
filter_pixel_iterator(const filter_pixel_iterator &)=default
typename image_type::sample sample
const filter_type & Filter() const noexcept
filter_type & Filter() noexcept
filter_pixel_iterator(image_type &image, const F &filter)
image_type & Image() const noexcept
Mutable filter pixel sample iterator.
sample * Position() const noexcept
filter_sample_iterator(const sample_iterator &i, const F &filter)
filter_sample_iterator()=default
filter_sample_iterator(const filter_sample_iterator &i)=default
filter_sample_iterator(image_type &image, const F &filter, int channel=-1)
filter_type & Filter() noexcept
image_type & Image() const noexcept
filter_sample_iterator & MoveBy(int dx, int dy) noexcept
const filter_type & Filter() const noexcept
bool IsValid() const noexcept
filter_sample_iterator(image_type &image, const F &filter, sample *i, sample *j)
typename image_type::sample sample
typename image_type::pixel_traits pixel_traits
typename image_type::pixel_traits pixel_traits
pixel_iterator & MoveBy(int dx, int dy) noexcept
pixel_iterator(image_type &image)
image_type & Image() const noexcept
sample * Position(int channel) const noexcept
pixel_iterator(const pixel_iterator &)=default
typename image_type::sample sample
bool IsValid() const noexcept
Mutable region-of-interest, filter pixel iterator.
roi_filter_pixel_iterator(const roi_filter_pixel_iterator &)=default
sample * Position(int channel) const noexcept
roi_filter_pixel_iterator(const roi_pixel_iterator &i, const F &filter)
roi_filter_pixel_iterator & MoveBy(int dx, int dy) noexcept
filter_type & Filter() noexcept
typename image_type::sample sample
bool IsValid() const noexcept
image_type & Image() const noexcept
roi_filter_pixel_iterator(image_type &image, const F &filter, const Rect &rect=Rect(0))
roi_filter_pixel_iterator()=default
const filter_type & Filter() const noexcept
typename image_type::pixel_traits pixel_traits
Mutable region-of-interest, filter pixel sample iterator.
roi_filter_sample_iterator(const roi_filter_sample_iterator &)=default
filter_type & Filter() noexcept
roi_filter_sample_iterator(image_type &image, const F &filter, const Rect &rect=Rect(0), int channel=-1)
roi_filter_sample_iterator(image_type &image, const F &filter, sample *i, sample *j)
sample * Position() const noexcept
typename image_type::sample sample
roi_filter_sample_iterator & MoveBy(int dx, int dy) noexcept
bool IsValid() const noexcept
const filter_type & Filter() const noexcept
image_type & Image() const noexcept
typename image_type::pixel_traits pixel_traits
roi_filter_sample_iterator(const roi_sample_iterator &i, const F &filter)
roi_filter_sample_iterator()=default
Mutable region-of-interest pixel iterator.
roi_pixel_iterator(const roi_pixel_iterator &)=default
sample * Position(int channel) const noexcept
typename image_type::sample sample
roi_pixel_iterator(image_type &image, const Rect &rect=Rect(0))
typename image_type::pixel_traits pixel_traits
image_type & Image() const noexcept
roi_pixel_iterator()=default
bool IsValid() const noexcept
roi_pixel_iterator & MoveBy(int dx, int dy) noexcept
Mutable region-of-interest pixel sample iterator.
sample * Position() const noexcept
roi_sample_iterator & MoveBy(int dx, int dy) noexcept
roi_sample_iterator(image_type &image, const Rect &rect=Rect(0), int channel=-1)
roi_sample_iterator(const roi_sample_iterator &)=default
typename image_type::pixel_traits pixel_traits
image_type & Image() const noexcept
typename image_type::sample sample
roi_sample_iterator(image_type &image, sample *i, sample *j)
bool IsValid() const noexcept
roi_sample_iterator()=default
Mutable pixel sample iterator.
sample_iterator()=default
sample_iterator(image_type &image, sample *i, sample *j)
sample_iterator & MoveBy(int dx, int dy) noexcept
typename image_type::sample sample
sample * Position() const noexcept
sample_iterator(image_type &image, int channel=-1)
sample_iterator(const sample_iterator &)=default
typename image_type::pixel_traits pixel_traits
bool IsValid() const noexcept
image_type & Image() const noexcept
Implements a generic, two-dimensional, shared or local image.
GenericImage & ShiftToBottomRight(int width, int height, const GenericVector< T > &fillValues)
double Norm(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
const sample * ScanLine(int y, int channel=0) const noexcept
void LocateExtremeSampleValues(Point &pmin, T &min, Point &pmax, T &max, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage & CropBy(int left, int top, int right, int bottom, const GenericVector< T > &fillValues)
double Sn(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage & Write(File &file, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
GenericImage & ShiftToBottomRight(int width, int height)
GenericImage Rescaled(T lowerBound, T upperBound, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
GenericImage & Fill(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Max(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
uint32 Hash32(int channel=-1, uint32 seed=0) const noexcept
GenericImage & ShiftToTopLeft(int width, int height, const GenericVector< T > &fillValues)
GenericImage & ShiftTo(const Point &p, const GenericVector< T > &fillValues)
GenericImage Applied(const ImageTransformation &transformation, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
GenericImage & Subtract(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage Divided(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
GenericImage & FreeData()
GenericImage Added(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
GenericImage & Assign(const GenericImage< P1 > &image, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & SetMinimum(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Xnor(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Transfer(GenericImage &image)
GenericImage & Apply(const GenericImage< P1 > &image, image_op op=ImageOp::Mov, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage Blended(const Bitmap &bitmap, const Point &point=Point(int_max), const Rect &rect=Rect(0)) const
GenericImage & SetMaximum(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
static int BytesPerSample() noexcept
void GetExtremePixelValues(sample &min, sample &max, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage(const GenericImage< P1 > &image, const Rect &rect, int firstChannel=-1, int lastChannel=-1)
sample & Pixel(int x, int y, int channel=0)
sample & Pixel(const Point &p, int channel=0)
double Qn(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage Raised(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
void GetIntensity(GenericImage< P1 > &I, const Rect &rect=Rect(0), int maxProcessors=0) const
GenericImage & ForgetAlphaChannels()
GenericImage & Nor(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Raise(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
bool SameSampleType(const GenericImage< P1 > &image) const noexcept
GenericImage & Sub(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & ShiftToBottomLeft(int width, int height, const GenericVector< T > &fillValues)
void LocateExtremeSampleValues(int &xmin, int &ymin, T &min, int &xmax, int &ymax, T &max, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
const sample * PixelAddress(const Point &p, int channel=0) const noexcept
GenericImage Inverted(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
GenericImage Truncated(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
GenericImage Subtracted(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
GenericImage & CropTo(int x0, int y0, int x1, int y1, const GenericVector< T > &fillValues)
sample * PixelAddress(int x, int y, int channel=0)
GenericImage & Crop(const GenericVector< T > &fillValues)
GenericImage & Move(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Mov(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
double Mean(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
size_type ImageSize() const noexcept
GenericImage & Read(File &file)
TwoSidedEstimate TwoSidedAvgDev(double center, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage & Or(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
void GetLightness(GenericImage< P1 > &L, const Rect &rect=Rect(0), int maxProcessors=0) const
pixel_allocator & Allocator() const noexcept
GenericImage & SetColumn(const T *buffer, int x, int channel=-1)
sample LocateMaximumPixelValue(Point &pmax, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
uint64 Hash(int channel=-1, uint64 seed=0) const noexcept
static bool IsComplexSample() noexcept
GenericImage & Nand(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Multiply(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage Applied(const GenericImage< P1 > &image, image_op op=ImageOp::Mov, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
GenericImage Applied(T scalar, image_op op=ImageOp::Mov, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
GenericImage & SetMinimum(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & SetLightness(const GenericImage< P1 > &L, const Point &point=Point(int_max), const Rect &rect=Rect(0), int maxProcessors=0)
GenericImage Multiplied(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
sample LocateMinimumPixelValue(int &xmin, int &ymin, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage Binarized(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
double MeanOfSquares(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage & White(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & ShiftToTopRight(int width, int height, const GenericVector< T > &fillValues)
GenericImage & DeleteAlphaChannel(int channel)
GenericImage & CropTo(int x0, int y0, int x1, int y1)
GenericImage & Binarize(T threshold, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
sample Pixel(int x, int y, int channel=0) const noexcept
GenericImage Binarized(T threshold, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
GenericImage & SetAbsoluteValue(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage AbsoluteValue(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
GenericImage & ShiftToCenter(int width, int height, const GenericVector< T > &fillValues)
bool SameSampleType(const GenericImage &image) const noexcept
GenericImage & Nor(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
bool IsUnique() const noexcept
void GetExtremeSampleValues(T &min, T &max, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage & Dif(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & CropTo(const Rect &rect)
GenericImage & EnsureLocal()
GenericImage(int width, int height, color_space colorSpace=ColorSpace::Gray)
GenericImage & Sub(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Mov(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Black(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
size_type LineSize() const noexcept
static int BitsPerSample() noexcept
GenericImage & SetColorSpace(color_space colorSpace, int maxProcessors=0)
GenericImage & Invert(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage AbsoluteDifference(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
void GetColumn(T *buffer, int x, int channel=-1) const
double AvgDev(double center, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
bool IsShared() const noexcept
sample * PixelData(int channel=0)
sample LocateMaximumSampleValue(Point &pmax, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage & CropTo(const Rect &rect, const GenericVector< T > &fillValues)
GenericImage Truncated(T lowerBound, T upperBound, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
GenericImage & ReleaseAlphaChannel(GenericImage &image, int channel)
GenericImage(GenericImage &&image)
TwoSidedEstimate TwoSidedMAD(double center, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
double SumOfSquares(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage & ShiftTo(int x, int y)
GenericImage & Truncate(T lowerBound, T upperBound, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & And(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage Maximum(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
GenericImage & Divide(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
sample MaximumSampleValue(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
sample_vector ColVector(int x, int channel=0) const
GenericImage & Raise(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Mul(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
sample_vector ColumnVector(int x, int channel=-1) const
size_type Count(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage & Normalize(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Nand(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Not(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & ShiftToTopRight(int width, int height)
GenericImage & Div(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
sample MaximumPixelValue(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage & SetRow(const T *buffer, int y, int channel=-1)
double Variance(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage & SetAbsoluteDifference(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
void GetRow(T *buffer, int y, int channel=-1) const
GenericImage & Div(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & ForgetAlphaChannel(int channel)
GenericImage & EnsureUnique()
GenericImage Minimum(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
typename pixel_traits::sample sample
GenericImage(void *handle)
void SetRGBWorkingSpace(const RGBColorSystem &RGBWS) override
GenericImage Filled(const GenericVector< T > &values, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
GenericImage(void *, int width, int height, color_space colorSpace=ColorSpace::Gray)
GenericImage & ImportData(sample **data, int width, int height, int numberOfChannels=1, color_space colorSpace=ColorSpace::Gray)
GenericImage & And(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Mul(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
size_type ChannelSize() const noexcept
sample LocateMaximumSampleValue(int &xmax, int &ymax, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage & Rescale(T lowerBound, T upperBound, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Exchange(GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Blend(const Bitmap &bitmap, const Point &point=Point(int_max), const Rect &rect=Rect(0))
GenericImage & ShiftBy(int dx, int dy)
sample * ScanLine(int y, int channel=0)
GenericImage & ShiftToBottomLeft(int width, int height)
double BiweightMidvariance(double center, double sigma, int k=9, bool reducedLength=false, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage & Fill(const GenericVector< T > &values, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Divide(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Rescale(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Add(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Pow(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & SetMaximum(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
sample LocateMinimumSampleValue(Point &pmin, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage & ShiftBy(int dx, int dy, const GenericVector< T > &fillValues)
const sample * PixelData(int channel=0) const noexcept
uint64 Hash64(int channel=-1, uint64 seed=0) const noexcept
GenericImage(const GenericImage< P1 > &image)
GenericImage & Xor(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & AllocateData(const Rect &rect, int numberOfChannels=1, color_space colorSpace=ColorSpace::Gray)
GenericImage & Min(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Apply(T scalar, image_op op=ImageOp::Mov, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & SetAbsoluteDifference(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
static bool IsFloatSample() noexcept
void GetLuminance(GenericImage< P1 > &Y, const Rect &rect=Rect(0), int maxProcessors=0) const
GenericImage & Invert(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & One(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
sample_vector RowVector(int y, int channel=-1) const
Vector Norms(int maxDegree=2, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage & Move(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Xchg(GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
double StdDev(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage & Subtract(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
Compression::subblock_list Compress(const Compression &compressor, const Rect &rect=Rect(0), int channel=-1, Compression::Performance *perf=nullptr) const
GenericImage & AllocateData(int width, int height, int numberOfChannels=1, color_space colorSpace=ColorSpace::Gray)
sample * PixelAddress(const Point &p, int channel=0)
sample MinimumPixelValue(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage & SetLuminance(const GenericImage< P1 > &Y, const Point &point=Point(int_max), const Rect &rect=Rect(0), int maxProcessors=0)
sample Pixel(const Point &p, int channel=0) const noexcept
GenericImage & ShiftToCenter(int width, int height)
sample LocateMaximumPixelValue(int &xmax, int &ymax, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage & Add(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Write(const String &filePath, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
GenericImage Inverted(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
GenericImage & CropBy(int left, int top, int right, int bottom)
GenericImage & Min(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Transfer(GenericImage &&image)
double OrderStatistic(double k, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage & Truncate(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
sample MinimumSampleValue(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage & ShiftToTopLeft(int width, int height)
GenericImage & Or(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
double MAD(double center, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
friend void Swap(GenericImage &x1, GenericImage &x2) noexcept
GenericImage & CreateAlphaChannels(int n)
GenericImage Normalized(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
GenericImage(File &stream)
GenericImage & Normalize(T lowerBound, T upperBound, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Max(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Pow(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
double Median(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage & DeleteAlphaChannels()
size_type NominalSize() const noexcept
GenericImage Filled(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
GenericImage & Read(const String &filePath)
GenericImage & Binarize(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Dif(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage(const GenericImage &image)
sample LocateMinimumPixelValue(Point &pmin, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage Normalized(T lowerBound, T upperBound, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
GenericImage & Shift(const GenericVector< T > &fillValues)
GenericImage & Xor(T scalar, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
sample LocateMinimumSampleValue(int &xmin, int &ymin, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage & ShiftTo(int x, int y, const GenericVector< T > &fillValues)
double Modulus(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
GenericImage & AddAlphaChannel(sample *data=nullptr)
const sample * PixelAddress(int x, int y, int channel=0) const noexcept
GenericImage & ShiftTo(const Point &p)
GenericImage & Xnor(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
double BendMidvariance(double center, double beta=0.2, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
size_type AlphaSize() const noexcept
GenericImage & Abs(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage Rescaled(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1) const
GenericImage & Zero(const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
GenericImage & Multiply(const GenericImage< P1 > &image, const Point &point=Point(int_max), int channel=-1, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1)
TwoSidedEstimate TwoSidedBiweightMidvariance(double center, const TwoSidedEstimate &sigma, int k=9, bool reducedLength=false, const Rect &rect=Rect(0), int firstChannel=-1, int lastChannel=-1, int maxProcessors=0) const
A generic point in the two-dimensional space.
component x
Abscissa (horizontal, or X-axis coordinate).
component y
Ordinate (vertical, or Y-axis coordinate).
A generic rectangle in the two-dimensional space.
point LeftTop() const noexcept
component x1
Horizontal coordinate of the lower right corner.
component y1
Vertical coordinate of the lower right corner.
bool IsRect() const noexcept
void ResizeTo(T1 w, T1 h) noexcept
component y0
Vertical coordinate of the upper left corner.
component x0
Horizontal coordinate of the upper left corner.
GenericRectangle MovedTo(const pcl::GenericPoint< T1 > &p) const noexcept
GenericRectangle Ordered() const noexcept
component Width() const noexcept
component Height() const noexcept
GenericRectangle Intersection(const GenericRectangle< T1 > &r) const noexcept
Generic vector of arbitrary length.
int Length() const noexcept
const RGBColorSystem & RGBWorkingSpace() const noexcept
color_space ColorSpace() const noexcept
int Width() const noexcept
Rect Bounds() const noexcept
Acts like a union for all types of images in PCL, with optional class-wide ownership of transported i...
32-bit floating point real image.
Manages transparent allocation and deallocation of shared and local pixel data.
32-bit integer point on the plane.
Colorimetrically defined RGB working color space.
32-bit integer rectangle on the plane.
Dynamic array of pointers to objects providing direct iteration and element access by reference.
void Destroy(iterator i, size_type n=1)
void Add(const ReferenceArray &x)
Thread-safe reference counter for copy-on-write data structures.
size_type integer vector.
16-bit unsigned integer image.
32-bit unsigned integer image.
8-bit unsigned integer image.
64-bit floating point real vector.
bool operator==(const Array< T, A > &x1, const Array< T, A > &x2) noexcept
bool operator<(const Array< T, A > &x1, const Array< T, A > &x2) noexcept
const RGBA * ScanLine(int y) const
Complex< T > Sqrt(const Complex< T > &c) noexcept
T Abs(const Complex< T > &c) noexcept
uint64 Hash64(const void *data, size_type size, uint64 seed=0) noexcept
uint32 Hash32(const void *data, size_type size, uint32 seed=0) noexcept
GenericImage< P1 > operator-(const GenericImage< P1 > &image1, const GenericImage< P2 > &image2)
GenericImage< P1 > operator/(const GenericImage< P1 > &image1, const GenericImage< P2 > &image2)
GenericImage< P1 > operator+(const GenericImage< P1 > &image1, const GenericImage< P2 > &image2)
GenericImage< P1 > operator^(const GenericImage< P1 > &image1, const GenericImage< P2 > &image2)
GenericImage< P1 > operator*(const GenericImage< P1 > &image1, const GenericImage< P2 > &image2)
int TruncInt(T x) noexcept
constexpr T Pow2(T x) noexcept
void Swap(GenericPoint< T > &p1, GenericPoint< T > &p2) noexcept
unsigned long long uint64
RI Select(RI i, RI j, distance_type k)
double Qn(T *__restrict__ x, T *__restrict__ xn)
double BendMidvariance(const T *__restrict__ x, const T *__restrict__ xn, double center, double beta=0.2)
double Variance(const T *__restrict__ i, const T *__restrict__ j, double center) noexcept
double Median(const T *__restrict__ i, const T *__restrict__ j, double 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.