1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkImageCheckerboard.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 "vtkImageCheckerboard.h"
16
17 #include "vtkImageData.h"
18 #include "vtkInformation.h"
19 #include "vtkInformationVector.h"
20 #include "vtkObjectFactory.h"
21 #include "vtkStreamingDemandDrivenPipeline.h"
22
23 vtkStandardNewMacro(vtkImageCheckerboard);
24
25 //----------------------------------------------------------------------------
vtkImageCheckerboard()26 vtkImageCheckerboard::vtkImageCheckerboard()
27 {
28 this->NumberOfDivisions[0] = 2;
29 this->NumberOfDivisions[1] = 2;
30 this->NumberOfDivisions[2] = 2;
31
32 this->SetNumberOfInputPorts(2);
33 }
34
35 //----------------------------------------------------------------------------
36 // This templated function executes the filter for any type of data.
37 // Handles the two input operations
38 template <class T>
vtkImageCheckerboardExecute2(vtkImageCheckerboard * self,vtkImageData * in1Data,T * in1Ptr,vtkImageData * in2Data,T * in2Ptr,vtkImageData * outData,T * outPtr,int outExt[6],int id,int wholeExt[6])39 void vtkImageCheckerboardExecute2(vtkImageCheckerboard *self,
40 vtkImageData *in1Data, T *in1Ptr,
41 vtkImageData *in2Data, T *in2Ptr,
42 vtkImageData *outData,
43 T *outPtr,
44 int outExt[6], int id,
45 int wholeExt[6])
46 {
47 int idxR, idxY, idxZ;
48 int maxY, maxZ;
49 int dimWholeX, dimWholeY, dimWholeZ;
50 int divX, divY, divZ;
51 int nComp;
52 int selectX, selectY, selectZ;
53 int which;
54 vtkIdType inIncX, inIncY, inIncZ;
55 vtkIdType in2IncX, in2IncY, in2IncZ;
56 vtkIdType outIncX, outIncY, outIncZ;
57 int rowLength;
58 unsigned long count = 0;
59 unsigned long target;
60 int threadOffsetX, threadOffsetY, threadOffsetZ;
61 int numDivX, numDivY, numDivZ;
62
63 // find the region to loop over
64 nComp = in1Data->GetNumberOfScalarComponents();
65 rowLength = (outExt[1] - outExt[0]+1)*nComp;
66 maxY = outExt[3] - outExt[2];
67 maxZ = outExt[5] - outExt[4];
68
69 dimWholeX = wholeExt[1] - wholeExt[0] + 1;
70 dimWholeY = wholeExt[3] - wholeExt[2] + 1;
71 dimWholeZ = wholeExt[5] - wholeExt[4] + 1;
72
73 threadOffsetX = (outExt[0] - wholeExt[0]) * nComp;
74 threadOffsetY = outExt[2] - wholeExt[2];
75 threadOffsetZ = outExt[4] - wholeExt[4];
76
77 target = static_cast<unsigned long>((maxZ+1)*(maxY+1)/50.0);
78 target++;
79
80 // Get increments to march through data
81 in1Data->GetContinuousIncrements(outExt, inIncX, inIncY, inIncZ);
82 in2Data->GetContinuousIncrements(outExt, in2IncX, in2IncY, in2IncZ);
83 outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ);
84
85 // make sure number of divisions is not 0
86 numDivX = (self->GetNumberOfDivisions()[0] == 0) ? 1 : self->GetNumberOfDivisions()[0];
87 numDivY = (self->GetNumberOfDivisions()[1] == 0) ? 1 : self->GetNumberOfDivisions()[1];
88 numDivZ = (self->GetNumberOfDivisions()[2] == 0) ? 1 : self->GetNumberOfDivisions()[2];
89
90 divX = dimWholeX / numDivX * nComp;
91 divY = dimWholeY / numDivY;
92 divZ = dimWholeZ / numDivZ;
93
94 // Loop through output pixels
95 for (idxZ = 0; idxZ <= maxZ; idxZ++)
96 {
97 selectZ = (((idxZ + threadOffsetZ) / divZ) % 2) << 2;
98 for (idxY = 0; idxY <= maxY; idxY++)
99 {
100 if (!id)
101 {
102 if (!(count%target))
103 {
104 self->UpdateProgress(count/(50.0*target));
105 }
106 count++;
107 }
108 selectY = (((idxY + threadOffsetY) / divY) % 2) << 1;
109 for (idxR = 0; idxR < rowLength; idxR++)
110 {
111
112 selectX = ((idxR + threadOffsetX) / divX) % 2;
113 which = selectZ + selectY + selectX;
114 switch (which)
115 {
116 case 0:
117 *outPtr = *in1Ptr;
118 break;
119 case 1:
120 *outPtr = *in2Ptr;
121 break;
122 case 2:
123 *outPtr = *in2Ptr;
124 break;
125 case 3:
126 *outPtr = *in1Ptr;
127 break;
128 case 4:
129 *outPtr = *in2Ptr;
130 break;
131 case 5:
132 *outPtr = *in1Ptr;
133 break;
134 case 6:
135 *outPtr = *in1Ptr;
136 break;
137 case 7:
138 *outPtr = *in2Ptr;
139 break;
140 }
141 outPtr++;
142 in1Ptr++;
143 in2Ptr++;
144 }
145 outPtr += outIncY;
146 in1Ptr += inIncY;
147 in2Ptr += in2IncY;
148 }
149 outPtr += outIncZ;
150 in1Ptr += inIncZ;
151 in2Ptr += in2IncZ;
152 }
153 }
154
155
156
157 //----------------------------------------------------------------------------
158 // This method is passed a input and output regions, and executes the filter
159 // algorithm to fill the output from the inputs.
ThreadedRequestData(vtkInformation * vtkNotUsed (request),vtkInformationVector ** vtkNotUsed (inputVector),vtkInformationVector * outputVector,vtkImageData *** inData,vtkImageData ** outData,int outExt[6],int id)160 void vtkImageCheckerboard::ThreadedRequestData(
161 vtkInformation * vtkNotUsed( request ),
162 vtkInformationVector ** vtkNotUsed( inputVector ),
163 vtkInformationVector * outputVector,
164 vtkImageData ***inData,
165 vtkImageData **outData,
166 int outExt[6], int id)
167 {
168 void *in1Ptr, *in2Ptr;
169 void *outPtr;
170
171 if (inData[0][0] == nullptr)
172 {
173 vtkErrorMacro(<< "Input " << 0 << " must be specified.");
174 return;
175 }
176 in1Ptr = inData[0][0]->GetScalarPointerForExtent(outExt);
177 if (!in1Ptr)
178 {
179 vtkErrorMacro(<< "Input " << 0 << " cannot be empty.");
180 return;
181 }
182
183 outPtr = outData[0]->GetScalarPointerForExtent(outExt);
184
185 if (inData[1][0] == nullptr)
186 {
187 vtkErrorMacro(<< "Input " << 1 << " must be specified.");
188 return;
189 }
190 in2Ptr = inData[1][0]->GetScalarPointerForExtent(outExt);
191 if (!in2Ptr)
192 {
193 vtkErrorMacro(<< "Input " << 1 << " cannot be empty.");
194 return;
195 }
196
197 // this filter expects that inputs that have the same number of components
198 if (inData[0][0]->GetNumberOfScalarComponents() !=
199 inData[1][0]->GetNumberOfScalarComponents())
200 {
201 vtkErrorMacro(<< "Execute: input1 NumberOfScalarComponents, "
202 << inData[0][0]->GetNumberOfScalarComponents()
203 << ", must match out input2 NumberOfScalarComponents "
204 << inData[1][0]->GetNumberOfScalarComponents());
205 return;
206 }
207
208 vtkInformation* outInfo = outputVector->GetInformationObject(0);
209 int wholeExtent[6];
210 outInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wholeExtent);
211 switch (inData[0][0]->GetScalarType())
212 {
213 vtkTemplateMacro(
214 vtkImageCheckerboardExecute2(this, inData[0][0],
215 static_cast<VTK_TT *>(in1Ptr),
216 inData[1][0],
217 static_cast<VTK_TT *>(in2Ptr),
218 outData[0],
219 static_cast<VTK_TT *>(outPtr),
220 outExt, id, wholeExtent));
221 default:
222 vtkErrorMacro(<< "Execute: Unknown ScalarType");
223 return;
224 }
225 }
226
PrintSelf(ostream & os,vtkIndent indent)227 void vtkImageCheckerboard::PrintSelf(ostream& os, vtkIndent indent)
228 {
229 this->Superclass::PrintSelf(os,indent);
230 os << indent << "NumberOfDivisions: (" << this->NumberOfDivisions[0] << ", "
231 << this->NumberOfDivisions[1] << ", "
232 << this->NumberOfDivisions[2] << ")\n";
233 }
234
235