1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkImageThreshold.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 "vtkImageThreshold.h"
16 
17 #include "vtkDataSetAttributes.h"
18 #include "vtkImageData.h"
19 #include "vtkImageProgressIterator.h"
20 #include "vtkInformation.h"
21 #include "vtkInformationVector.h"
22 #include "vtkObjectFactory.h"
23 #include "vtkStreamingDemandDrivenPipeline.h"
24 
25 vtkStandardNewMacro(vtkImageThreshold);
26 
27 //------------------------------------------------------------------------------
28 // Constructor sets default values
vtkImageThreshold()29 vtkImageThreshold::vtkImageThreshold()
30 {
31   this->UpperThreshold = VTK_FLOAT_MAX;
32   this->LowerThreshold = -VTK_FLOAT_MAX;
33   this->ReplaceIn = 0;
34   this->InValue = 0.0;
35   this->ReplaceOut = 0;
36   this->OutValue = 0.0;
37 
38   this->OutputScalarType = -1; // invalid; output same as input
39 }
40 
41 //------------------------------------------------------------------------------
SetInValue(double val)42 void vtkImageThreshold::SetInValue(double val)
43 {
44   if (val != this->InValue || this->ReplaceIn != 1)
45   {
46     this->InValue = val;
47     this->ReplaceIn = 1;
48     this->Modified();
49   }
50 }
51 
52 //------------------------------------------------------------------------------
SetOutValue(double val)53 void vtkImageThreshold::SetOutValue(double val)
54 {
55   if (val != this->OutValue || this->ReplaceOut != 1)
56   {
57     this->OutValue = val;
58     this->ReplaceOut = 1;
59     this->Modified();
60   }
61 }
62 
63 //------------------------------------------------------------------------------
64 // The values greater than or equal to the value match.
ThresholdByUpper(double thresh)65 void vtkImageThreshold::ThresholdByUpper(double thresh)
66 {
67   if (this->LowerThreshold != thresh || this->UpperThreshold < VTK_FLOAT_MAX)
68   {
69     this->LowerThreshold = thresh;
70     this->UpperThreshold = VTK_FLOAT_MAX;
71     this->Modified();
72   }
73 }
74 
75 //------------------------------------------------------------------------------
76 // The values less than or equal to the value match.
ThresholdByLower(double thresh)77 void vtkImageThreshold::ThresholdByLower(double thresh)
78 {
79   if (this->UpperThreshold != thresh || this->LowerThreshold > -VTK_FLOAT_MAX)
80   {
81     this->UpperThreshold = thresh;
82     this->LowerThreshold = -VTK_FLOAT_MAX;
83     this->Modified();
84   }
85 }
86 
87 //------------------------------------------------------------------------------
88 // The values in a range (inclusive) match
ThresholdBetween(double lower,double upper)89 void vtkImageThreshold::ThresholdBetween(double lower, double upper)
90 {
91   if (this->LowerThreshold != lower || this->UpperThreshold != upper)
92   {
93     this->LowerThreshold = lower;
94     this->UpperThreshold = upper;
95     this->Modified();
96   }
97 }
98 
99 //------------------------------------------------------------------------------
RequestInformation(vtkInformation * vtkNotUsed (request),vtkInformationVector ** inputVector,vtkInformationVector * outputVector)100 int vtkImageThreshold::RequestInformation(vtkInformation* vtkNotUsed(request),
101   vtkInformationVector** inputVector, vtkInformationVector* outputVector)
102 {
103   // get the info objects
104   vtkInformation* outInfo = outputVector->GetInformationObject(0);
105   vtkInformation* inInfo = inputVector[0]->GetInformationObject(0);
106 
107   if (this->OutputScalarType == -1)
108   {
109     vtkInformation* inScalarInfo = vtkDataObject::GetActiveFieldInformation(
110       inInfo, vtkDataObject::FIELD_ASSOCIATION_POINTS, vtkDataSetAttributes::SCALARS);
111     if (!inScalarInfo)
112     {
113       vtkErrorMacro("Missing scalar field on input information!");
114       return 0;
115     }
116     vtkDataObject::SetPointDataActiveScalarInfo(
117       outInfo, inScalarInfo->Get(vtkDataObject::FIELD_ARRAY_TYPE()), -1);
118   }
119   else
120   {
121     vtkDataObject::SetPointDataActiveScalarInfo(outInfo, this->OutputScalarType, -1);
122   }
123   return 1;
124 }
125 
126 //------------------------------------------------------------------------------
127 // This templated function executes the filter for any type of data.
128 template <class IT, class OT>
vtkImageThresholdExecute(vtkImageThreshold * self,vtkImageData * inData,vtkImageData * outData,int outExt[6],int id,IT *,OT *)129 void vtkImageThresholdExecute(vtkImageThreshold* self, vtkImageData* inData, vtkImageData* outData,
130   int outExt[6], int id, IT*, OT*)
131 {
132   vtkImageIterator<IT> inIt(inData, outExt);
133   vtkImageProgressIterator<OT> outIt(outData, outExt, self, id);
134   IT lowerThreshold;
135   IT upperThreshold;
136   int replaceIn = self->GetReplaceIn();
137   OT inValue;
138   int replaceOut = self->GetReplaceOut();
139   OT outValue;
140   IT temp;
141 
142   // Make sure the thresholds are valid for the input scalar range
143   if (static_cast<double>(self->GetLowerThreshold()) < inData->GetScalarTypeMin())
144   {
145     lowerThreshold = static_cast<IT>(inData->GetScalarTypeMin());
146   }
147   else
148   {
149     if (static_cast<double>(self->GetLowerThreshold()) > inData->GetScalarTypeMax())
150     {
151       lowerThreshold = static_cast<IT>(inData->GetScalarTypeMax());
152     }
153     else
154     {
155       lowerThreshold = static_cast<IT>(self->GetLowerThreshold());
156     }
157   }
158   if (static_cast<double>(self->GetUpperThreshold()) > inData->GetScalarTypeMax())
159   {
160     upperThreshold = static_cast<IT>(inData->GetScalarTypeMax());
161   }
162   else
163   {
164     if (static_cast<double>(self->GetUpperThreshold()) < inData->GetScalarTypeMin())
165     {
166       upperThreshold = static_cast<IT>(inData->GetScalarTypeMin());
167     }
168     else
169     {
170       upperThreshold = static_cast<IT>(self->GetUpperThreshold());
171     }
172   }
173 
174   // Make sure the replacement values are within the output scalar range
175   if (static_cast<double>(self->GetInValue()) < outData->GetScalarTypeMin())
176   {
177     inValue = static_cast<OT>(outData->GetScalarTypeMin());
178   }
179   else
180   {
181     if (static_cast<double>(self->GetInValue()) > outData->GetScalarTypeMax())
182     {
183       inValue = static_cast<OT>(outData->GetScalarTypeMax());
184     }
185     else
186     {
187       inValue = static_cast<OT>(self->GetInValue());
188     }
189   }
190   if (static_cast<double>(self->GetOutValue()) > outData->GetScalarTypeMax())
191   {
192     outValue = static_cast<OT>(outData->GetScalarTypeMax());
193   }
194   else
195   {
196     if (static_cast<double>(self->GetOutValue()) < outData->GetScalarTypeMin())
197     {
198       outValue = static_cast<OT>(outData->GetScalarTypeMin());
199     }
200     else
201     {
202       outValue = static_cast<OT>(self->GetOutValue());
203     }
204   }
205 
206   // Loop through output pixels
207   while (!outIt.IsAtEnd())
208   {
209     IT* inSI = inIt.BeginSpan();
210     OT* outSI = outIt.BeginSpan();
211     OT* outSIEnd = outIt.EndSpan();
212     while (outSI != outSIEnd)
213     {
214       // Pixel operation
215       temp = (*inSI);
216       if (lowerThreshold <= temp && temp <= upperThreshold)
217       {
218         // match
219         if (replaceIn)
220         {
221           *outSI = inValue;
222         }
223         else
224         {
225           *outSI = static_cast<OT>(temp);
226         }
227       }
228       else
229       {
230         // not match
231         if (replaceOut)
232         {
233           *outSI = outValue;
234         }
235         else
236         {
237           *outSI = static_cast<OT>(temp);
238         }
239       }
240       ++inSI;
241       ++outSI;
242     }
243     inIt.NextSpan();
244     outIt.NextSpan();
245   }
246 }
247 
248 //------------------------------------------------------------------------------
249 template <class T>
vtkImageThresholdExecute1(vtkImageThreshold * self,vtkImageData * inData,vtkImageData * outData,int outExt[6],int id,T *)250 void vtkImageThresholdExecute1(
251   vtkImageThreshold* self, vtkImageData* inData, vtkImageData* outData, int outExt[6], int id, T*)
252 {
253   switch (outData->GetScalarType())
254   {
255     vtkTemplateMacro(vtkImageThresholdExecute(
256       self, inData, outData, outExt, id, static_cast<T*>(nullptr), static_cast<VTK_TT*>(nullptr)));
257     default:
258       vtkGenericWarningMacro("Execute: Unknown input ScalarType");
259       return;
260   }
261 }
262 
263 //------------------------------------------------------------------------------
264 // This method is passed a input and output data, and executes the filter
265 // algorithm to fill the output from the input.
266 // It just executes a switch statement to call the correct function for
267 // the datas data types.
ThreadedRequestData(vtkInformation * vtkNotUsed (request),vtkInformationVector ** vtkNotUsed (inputVector),vtkInformationVector * vtkNotUsed (outputVector),vtkImageData *** inData,vtkImageData ** outData,int outExt[6],int id)268 void vtkImageThreshold::ThreadedRequestData(vtkInformation* vtkNotUsed(request),
269   vtkInformationVector** vtkNotUsed(inputVector), vtkInformationVector* vtkNotUsed(outputVector),
270   vtkImageData*** inData, vtkImageData** outData, int outExt[6], int id)
271 {
272   switch (inData[0][0]->GetScalarType())
273   {
274     vtkTemplateMacro(vtkImageThresholdExecute1(
275       this, inData[0][0], outData[0], outExt, id, static_cast<VTK_TT*>(nullptr)));
276     default:
277       vtkErrorMacro(<< "Execute: Unknown input ScalarType");
278       return;
279   }
280 }
281 
282 //------------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)283 void vtkImageThreshold::PrintSelf(ostream& os, vtkIndent indent)
284 {
285   this->Superclass::PrintSelf(os, indent);
286 
287   os << indent << "OutputScalarType: " << this->OutputScalarType << "\n";
288   os << indent << "InValue: " << this->InValue << "\n";
289   os << indent << "OutValue: " << this->OutValue << "\n";
290   os << indent << "LowerThreshold: " << this->LowerThreshold << "\n";
291   os << indent << "UpperThreshold: " << this->UpperThreshold << "\n";
292   os << indent << "ReplaceIn: " << this->ReplaceIn << "\n";
293   os << indent << "ReplaceOut: " << this->ReplaceOut << "\n";
294 }
295