+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#ifndef __CPPLUGINS__EXTENSIONS__ALGORITHMS__RGBIMAGETOHSVCHANNELSFILTER__HXX__
+#define __CPPLUGINS__EXTENSIONS__ALGORITHMS__RGBIMAGETOHSVCHANNELSFILTER__HXX__
+
+#include <cmath>
+#include <limits>
+#include <vnl/vnl_math.h>
+
+#include <itkImageRegionIterator.h>
+#include <itkImageRegionConstIterator.h>
+
+// -------------------------------------------------------------------------
+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$