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