1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkImageNormalize.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 "vtkImageNormalize.h"
16 
17 #include "vtkImageData.h"
18 #include "vtkImageProgressIterator.h"
19 #include "vtkInformation.h"
20 #include "vtkInformationVector.h"
21 #include "vtkObjectFactory.h"
22 #include "vtkStreamingDemandDrivenPipeline.h"
23 
24 #include <cmath>
25 
26 vtkStandardNewMacro(vtkImageNormalize);
27 
28 //------------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)29 void vtkImageNormalize::PrintSelf(ostream& os, vtkIndent indent)
30 {
31   this->Superclass::PrintSelf(os, indent);
32 }
33 
34 //------------------------------------------------------------------------------
vtkImageNormalize()35 vtkImageNormalize::vtkImageNormalize()
36 {
37   this->SetNumberOfInputPorts(1);
38   this->SetNumberOfOutputPorts(1);
39 }
40 
41 //------------------------------------------------------------------------------
RequestInformation(vtkInformation * vtkNotUsed (request),vtkInformationVector ** vtkNotUsed (inputVector),vtkInformationVector * outputVector)42 int vtkImageNormalize::RequestInformation(vtkInformation* vtkNotUsed(request),
43   vtkInformationVector** vtkNotUsed(inputVector), vtkInformationVector* outputVector)
44 {
45   // get the info objects
46   vtkInformation* outInfo = outputVector->GetInformationObject(0);
47   vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_FLOAT, -1);
48   return 1;
49 }
50 
51 //------------------------------------------------------------------------------
52 // This execute method handles boundaries.
53 // it handles boundaries. Pixels are just replicated to get values
54 // out of extent.
55 template <class T>
vtkImageNormalizeExecute(vtkImageNormalize * self,vtkImageData * inData,vtkImageData * outData,int outExt[6],int id,T *)56 void vtkImageNormalizeExecute(
57   vtkImageNormalize* self, vtkImageData* inData, vtkImageData* outData, int outExt[6], int id, T*)
58 {
59   vtkImageIterator<T> inIt(inData, outExt);
60   vtkImageProgressIterator<float> outIt(outData, outExt, self, id);
61   int idxC, maxC;
62   float sum;
63   T* inVect;
64 
65   // find the region to loop over
66   maxC = inData->GetNumberOfScalarComponents();
67 
68   // Loop through output pixels
69   while (!outIt.IsAtEnd())
70   {
71     T* inSI = inIt.BeginSpan();
72     float* outSI = outIt.BeginSpan();
73     float* outSIEnd = outIt.EndSpan();
74     while (outSI != outSIEnd)
75     {
76       // save the start of the vector
77       inVect = inSI;
78 
79       // compute the magnitude.
80       sum = 0.0;
81       for (idxC = 0; idxC < maxC; idxC++)
82       {
83         sum += static_cast<float>(*inSI) * static_cast<float>(*inSI);
84         inSI++;
85       }
86       if (sum > 0.0)
87       {
88         sum = 1.0 / sqrt(sum);
89       }
90 
91       // now divide to normalize.
92       for (idxC = 0; idxC < maxC; idxC++)
93       {
94         *outSI = static_cast<float>(*inVect) * sum;
95         inVect++;
96         outSI++;
97       }
98     }
99     inIt.NextSpan();
100     outIt.NextSpan();
101   }
102 }
103 
104 //------------------------------------------------------------------------------
105 // This method contains a switch statement that calls the correct
106 // templated function for the input data type.  The output data
107 // must match input type.  This method does handle boundary conditions.
ThreadedExecute(vtkImageData * inData,vtkImageData * outData,int outExt[6],int id)108 void vtkImageNormalize::ThreadedExecute(
109   vtkImageData* inData, vtkImageData* outData, int outExt[6], int id)
110 {
111   vtkDebugMacro(<< "Execute: inData = " << inData << ", outData = " << outData);
112 
113   // this filter expects that input is the same type as output.
114   if (outData->GetScalarType() != VTK_FLOAT)
115   {
116     vtkErrorMacro(<< "Execute: output ScalarType, " << outData->GetScalarType()
117                   << ", must be float");
118     return;
119   }
120 
121   switch (inData->GetScalarType())
122   {
123     vtkTemplateMacro(
124       vtkImageNormalizeExecute(this, inData, outData, outExt, id, static_cast<VTK_TT*>(nullptr)));
125     default:
126       vtkErrorMacro(<< "Execute: Unknown ScalarType");
127       return;
128   }
129 }
130