// ------------------------------------------------------------------------- // @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) // ------------------------------------------------------------------------- #ifndef __CPPLUGINS__EXTENSIONS__ALGORITHMS__RGBIMAGETOHSVCHANNELSFILTER__HXX__ #define __CPPLUGINS__EXTENSIONS__ALGORITHMS__RGBIMAGETOHSVCHANNELSFILTER__HXX__ #include #include #include #include #include // ------------------------------------------------------------------------- template< class I, class O > O* cpPlugins::Extensions::Algorithms::RGBImageToHSVChannelsFilter< I, O >:: GetHueOutput( ) { return( this->GetOutput( 0 ) ); } // ------------------------------------------------------------------------- template< class I, class O > O* cpPlugins::Extensions::Algorithms::RGBImageToHSVChannelsFilter< I, O >:: GetSaturationOutput( ) { return( this->GetOutput( 1 ) ); } // ------------------------------------------------------------------------- template< class I, class O > O* cpPlugins::Extensions::Algorithms::RGBImageToHSVChannelsFilter< I, O >:: GetValueOutput( ) { return( this->GetOutput( 2 ) ); } // ------------------------------------------------------------------------- template< class I, class O > const O* cpPlugins::Extensions::Algorithms::RGBImageToHSVChannelsFilter< I, O >:: GetHueOutput( ) const { if( this->GetNumberOfOutputs( ) > 0 ) return( dynamic_cast< const O* >( this->itk::ProcessObject::GetOutput( 0 ) ) ); else return( NULL ); } // ------------------------------------------------------------------------- template< class I, class O > const O* cpPlugins::Extensions::Algorithms::RGBImageToHSVChannelsFilter< I, O >:: GetSaturationOutput( ) const { if( this->GetNumberOfOutputs( ) > 1 ) return( dynamic_cast< const O* >( this->itk::ProcessObject::GetOutput( 1 ) ) ); else return( NULL ); } // ------------------------------------------------------------------------- template< class I, class O > const O* cpPlugins::Extensions::Algorithms::RGBImageToHSVChannelsFilter< I, O >:: GetValueOutput( ) const { if( this->GetNumberOfOutputs( ) > 2 ) return( dynamic_cast< const O* >( this->itk::ProcessObject::GetOutput( 2 ) ) ); else return( NULL ); } // ------------------------------------------------------------------------- template< class I, class O > void cpPlugins::Extensions::Algorithms::RGBImageToHSVChannelsFilter< I, O >:: GraftHueOutput( O* hue ) { this->GraftNthOutput( 0, hue ); } // ------------------------------------------------------------------------- template< class I, class O > void cpPlugins::Extensions::Algorithms::RGBImageToHSVChannelsFilter< I, O >:: GraftSaturationOutput( O* saturation ) { this->GraftNthOutput( 1, saturation ); } // ------------------------------------------------------------------------- template< class I, class O > void cpPlugins::Extensions::Algorithms::RGBImageToHSVChannelsFilter< I, O >:: GraftValueOutput( O* value ) { this->GraftNthOutput( 2, value ); } // ------------------------------------------------------------------------- template< class I, class O > cpPlugins::Extensions::Algorithms::RGBImageToHSVChannelsFilter< I, O >:: RGBImageToHSVChannelsFilter( ) : Superclass( ) { this->SetNumberOfRequiredInputs( 1 ); this->SetNumberOfRequiredOutputs( 3 ); for( unsigned int i = 0; i < 3; i++ ) { typename O::Pointer o = O::New( ); this->SetNthOutput( i, o ); } // rof } // ------------------------------------------------------------------------- template< class I, class O > cpPlugins::Extensions::Algorithms::RGBImageToHSVChannelsFilter< I, O >:: ~RGBImageToHSVChannelsFilter( ) { } // ------------------------------------------------------------------------- template< class I, class O > void cpPlugins::Extensions::Algorithms::RGBImageToHSVChannelsFilter< I, O >:: BeforeThreadedGenerateData( ) { } // ------------------------------------------------------------------------- template< class I, class O > void cpPlugins::Extensions::Algorithms::RGBImageToHSVChannelsFilter< I, O >:: AfterThreadedGenerateData( ) { } // ------------------------------------------------------------------------- template< class I, class O > void cpPlugins::Extensions::Algorithms::RGBImageToHSVChannelsFilter< I, O >:: ThreadedGenerateData( const typename Superclass::OutputImageRegionType& region, itk::ThreadIdType threadId ) { typedef itk::ImageRegionConstIterator< I > TInIt; typedef itk::ImageRegionIterator< O > TOutIt; TInIt inIt( this->GetInput( ), region ); TOutIt hIt( this->GetHueOutput( ), region ); TOutIt sIt( this->GetSaturationOutput( ), region ); TOutIt vIt( this->GetValueOutput( ), region ); inIt.GoToBegin( ); hIt.GoToBegin( ); sIt.GoToBegin( ); vIt.GoToBegin( ); for( ; !inIt.IsAtEnd( ); ++inIt, ++hIt, ++sIt, ++vIt ) { TOutputPixel H, S, V; Self::_RGB2HSV( inIt.Get( ), H, S, V ); hIt.Set( H ); sIt.Set( S ); vIt.Set( V ); } // rof } // ------------------------------------------------------------------------- template< class I, class O > void cpPlugins::Extensions::Algorithms::RGBImageToHSVChannelsFilter< I, O >:: _RGB2HSV( const TInputPixel& RGB, TOutputPixel& H, TOutputPixel& S, TOutputPixel& V ) { typedef typename TInputPixel::ComponentType TComponent; const double mVal = double( std::numeric_limits< TComponent >::max( ) ); const double _0 = double( 0 ); const double _1 = double( 1 ); const double _2 = double( 2 ); const double _3 = double( 3 ); const double _2pi = _2 * double( vnl_math::pi ); double R = double( RGB.GetRed( ) ); double G = double( RGB.GetGreen( ) ); double B = double( RGB.GetBlue( ) ); double sRGB = R + G + B; double RG = R - G; double RB = R - B; double GB = G - B; // Hue double A = std::sqrt( ( RG * RG ) + ( RB * GB ) ); if( A != _0 ) A = std::acos( ( RG + RB ) / ( _2 * A ) ); A /= _2pi; H = TOutputPixel( mVal * ( ( G >= B )? A: _1 - A ) ); // Saturation if( sRGB != _0 ) { double C = ( G < R )? G: R; C = ( B < C )? B: C; S = TOutputPixel( mVal * ( _1 - ( ( _3 * C ) / sRGB ) ) ); } else S = TOutputPixel( 0 ); // Value V = TOutputPixel( sRGB / _3 ); } #endif // __CPPLUGINS__EXTENSIONS__ALGORITHMS__RGBIMAGETOHSVCHANNELSFILTER__HXX__ // eof - $RCSfile$