1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkImageRGBToHSV.cxx
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 #include "vtkImageRGBToHSV.h"
16 
17 #include "vtkImageData.h"
18 #include "vtkImageProgressIterator.h"
19 #include "vtkMath.h"
20 #include "vtkObjectFactory.h"
21 
22 vtkStandardNewMacro(vtkImageRGBToHSV);
23 
24 //----------------------------------------------------------------------------
vtkImageRGBToHSV()25 vtkImageRGBToHSV::vtkImageRGBToHSV()
26 {
27   this->Maximum = 255.0;
28   this->SetNumberOfInputPorts(1);
29   this->SetNumberOfOutputPorts(1);
30 }
31 
32 //----------------------------------------------------------------------------
33 // This templated function executes the filter for any type of data.
34 template <class T>
vtkImageRGBToHSVExecute(vtkImageRGBToHSV * self,vtkImageData * inData,vtkImageData * outData,int outExt[6],int id,T *)35 void vtkImageRGBToHSVExecute(vtkImageRGBToHSV *self,
36                              vtkImageData *inData,
37                              vtkImageData *outData,
38                              int outExt[6], int id, T *)
39 {
40   vtkImageIterator<T> inIt(inData, outExt);
41   vtkImageProgressIterator<T> outIt(outData, outExt, self, id);
42   int idxC, maxC;
43   double R, G, B, H, S, V;
44   double max = self->GetMaximum();
45 
46   // find the region to loop over
47   maxC = inData->GetNumberOfScalarComponents()-1;
48 
49   // Loop through output pixels
50   while (!outIt.IsAtEnd())
51     {
52     T* inSI = inIt.BeginSpan();
53     T* outSI = outIt.BeginSpan();
54     T* outSIEnd = outIt.EndSpan();
55     while (outSI != outSIEnd)
56       {
57       // Pixel operation
58       R = static_cast<double>(*inSI) / max; inSI++;
59       G = static_cast<double>(*inSI) / max; inSI++;
60       B = static_cast<double>(*inSI) / max; inSI++;
61 
62       vtkMath::RGBToHSV(R, G, B, &H, &S, &V);
63 
64       H *= max;
65       S *= max;
66       V *= max;
67 
68       if (H > max)
69         {
70         H = max;
71         }
72       if (S > max)
73         {
74         S = max;
75         }
76       if (V > max)
77         {
78         V = max;
79         }
80 
81       // assign output.
82       *outSI = static_cast<T>(H); outSI++;
83       *outSI = static_cast<T>(S); outSI++;
84       *outSI = static_cast<T>(V); outSI++;
85 
86       for (idxC = 3; idxC <= maxC; idxC++)
87         {
88         *outSI++ = *inSI++;
89         }
90       }
91     inIt.NextSpan();
92     outIt.NextSpan();
93     }
94 }
95 
96 //----------------------------------------------------------------------------
ThreadedExecute(vtkImageData * inData,vtkImageData * outData,int outExt[6],int id)97 void vtkImageRGBToHSV::ThreadedExecute (vtkImageData *inData,
98                                          vtkImageData *outData,
99                                          int outExt[6], int id)
100 {
101   vtkDebugMacro(<< "Execute: inData = " << inData
102   << ", outData = " << outData);
103 
104   // this filter expects that input is the same type as output.
105   if (inData->GetScalarType() != outData->GetScalarType())
106     {
107     vtkErrorMacro(<< "Execute: input ScalarType, " << inData->GetScalarType()
108     << ", must match out ScalarType " << outData->GetScalarType());
109     return;
110     }
111 
112   // need three components for input and output
113   if (inData->GetNumberOfScalarComponents() < 3)
114     {
115     vtkErrorMacro("Input has too few components");
116     return;
117     }
118   if (outData->GetNumberOfScalarComponents() < 3)
119     {
120     vtkErrorMacro("Output has too few components");
121     return;
122     }
123 
124   switch (inData->GetScalarType())
125     {
126     vtkTemplateMacro(
127       vtkImageRGBToHSVExecute( this, inData,
128                                outData, outExt, id,
129                                static_cast<VTK_TT *>(0)));
130     default:
131       vtkErrorMacro(<< "Execute: Unknown ScalarType");
132       return;
133     }
134 }
135 
PrintSelf(ostream & os,vtkIndent indent)136 void vtkImageRGBToHSV::PrintSelf(ostream& os, vtkIndent indent)
137 {
138   this->Superclass::PrintSelf(os,indent);
139 
140   os << indent << "Maximum: " << this->Maximum << "\n";
141 }
142 
143