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

      image.EnsureUnique();

      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;

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

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

      ReferenceArray<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;
   }
   template <class P, class S> static
   void Apply( GenericImage<P>& image, S*,
               const ICCProfileTransformation& T,
               ICCProfileTransformation::transformation_handle transformation )
   {
      if ( image.IsEmptySelection() || T.Profiles().IsEmpty() )
         return;

      if ( image.ColorSpace() != ColorSpace::RGB && image.ColorSpace() != ColorSpace::Gray )
         throw Error( String().Format( "Unsupported color space %X in ICC color transformation.", image.ColorSpace() ) );

      image.EnsureUnique();

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

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

      size_type N = image.NumberOfSelectedPixels();
      if ( image.Status().IsInitializationEnabled() )
         image.Status().Initialize( "In-place ICC color profile transformation", N );

      ThreadData<P> data( image, T, transformation, N );

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

      AbstractImage::RunThreads( threads, data );

      threads.Destroy();

      image.Status() = data.status;
   }
Beispiel #3
0
   template <class P> inline
   static void Apply( GenericImage<P>& image, const IntegerResample& Z )
   {
      int width = image.Width();
      int w0 = width;
      int height = image.Height();
      int h0 = height;

      Z.GetNewSizes( width, height );

      if ( width == w0 && height == h0 )
         return;

      if ( width == 0 || height == 0 )
      {
         image.FreeData();
         return;
      }

      image.EnsureUnique();

      typename P::sample* f = 0;
      typename P::sample** f0 = 0;

      int n = image.NumberOfChannels();
      size_type N = image.NumberOfPixels();
      typename GenericImage<P>::color_space cs0 = image.ColorSpace();

      StatusMonitor status = image.Status();

      int z = pcl::Abs( Z.ZoomFactor() );
      int z2 = z*z;
      int n2 = z2 >> 1;

      try
      {
         if ( status.IsInitializationEnabled() )
         {
            String info = (Z.ZoomFactor() > 0) ? "Upsampling" : "Downsampling";

            info.AppendFormat( " %d:%d, %dx%d",
               (Z.ZoomFactor() > 0) ? z : 1, (Z.ZoomFactor() > 0) ? 1 : z, width, height );

            if ( Z.ZoomFactor() < 0 )
            {
               info += ", ";
               switch ( Z.DownsampleMode() )
               {
               default:
               case IntegerDownsampleMode::Average: info += "average"; break;
               case IntegerDownsampleMode::Median:  info += "median"; break;
               case IntegerDownsampleMode::Maximum: info += "maximum"; break;
               case IntegerDownsampleMode::Minimum: info += "minimum"; break;
               }
            }

            status.Initialize( info, n*N );
         }

         GenericVector<typename P::sample> fm;
         if ( Z.ZoomFactor() < 0 && Z.DownsampleMode() == IntegerDownsampleMode::Median )
            fm = GenericVector<typename P::sample>( z2 );

         f0 = image.ReleaseData();

         for ( int c = 0; c < n; ++c, status += N )
         {
            f = image.Allocator().AllocatePixels( width, height );

            if ( Z.ZoomFactor() > 0 )
            {
               const typename P::sample* f0c = f0[c];

               for ( int y = 0; y < h0; ++y )
               {
                  int yz = y*z;

                  for ( int x = 0; x < w0; ++x )
                  {
                     int xz = x*z;
                     typename P::sample v = *f0c++;

                     for ( int i = 0; i < z; ++i )
                     {
                        typename P::sample* fi = f + (size_type( yz + i )*width + xz);

                        for ( int j = 0; j < z; ++j )
                           *fi++ = v;
                     }
                  }
               }
            }
            else
            {
               typename P::sample* fz = f;

               for ( int y = 0; y < height; ++y )
               {
                  const typename P::sample* fy = f0[c] + size_type( y )*z*w0;

                  for ( int x = 0; x < width; ++x )
                  {
                     const typename P::sample* fyx = fy + x*z;

                     switch ( Z.DownsampleMode() )
                     {
                     default:
                     case IntegerDownsampleMode::Average:
                        {
                           double s = 0;
                           for ( int i = 0; i < z; ++i, fyx += w0 )
                              for ( int j = 0; j < z; ++j )
                                 s += fyx[j];
                           *fz++ = typename P::sample( P::IsFloatSample() ? s/z2 : Round( s/z2 ) );
                        }
                        break;

                     case IntegerDownsampleMode::Median:
                        {
                           typename P::sample* fmi = *fm;
                           for ( int i = 0; i < z; ++i, fyx += w0 )
                              for ( int j = 0; j < z; ++j )
                                 *fmi++ = fyx[j];

                           *fz++ = (z & 1) ?
                                 *Select( *fm, fm.At( z2 ), n2 ) :
                                 P::FloatToSample( 0.5*(double( *Select( *fm, fm.At( z2 ), n2   ) ) +
                                                        double( *Select( *fm, fm.At( z2 ), n2-1 ) )) );
                        }
                        break;

                     case IntegerDownsampleMode::Maximum:
                        {
                           *fz = P::MinSampleValue();
                           for ( int i = 0; i < z; ++i, fyx += w0 )
                              for ( int j = 0; j < z; ++j )
                                 if ( fyx[j] > *fz )
                                    *fz = fyx[j];
                           ++fz;
                        }
                        break;

                     case IntegerDownsampleMode::Minimum:
                        {
                           *fz = P::MaxSampleValue();
                           for ( int i = 0; i < z; ++i, fyx += w0 )
                              for ( int j = 0; j < z; ++j )
                                 if ( fyx[j] < *fz )
                                    *fz = fyx[j];
                           ++fz;
                        }
                        break;
                     }
                  }
               }
            }

            image.Allocator().Deallocate( f0[c] );
            f0[c] = f;
            f = 0;
         }

         image.ImportData( f0, width, height, n, cs0 ).Status() = status;
      }
      catch ( ... )
      {
         if ( f != 0 )
            image.Allocator().Deallocate( f );
         if ( f0 != 0 )
         {
            for ( int c = 0; c < n; ++c )
               if ( f0[c] != 0 )
                  image.Allocator().Deallocate( f0[c] );
            image.Allocator().Deallocate( f0 );
         }
         image.FreeData();
         throw;
      }
   }
   template <class P> static
   void Apply( GenericImage<P>& image, const MorphologicalTransformation& transformation )
   {
      if ( image.IsEmptySelection() )
         return;

      image.EnsureUnique();

      int n = transformation.OverlappingDistance();
      if ( n > image.Height() || n > image.Width() )
      {
         image.Zero();
         return;
      }

      /*
       * Dilation requires a reflected structure. We'll unreflect it once the
       * transformation has finished.
       */
      bool didReflect = false;
      if ( transformation.Operator().IsDilation() != transformation.Structure().IsReflected() )
      {
         const_cast<StructuringElement&>( transformation.Structure() ).Reflect();
         didReflect = true;
      }

      int numberOfRows = image.SelectedRectangle().Height();
      int numberOfThreads = transformation.IsParallelProcessingEnabled() ?
               Min( transformation.MaxProcessors(), pcl::Thread::NumberOfThreads( numberOfRows, n ) ) : 1;
      int rowsPerThread = numberOfRows/numberOfThreads;

      size_type N = image.NumberOfSelectedSamples();
      if ( image.Status().IsInitializationEnabled() )
         image.Status().Initialize( "Morphological transformation, " + transformation.Operator().Description(), N );

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

      ReferenceArray<Thread<P> > threads;
      for ( int i = 0, j = 1, y0 = image.SelectedRectangle().y0; i < numberOfThreads; ++i, ++j )
         threads.Add( new Thread<P>( data,
                                     y0 + i*rowsPerThread,
                                     y0 + ((j < numberOfThreads) ? j*rowsPerThread : numberOfRows),
                                     i > 0,
                                     j < numberOfThreads ) );
      try
      {
         AbstractImage::RunThreads( threads, data );
         if ( didReflect )
            const_cast<StructuringElement&>( transformation.Structure() ).Reflect();
      }
      catch ( ... )
      {
         if ( didReflect )
            const_cast<StructuringElement&>( transformation.Structure() ).Reflect();
         throw;
      }

      image.SetStatusCallback( nullptr );

      int c0 = image.SelectedChannel();
      Point p0 = image.SelectedRectangle().LeftTop();

      for ( int i = 0, j = 1; i < numberOfThreads; ++i, ++j )
      {
         if ( i > 0 )
            image.Mov( threads[i].UpperOverlappingRegion(),
                       Point( p0.x, p0.y + i*rowsPerThread ), c0 );
         if ( j < numberOfThreads )
            image.Mov( threads[i].LowerOverlappingRegion(),
                       Point( p0.x, p0.y + j*rowsPerThread - threads[i].LowerOverlappingRegion().Height() ), c0 );
      }

      image.Status() = data.status;

      threads.Destroy();
   }
Beispiel #5
0
   template <class P> static
   void Apply( GenericImage<P>& image, const Translation& translation )
   {
      if ( translation.Delta() == 0.0 )
         return;

      int width = image.Width();
      int height = image.Height();
      if ( width == 0 || height == 0 )
         return;

      image.EnsureUnique();

      typename P::sample* f = nullptr;
      typename P::sample** f0 = nullptr;

      int n = image.NumberOfChannels();
      typename GenericImage<P>::color_space cs0 = image.ColorSpace();

      StatusMonitor status = image.Status();

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

      try
      {
         size_type N = size_type( width )*size_type( height );
         if ( status.IsInitializationEnabled() )
            status.Initialize( String().Format( "Translate dx=%.3lf, dy=%.3lf, ",
                        translation.Delta().x, translation.Delta().y ) + translation.Interpolation().Description(),
                        size_type( n )*N );

         f0 = image.ReleaseData();

         for ( int c = 0; c < n; ++c )
         {
            ThreadData<P> data( translation.Delta(), width, height, status, N );

            data.f = f = image.Allocator().AllocatePixels( size_type( width )*size_type( height ) );
            data.fillValue = (c < translation.FillValues().Length()) ? P::ToSample( translation.FillValues()[c] ) : P::MinSampleValue();

            ReferenceArray<Thread<P> > threads;
            for ( int i = 0, j = 1; i < numberOfThreads; ++i, ++j )
               threads.Add( new Thread<P>( data,
                                           translation.Interpolation().NewInterpolator<P>( f0[c], width, height ),
                                           i*rowsPerThread,
                                           (j < numberOfThreads) ? j*rowsPerThread : height ) );

            AbstractImage::RunThreads( threads, data );

            threads.Destroy();

            image.Allocator().Deallocate( f0[c] );
            f0[c] = f;
            f = nullptr;

            status = data.status;
         }

         image.ImportData( f0, width, height, n, cs0 ).Status() = status;
      }
      catch ( ... )
      {
         if ( f != nullptr )
            image.Allocator().Deallocate( f );
         if ( f0 != nullptr )
         {
            for ( int c = 0; c < n; ++c )
               if ( f0[c] != nullptr )
                  image.Allocator().Deallocate( f0[c] );
            image.Allocator().Deallocate( f0 );
         }
         image.FreeData();
         throw;
      }
   }
Beispiel #6
0
   template <class P> static
   void Apply( GenericImage<P>& image, const Resample& resample )
   {
      int width = image.Width();
      int w0 = width;
      int height = image.Height();
      int h0 = height;

      resample.GetNewSizes( width, height );

      if ( width == w0 && height == h0 )
         return;

      if ( width <= 0 || height <= 0 )
      {
         image.FreeData();
         return;
      }

      image.EnsureUnique();

      typename P::sample* f = nullptr;
      typename P::sample** f0 = nullptr;

      int n = image.NumberOfChannels();
      typename GenericImage<P>::color_space cs0 = image.ColorSpace();

      double rx = double( w0 )/width;
      double ry = double( h0 )/height;

      StatusMonitor status = image.Status();

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

      try
      {
         size_type N = size_type( width )*size_type( height );
         if ( status.IsInitializationEnabled() )
            status.Initialize( String().Format( "Resampling to %dx%d px, ", width, height )
                                                + resample.Interpolation().Description(), size_type( n )*N );
         f0 = image.ReleaseData();

         for ( int c = 0; c < n; ++c )
         {
            ThreadData<P> data( rx, ry, width, status, N );
            data.f = f = image.Allocator().AllocatePixels( width, height );

            ReferenceArray<Thread<P> > threads;
            for ( int i = 0, j = 1; i < numberOfThreads; ++i, ++j )
               threads.Add( new Thread<P>( data, resample.Interpolation().NewInterpolator<P>( f0[c], w0, h0 ),
                                           i*rowsPerThread,
                                           (j < numberOfThreads) ? j*rowsPerThread : height ) );

            AbstractImage::RunThreads( threads, data );

            threads.Destroy();

            image.Allocator().Deallocate( f0[c] );
            f0[c] = f;
            f = nullptr;

            status = data.status;
         }

         image.ImportData( f0, width, height, n, cs0 ).Status() = status;
      }
      catch ( ... )
      {
         if ( f != nullptr )
            image.Allocator().Deallocate( f );
         if ( f0 != nullptr )
         {
            for ( int c = 0; c < n; ++c )
               if ( f0[c] != nullptr )
                  image.Allocator().Deallocate( f0[c] );
            image.Allocator().Deallocate( f0 );
         }
         image.FreeData();
         throw;
      }
   }