PCL
AbstractImage.h
Go to the documentation of this file.
1 // ____ ______ __
2 // / __ \ / ____// /
3 // / /_/ // / / /
4 // / ____// /___ / /___ PixInsight Class Library
5 // /_/ \____//_____/ PCL 2.7.0
6 // ----------------------------------------------------------------------------
7 // pcl/AbstractImage.h - Released 2024-06-18T15:48:54Z
8 // ----------------------------------------------------------------------------
9 // This file is part of the PixInsight Class Library (PCL).
10 // PCL is a multiplatform C++ framework for development of PixInsight modules.
11 //
12 // Copyright (c) 2003-2024 Pleiades Astrophoto S.L. All Rights Reserved.
13 //
14 // Redistribution and use in both source and binary forms, with or without
15 // modification, is permitted provided that the following conditions are met:
16 //
17 // 1. All redistributions of source code must retain the above copyright
18 // notice, this list of conditions and the following disclaimer.
19 //
20 // 2. All redistributions in binary form must reproduce the above copyright
21 // notice, this list of conditions and the following disclaimer in the
22 // documentation and/or other materials provided with the distribution.
23 //
24 // 3. Neither the names "PixInsight" and "Pleiades Astrophoto", nor the names
25 // of their contributors, may be used to endorse or promote products derived
26 // from this software without specific prior written permission. For written
27 // permission, please contact info@pixinsight.com.
28 //
29 // 4. All products derived from this software, in any form whatsoever, must
30 // reproduce the following acknowledgment in the end-user documentation
31 // and/or other materials provided with the product:
32 //
33 // "This product is based on software from the PixInsight project, developed
34 // by Pleiades Astrophoto and its contributors (https://pixinsight.com/)."
35 //
36 // Alternatively, if that is where third-party acknowledgments normally
37 // appear, this acknowledgment must be reproduced in the product itself.
38 //
39 // THIS SOFTWARE IS PROVIDED BY PLEIADES ASTROPHOTO AND ITS CONTRIBUTORS
40 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
41 // TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PLEIADES ASTROPHOTO OR ITS
43 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
44 // EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, BUSINESS
45 // INTERRUPTION; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; AND LOSS OF USE,
46 // DATA OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
47 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
49 // POSSIBILITY OF SUCH DAMAGE.
50 // ----------------------------------------------------------------------------
51 
52 #ifndef __PCL_AbstractImage_h
53 #define __PCL_AbstractImage_h
54 
56 
57 #include <pcl/Defs.h>
58 
59 #include <pcl/Array.h>
60 #include <pcl/ImageColor.h>
61 #include <pcl/ImageGeometry.h>
62 #include <pcl/ImageSelections.h>
63 #include <pcl/Mutex.h>
64 #include <pcl/ParallelProcess.h>
65 #include <pcl/ReferenceArray.h>
66 #include <pcl/StatusMonitor.h>
67 #include <pcl/Thread.h>
68 
69 #ifdef __PCL_BUILDING_PIXINSIGHT_APPLICATION
70 namespace pi
71 {
72 class SharedImage;
73 }
74 #endif
75 
76 namespace pcl
77 {
78 
79 // ----------------------------------------------------------------------------
80 
81 #define m_width m_geometry->width
82 #define m_height m_geometry->height
83 #define m_numberOfChannels m_geometry->numberOfChannels
84 
85 #define m_colorSpace m_color->colorSpace
86 #define m_RGBWS m_color->RGBWS
87 
88 // ----------------------------------------------------------------------------
89 
118 class PCL_CLASS AbstractImage : public ImageGeometry,
119  public ImageColor,
120  public ParallelProcess
121 {
122 public:
123 
128 
134  using color_space = ImageColor::color_space;
135 
139  ~AbstractImage() override
140  {
141  }
142 
147  int NumberOfNominalChannels() const noexcept
148  {
149  return ColorSpace::NumberOfNominalChannels( m_colorSpace );
150  }
151 
157  {
158  return NumberOfPixels() * NumberOfNominalChannels();
159  }
160 
167  bool HasAlphaChannels() const noexcept
168  {
169  PCL_PRECONDITION( NumberOfChannels() != 0 )
170  return NumberOfChannels() > NumberOfNominalChannels();
171  }
172 
176  int NumberOfAlphaChannels() const noexcept
177  {
178  PCL_PRECONDITION( NumberOfChannels() != 0 )
179  return NumberOfChannels() - NumberOfNominalChannels();
180  }
181 
188  {
189  return NumberOfPixels() * NumberOfAlphaChannels();
190  }
191 
192  // -------------------------------------------------------------------------
193 
200  void SelectChannel( int c ) const noexcept
201  {
202  PCL_PRECONDITION( 0 <= c && c < m_numberOfChannels )
203  m_selected.channel = m_selected.lastChannel = c;
204  ValidateChannelRange();
205  }
206 
215  int SelectedChannel() const noexcept
216  {
217  return m_selected.channel;
218  }
219 
227  void SelectChannelRange( int c0, int c1 ) const noexcept
228  {
229  PCL_PRECONDITION( 0 <= c0 && c0 < m_numberOfChannels )
230  PCL_PRECONDITION( 0 <= c1 && c1 < m_numberOfChannels )
231  m_selected.channel = c0;
232  m_selected.lastChannel = c1;
233  ValidateChannelRange();
234  }
235 
240  void SelectNominalChannels() const noexcept
241  {
242  m_selected.channel = 0;
243  m_selected.lastChannel = NumberOfNominalChannels()-1;
244  ValidateChannelRange();
245  }
246 
254  void SelectAlphaChannels() const noexcept
255  {
256  m_selected.channel = NumberOfNominalChannels();
257  m_selected.lastChannel = m_numberOfChannels-1;
258  ValidateChannelRange();
259  }
260 
265  void ResetChannelRange() const noexcept
266  {
267  m_selected.channel = 0;
268  m_selected.lastChannel = pcl::Max( 0, m_numberOfChannels-1 );
269  }
270 
274  int NumberOfSelectedChannels() const noexcept
275  {
276  return 1 + m_selected.lastChannel - m_selected.channel;
277  }
278 
282  int FirstSelectedChannel() const noexcept
283  {
284  return m_selected.channel;
285  }
286 
290  int LastSelectedChannel() const noexcept
291  {
292  return m_selected.lastChannel;
293  }
294 
302  void GetSelectedChannelRange( int& c0, int& c1 ) const noexcept
303  {
304  c0 = m_selected.channel;
305  c1 = m_selected.lastChannel;
306  }
307 
314  void SelectPoint( int x, int y ) const noexcept
315  {
316  m_selected.point.MoveTo( x, y );
317  }
318 
322  void SelectPoint( const Point& p ) const noexcept
323  {
324  m_selected.point = p;
325  }
326 
330  void ResetPoint() const noexcept
331  {
332  m_selected.point = 0;
333  }
334 
338  const Point& SelectedPoint() const noexcept
339  {
340  return m_selected.point;
341  }
342 
356  void SelectRectangle( int x0, int y0, int x1, int y1 ) const noexcept
357  {
358  m_selected.rectangle.Set( x0, y0, x1, y1 );
359  Clip( m_selected.rectangle );
360  }
361 
370  void SelectRectangle( const Point& p0, const Point& p1 ) const noexcept
371  {
372  SelectRectangle( p0.x, p0.y, p1.x, p1.y );
373  }
374 
379  void SelectRectangle( const Rect& r ) const noexcept
380  {
381  SelectRectangle( r.x0, r.y0, r.x1, r.y1 );
382  }
383 
387  void ResetSelection() const noexcept
388  {
389  m_selected.rectangle.Set( 0, 0, m_width, m_height );
390  }
391 
395  bool IsEmptySelection() const noexcept
396  {
397  return m_selected.rectangle.IsPointOrLine();
398  }
399 
404  bool IsFullSelection() const noexcept
405  {
406  return m_selected.rectangle.x0 <= 0 &&
407  m_selected.rectangle.y0 <= 0 &&
408  m_selected.rectangle.x1 >= m_width &&
409  m_selected.rectangle.y1 >= m_height;
410  }
411 
415  const Rect& SelectedRectangle() const noexcept
416  {
417  return m_selected.rectangle;
418  }
419 
428  bool IsCompletelySelected() const noexcept
429  {
430  return m_selected.channel == 0 &&
431  m_selected.lastChannel >= m_numberOfChannels-1 &&
432  m_selected.rectangle.x0 <= 0 &&
433  m_selected.rectangle.y0 <= 0 &&
434  m_selected.rectangle.x1 >= m_width &&
435  m_selected.rectangle.y1 >= m_height;
436  }
437 
443  {
444  return size_type( m_selected.rectangle.Width() ) * size_type( m_selected.rectangle.Height() );
445  // ### N.B. Rect::Area() cannot be used here because it performs a
446  // *signed* multiplication of two 32-bit signed integers.
447  //return m_selected.rectangle.Area();
448  }
449 
456  {
457  return NumberOfSelectedPixels()*size_type( NumberOfSelectedChannels() );
458  }
459 
482  bool IsRangeClippingEnabled() const noexcept
483  {
484  return m_selected.clippedLow || m_selected.clippedHigh;
485  }
486 
495  bool IsLowRangeClippingEnabled() const noexcept
496  {
497  return m_selected.clippedLow;
498  }
499 
508  bool IsHighRangeClippingEnabled() const noexcept
509  {
510  return m_selected.clippedHigh;
511  }
512 
518  void EnableRangeClipping( bool enableLow = true, bool enableHigh = true ) const noexcept
519  {
520  m_selected.clippedLow = enableLow;
521  m_selected.clippedHigh = enableHigh;
522  }
523 
529  void DisableRangeClipping( bool disableLow = true, bool disableHigh = true ) const noexcept
530  {
531  m_selected.clippedLow = !disableLow;
532  m_selected.clippedHigh = !disableHigh;
533  }
534 
540  double RangeClipLow() const noexcept
541  {
542  return m_selected.clipLow;
543  }
544 
550  double RangeClipHigh() const noexcept
551  {
552  return m_selected.clipHigh;
553  }
554 
560  void SetRangeClipLow( double clipLow ) const noexcept
561  {
562  m_selected.clipLow = clipLow;
563  if ( m_selected.clipHigh < m_selected.clipLow )
564  pcl::Swap( m_selected.clipLow, m_selected.clipHigh );
565  }
566 
572  void SetRangeClipHigh( double clipHigh ) const noexcept
573  {
574  m_selected.clipHigh = clipHigh;
575  if ( m_selected.clipHigh < m_selected.clipLow )
576  pcl::Swap( m_selected.clipLow, m_selected.clipHigh );
577  }
578 
585  void SetRangeClipping( double clipLow, double clipHigh ) const noexcept
586  {
587  if ( clipHigh < clipLow )
588  pcl::Swap( clipLow, clipHigh );
589  m_selected.clipLow = clipLow;
590  m_selected.clipHigh = clipHigh;
591  m_selected.clippedLow = m_selected.clippedHigh = true;
592  }
593 
601  void ResetRangeClipping() const noexcept
602  {
603  m_selected.clipLow = 0;
604  m_selected.clipHigh = 1;
605  m_selected.clippedLow = m_selected.clippedHigh = false;
606  }
607 
626  void ResetSelections() const noexcept
627  {
628  ResetChannelRange();
629  ResetPoint();
630  ResetSelection();
631  ResetRangeClipping();
632  }
633 
637  ImageSelections& Selections() const noexcept
638  {
639  return m_selected;
640  }
641 
646  void PushSelections() const
647  {
648  m_savedSelections.Append( m_selected );
649  }
650 
659  void PopSelections() const
660  {
661  if ( CanPopSelections() )
662  {
663  selection_stack::iterator i = m_savedSelections.ReverseBegin();
664  m_selected = *i;
665  m_savedSelections.Remove( i );
666  }
667  }
668 
674  bool CanPopSelections() const noexcept
675  {
676  return !m_savedSelections.IsEmpty();
677  }
678 
691  bool ParseRect( Rect& rect ) const noexcept
692  {
693  if ( !rect.IsRect() )
694  {
695  rect = m_selected.rectangle;
696  if ( !rect.IsRect() )
697  return false;
698  }
699  if ( !Clip( rect ) )
700  return false;
701  return true;
702  }
703 
714  bool ParseChannel( int& channel ) const noexcept
715  {
716  if ( channel < 0 )
717  {
718  channel = m_selected.channel;
719  if ( channel < 0 )
720  return false;
721  }
722  if ( channel >= m_numberOfChannels )
723  return false;
724 
725  return true;
726  }
727 
752  bool ParseSelection( Rect& rect, int& firstChannel, int& lastChannel ) const noexcept
753  {
754  if ( !ParseRect( rect ) || !ParseChannel( firstChannel ) )
755  return false;
756 
757  if ( lastChannel < 0 )
758  {
759  lastChannel = m_selected.lastChannel;
760  if ( lastChannel < 0 )
761  return false;
762  }
763  if ( lastChannel >= m_numberOfChannels )
764  return false;
765 
766  if ( lastChannel < firstChannel )
767  pcl::Swap( firstChannel, lastChannel );
768 
769  return true;
770  }
771 
789  bool ParseSelection( Rect& rect, int& channel ) const noexcept
790  {
791  return ParseRect( rect ) && ParseChannel( channel );
792  }
793 
794  // -------------------------------------------------------------------------
795 
800  StatusMonitor& Status() const noexcept
801  {
802  return m_status;
803  }
804 
810  {
811  return m_status.Callback();
812  }
813 
820  {
821  return StatusCallback();
822  }
823 
828  void SetStatusCallback( pcl::StatusCallback* callback ) const noexcept
829  {
830  m_status.SetCallback( callback );
831  }
832 
859  int NumberOfThreads( size_type count, int maxProcessors = 0, size_type overheadLimit = 16u ) const noexcept
860  {
861  return m_parallel ? pcl::Min( (maxProcessors > 0) ? maxProcessors : m_maxProcessors,
862  Thread::NumberOfThreads( count, overheadLimit ) ) : 1;
863  }
864 
897  int NumberOfThreadsForRows( int rowCount = 0, int rowWidth = 0, int maxProcessors = 0, size_type overheadLimitPx = 1024u ) const noexcept
898  {
899  return NumberOfThreads( (rowCount > 0) ? rowCount : Height(),
900  maxProcessors,
901  pcl::Max( size_type( 1 ), size_type( overheadLimitPx/((rowWidth > 0) ? rowWidth : Width()) ) ) );
902  }
903 
944  Array<size_type> OptimalThreadRows( int rowCount = 0, int rowWidth = 0, int maxProcessors = 0, size_type overheadLimitPx = 1024u ) const noexcept
945  {
946  return Thread::OptimalThreadLoads( (rowCount > 0) ? rowCount : Height(),
947  pcl::Max( size_type( 1 ), size_type( overheadLimitPx/((rowWidth > 0) ? rowWidth : Width()) ) ),
948  m_parallel ? ((maxProcessors > 0) ? maxProcessors : m_maxProcessors) : 1 );
949  }
950 
951  // -------------------------------------------------------------------------
952 
964  struct ThreadData
965  {
967  mutable Mutex mutex;
968  mutable size_type count = 0;
969  size_type total = 0;
970  size_type numThreads = 0;
971 
975  ThreadData() = default;
976 
986  ThreadData( const AbstractImage& image, size_type N )
987  : status( image.Status() )
988  , total( N )
989  {
990  }
991 
1000  ThreadData( const StatusMonitor& a_status, size_type N )
1001  : status( a_status )
1002  , total( N )
1003  {
1004  }
1005  };
1006 
1071  template <class thread>
1072  static void RunThreads( ReferenceArray<thread>& threads, ThreadData& data, bool useAffinity = true )
1073  {
1074  if ( threads.IsEmpty() )
1075  return;
1076 
1077  data.numThreads = threads.Length();
1078  if ( data.numThreads == 1 )
1079  {
1080  try
1081  {
1082  threads[0].Run();
1083  return;
1084  }
1085  catch ( ... )
1086  {
1087  threads.Destroy();
1088  throw;
1089  }
1090  }
1091 
1092  if ( useAffinity )
1093  if ( !Thread::IsRootThread() )
1094  useAffinity = false;
1095 
1096  {
1097  int n = 0;
1098  for ( thread& t : threads )
1099  t.Start( ThreadPriority::DefaultMax, useAffinity ? n++ : -1 );
1100  }
1101 
1102  uint32 waitTime = StatusMonitor::RefreshRate() >> 1;
1103  waitTime += waitTime >> 2; // waitTime = 0.625 * StatusMonitor::RefreshRate()
1104 
1105  for ( size_type lastCount = 0; ; )
1106  {
1107  for ( typename ReferenceArray<thread>::iterator i = threads.Begin(); ; )
1108  {
1109  if ( !i->Wait( waitTime ) )
1110  break;
1111 
1112  if ( ++i == threads.End() )
1113  {
1114  if ( data.total > 0 )
1115  data.status += data.total - lastCount;
1116  return;
1117  }
1118  }
1119 
1120  if ( data.mutex.TryLock() )
1121  {
1122  try
1123  {
1124  if ( data.total > 0 )
1125  {
1126  data.status += data.count - lastCount;
1127  lastCount = data.count;
1128  }
1129  else
1130  ++data.status;
1131 
1132  data.mutex.Unlock();
1133  }
1134  catch ( ... )
1135  {
1136  data.mutex.Unlock();
1137  for ( thread& t : threads )
1138  t.Abort();
1139  for ( thread& t : threads )
1140  t.Wait();
1141  threads.Destroy();
1142  throw ProcessAborted();
1143  }
1144  }
1145  }
1146  }
1147 
1148 protected:
1149 
1150  mutable ImageSelections m_selected;
1151  mutable selection_stack m_savedSelections;
1152  mutable StatusMonitor m_status;
1153 
1154  AbstractImage() = default;
1155 
1156  AbstractImage( const AbstractImage& ) = default;
1157 
1158  AbstractImage& operator =( const AbstractImage& ) = default;
1159 
1160  void Swap( AbstractImage& image ) noexcept
1161  {
1162  ImageGeometry::Swap( image );
1163  ImageColor::Swap( image );
1164  ParallelProcess::Swap( image );
1165  pcl::Swap( m_selected, image.m_selected );
1166  pcl::Swap( m_savedSelections, image.m_savedSelections );
1167  pcl::Swap( m_status, image.m_status );
1168  }
1169 
1170  void ValidateChannelRange() const noexcept
1171  {
1172  if ( m_numberOfChannels > 0 )
1173  {
1174  if ( m_selected.channel < 0 )
1175  m_selected.channel = 0;
1176  else if ( m_selected.channel >= m_numberOfChannels )
1177  m_selected.channel = m_numberOfChannels-1;
1178 
1179  if ( m_selected.lastChannel < 0 )
1180  m_selected.lastChannel = 0;
1181  else if ( m_selected.lastChannel >= m_numberOfChannels )
1182  m_selected.lastChannel = m_numberOfChannels-1;
1183 
1184  if ( m_selected.lastChannel < m_selected.channel )
1185  pcl::Swap( m_selected.channel, m_selected.lastChannel );
1186  }
1187  else
1188  {
1189  m_selected.channel = m_selected.lastChannel = 0;
1190  }
1191  }
1192 
1193 #ifdef __PCL_BUILDING_PIXINSIGHT_APPLICATION
1194  friend class pi::SharedImage;
1195 #endif
1196 };
1197 
1198 // ----------------------------------------------------------------------------
1199 
1200 #undef m_width
1201 #undef m_height
1202 #undef m_numberOfChannels
1203 #undef m_colorSpace
1204 #undef m_RGBWS
1205 
1206 // ----------------------------------------------------------------------------
1207 
1226 #define INIT_THREAD_MONITOR() \
1227  size_type ___n___ = 0, ___n1___ = 0;
1228 
1314 #define UPDATE_THREAD_MONITOR( N ) \
1315  if ( ++___n1___ == (N) ) \
1316  { \
1317  if ( this->m_data.numThreads > 1 ) \
1318  { \
1319  if ( this->TryIsAborted() ) \
1320  return; \
1321  ___n___ += (N); \
1322  if ( this->m_data.total > 0 ) \
1323  if ( this->m_data.mutex.TryLock() ) \
1324  { \
1325  this->m_data.count += ___n___; \
1326  this->m_data.mutex.Unlock(); \
1327  ___n___ = 0; \
1328  } \
1329  } \
1330  else \
1331  { \
1332  if ( this->m_data.total > 0 ) \
1333  this->m_data.status += (N); \
1334  else \
1335  ++this->m_data.status; \
1336  } \
1337  ___n1___ = 0; \
1338  }
1339 
1395 #define UPDATE_THREAD_MONITOR_CHUNK( N, chunkSize ) \
1396  if ( (___n1___ += (chunkSize)) == (N) ) \
1397  { \
1398  if ( this->m_data.numThreads > 1 ) \
1399  { \
1400  if ( this->TryIsAborted() ) \
1401  return; \
1402  ___n___ += (N); \
1403  if ( this->m_data.total > 0 ) \
1404  if ( this->m_data.mutex.TryLock() ) \
1405  { \
1406  this->m_data.count += ___n___; \
1407  this->m_data.mutex.Unlock(); \
1408  ___n___ = 0; \
1409  } \
1410  } \
1411  else \
1412  { \
1413  if ( this->m_data.total > 0 ) \
1414  this->m_data.status += (N); \
1415  else \
1416  ++this->m_data.status; \
1417  } \
1418  ___n1___ = 0; \
1419  }
1420 
1421 // ----------------------------------------------------------------------------
1422 
1423 } // pcl
1424 
1425 #endif // __PCL_AbstractImage_h
1426 
1427 // ----------------------------------------------------------------------------
1428 // EOF pcl/AbstractImage.h - Released 2024-06-18T15:48:54Z
Base class of all two-dimensional images in PCL.
void ResetPoint() const noexcept
int NumberOfThreadsForRows(int rowCount=0, int rowWidth=0, int maxProcessors=0, size_type overheadLimitPx=1024u) const noexcept
void SelectAlphaChannels() const noexcept
bool IsLowRangeClippingEnabled() const noexcept
bool IsHighRangeClippingEnabled() const noexcept
void SelectChannelRange(int c0, int c1) const noexcept
void SetRangeClipLow(double clipLow) const noexcept
void GetSelectedChannelRange(int &c0, int &c1) const noexcept
bool CanPopSelections() const noexcept
void SelectRectangle(int x0, int y0, int x1, int y1) const noexcept
size_type NumberOfSelectedPixels() const noexcept
int NumberOfAlphaChannels() const noexcept
void EnableRangeClipping(bool enableLow=true, bool enableHigh=true) const noexcept
void ResetSelection() const noexcept
void SelectNominalChannels() const noexcept
int NumberOfNominalChannels() const noexcept
int LastSelectedChannel() const noexcept
double RangeClipHigh() const noexcept
~AbstractImage() override
void ResetRangeClipping() const noexcept
static void RunThreads(ReferenceArray< thread > &threads, ThreadData &data, bool useAffinity=true)
int NumberOfSelectedChannels() const noexcept
void SelectChannel(int c) const noexcept
bool IsCompletelySelected() const noexcept
int SelectedChannel() const noexcept
Array< size_type > OptimalThreadRows(int rowCount=0, int rowWidth=0, int maxProcessors=0, size_type overheadLimitPx=1024u) const noexcept
void SetRangeClipHigh(double clipHigh) const noexcept
bool ParseRect(Rect &rect) const noexcept
void SelectRectangle(const Point &p0, const Point &p1) const noexcept
size_type NumberOfNominalSamples() const noexcept
bool ParseChannel(int &channel) const noexcept
void PushSelections() const
int FirstSelectedChannel() const noexcept
void ResetSelections() const noexcept
bool IsRangeClippingEnabled() const noexcept
void SetStatusCallback(pcl::StatusCallback *callback) const noexcept
ImageSelections & Selections() const noexcept
pcl::StatusCallback * GetStatusCallback() const noexcept
const Rect & SelectedRectangle() const noexcept
double RangeClipLow() const noexcept
void PopSelections() const
pcl::StatusCallback * StatusCallback() const noexcept
void SelectRectangle(const Rect &r) const noexcept
StatusMonitor & Status() const noexcept
bool HasAlphaChannels() const noexcept
void SelectPoint(int x, int y) const noexcept
bool ParseSelection(Rect &rect, int &firstChannel, int &lastChannel) const noexcept
bool IsEmptySelection() const noexcept
void SetRangeClipping(double clipLow, double clipHigh) const noexcept
void SelectPoint(const Point &p) const noexcept
const Point & SelectedPoint() const noexcept
bool ParseSelection(Rect &rect, int &channel) const noexcept
size_type NumberOfAlphaSamples() const noexcept
void DisableRangeClipping(bool disableLow=true, bool disableHigh=true) const noexcept
size_type NumberOfSelectedSamples() const noexcept
int NumberOfThreads(size_type count, int maxProcessors=0, size_type overheadLimit=16u) const noexcept
bool IsFullSelection() const noexcept
void ResetChannelRange() const noexcept
A generic point in the two-dimensional space.
Definition: Point.h:100
A generic rectangle in the two-dimensional space.
Definition: Rectangle.h:314
Implements color space properties of images.
Definition: ImageColor.h:97
ColorSpace::value_type color_space
Definition: ImageColor.h:105
Implements geometric properties of two-dimensional images.
Definition: ImageGeometry.h:84
Adaptive mutual exclusion lock variable.
Definition: Mutex.h:209
void Unlock()
Definition: Mutex.h:337
bool TryLock()
Definition: Mutex.h:389
A process using multiple concurrent execution threads.
void Swap(ParallelProcess &process) noexcept
An exception class signaling the interruption of a process.
Mutable ReferenceArray iterator.
Dynamic array of pointers to objects providing direct iteration and element access by reference.
size_type Length() const
void Destroy(iterator i, size_type n=1)
bool IsEmpty() const
Provides status monitoring callback functions.
Definition: StatusMonitor.h:98
An asynchronous status monitoring system.
static unsigned RefreshRate()
static int NumberOfThreads(size_type count, size_type overheadLimit=1u)
static bool IsRootThread()
static Array< size_type > OptimalThreadLoads(size_type count, size_type overheadLimit=1u, int maxThreads=PCL_MAX_PROCESSORS)
void Swap(GenericPoint< T > &p1, GenericPoint< T > &p2) noexcept
Definition: Point.h:1459
unsigned int uint32
Definition: Defs.h:666
size_t size_type
Definition: Defs.h:609
constexpr const T & Min(const T &a, const T &b) noexcept
Definition: Utility.h:90
constexpr const T & Max(const T &a, const T &b) noexcept
Definition: Utility.h:119
int NumberOfNominalChannels(int colorSpace)
Definition: ColorSpace.h:102
PCL root namespace.
Definition: AbstractImage.h:77
Thread synchronization data for status monitoring of parallel image processing tasks.
ThreadData(const AbstractImage &image, size_type N)
size_type count
current monitoring count.
Mutex mutex
Mutual exclusion for synchronized thread access.
StatusMonitor status
Status monitoring object.
size_type total
Total monitoring count.
ThreadData(const StatusMonitor &a_status, size_type N)
size_type numThreads
Number of concurrent threads being executed (set by RunThreads()).
A structure used to store rectangular image selections, channel ranges, anchor points,...
int lastChannel
Last selected channel.
int channel
First selected channel.