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