template <class P> static
   void Apply( GenericImage<P>& image, const HistogramTransformation& H )
   {
      if ( image.IsEmptySelection() )
         return;

      image.SetUnique();

      Rect r = image.SelectedRectangle();
      int h = r.Height();

      int numberOfThreads = H.IsParallelProcessingEnabled() ? Min( H.MaxProcessors(), pcl::Thread::NumberOfThreads( h, 1 ) ) : 1;
      int rowsPerThread = h/numberOfThreads;

      H.UpdateFlags();

      size_type N = image.NumberOfSelectedSamples();
      if ( image.Status().IsInitializationEnabled() )
         image.Status().Initialize( "Histogram transformation", N );

      ThreadData<P> data( image, H, N );

      PArray<Thread<P> > threads;
      for ( int i = 0, j = 1; i < numberOfThreads; ++i, ++j )
         threads.Add( new Thread<P>( data, i*rowsPerThread, (j < numberOfThreads) ? j*rowsPerThread : h ) );

      AbstractImage::RunThreads( threads, data );
      threads.Destroy();

      image.Status() = data.status;
   }
void HistogramTransformation::Make24BitLUT( uint16* lut ) const
{
   if ( lut == 0 )
      return;

   UpdateFlags();

   int numberOfThreads = m_parallel ? Min( int( m_maxProcessors ), Thread::NumberOfThreads( uint24_max+1, 256 ) ) : 1;
   int itemsPerThread = (uint24_max + 1)/numberOfThreads;
   bool useAffinity = m_parallel && Thread::IsRootThread();

   PArray<LUT2416Thread> threads;
   for ( int i = 0, j = 1; i < numberOfThreads; ++i, ++j )
      threads.Add( new LUT2416Thread( lut, *this,
                                      i*itemsPerThread, (j < numberOfThreads) ? j*itemsPerThread : uint24_max+1 ) );
   if ( numberOfThreads > 1 )
   {
      for ( int i = 0; i < numberOfThreads; ++i )
         threads[i].Start( ThreadPriority::DefaultMax, useAffinity ? i : -1 );
      for ( int i = 0; i < numberOfThreads; ++i )
         threads[i].Wait();
   }
   else
      threads[0].Run();
}