1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkImageRectilinearWipe.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 "vtkImageRectilinearWipe.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(vtkImageRectilinearWipe);
24 
25 //----------------------------------------------------------------------------
vtkImageRectilinearWipe()26 vtkImageRectilinearWipe::vtkImageRectilinearWipe()
27 {
28   this->Position[0] = 0;
29   this->Position[1] = 0;
30   this->Axis[0] = 0;
31   this->Axis[1] = 1;
32   this->Wipe = VTK_WIPE_QUAD;
33   this->SetNumberOfInputPorts(2);
34 }
35 
36 //----------------------------------------------------------------------------
37 // This templated function executes the filter for any type of data.
38 // Handles the two input operations
39 template <class T>
vtkImageRectilinearWipeExecute2(vtkImageRectilinearWipe * self,vtkImageData * inData,T * inPtr,vtkImageData * outData,T * outPtr,int outExt[6],int id)40 void vtkImageRectilinearWipeExecute2(vtkImageRectilinearWipe *self,
41                            vtkImageData *inData, T *inPtr,
42                            vtkImageData *outData,
43                            T *outPtr,
44                            int outExt[6], int id)
45 {
46   int idxR, idxY, idxZ;
47   int maxY, maxZ;
48   vtkIdType inIncX, inIncY, inIncZ;
49   vtkIdType outIncX, outIncY, outIncZ;
50   int rowLength;
51   unsigned long count = 0;
52   unsigned long target;
53 
54   // find the region to loop over
55   rowLength = (outExt[1] - outExt[0]+1)*inData->GetNumberOfScalarComponents();
56   maxY = outExt[3] - outExt[2];
57   maxZ = outExt[5] - outExt[4];
58 
59   target = static_cast<unsigned long>((maxZ+1)*(maxY+1)/50.0);
60   target++;
61 
62   // Get increments to march through data
63   inData->GetContinuousIncrements(outExt, inIncX, inIncY, inIncZ);
64   outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ);
65 
66   // Loop through output pixels
67   for (idxZ = 0; idxZ <= maxZ; idxZ++)
68     {
69     for (idxY = 0; idxY <= maxY; idxY++)
70       {
71       if (!id)
72         {
73         if (!(count%target))
74           {
75           self->UpdateProgress(count/(50.0*target));
76           }
77         count++;
78         }
79       for (idxR = 0; idxR < rowLength; idxR++)
80         {
81         *outPtr = *inPtr;
82         outPtr++;
83         inPtr++;
84         }
85       outPtr += outIncY;
86       inPtr += inIncY;
87       }
88     outPtr += outIncZ;
89     inPtr += inIncZ;
90     }
91 }
92 
93 
94 
95 //----------------------------------------------------------------------------
96 // This function adjusts the extents of the wipe to the output extents.
vtkImageRectilinearWipeClampExtents(int wipeExt[6],int outExt[6])97 static int vtkImageRectilinearWipeClampExtents(int wipeExt[6], int outExt[6])
98 {
99   int status = 1;
100 
101   for (int i = 0; i < 3; i++)
102     {
103     // the lower and upper extents cannot be below the lower output extent
104     if (wipeExt[2*i] < outExt[2*i])
105       {
106       wipeExt[2*i] = outExt[2*i];
107       }
108     if (wipeExt[2*i + 1] < outExt[2*i])
109       {
110       wipeExt[2*i + 1] = outExt[2*i];
111       status = 0;
112       }
113 
114     // the lower and upper extents cannot be above the upper output extent
115     if (wipeExt[2*i] > outExt[2*i + 1])
116       {
117       wipeExt[2*i] = outExt[2*i + 1];
118       status = 0;
119       }
120     if (wipeExt[2*i + 1] > outExt[2*i + 1])
121       {
122       wipeExt[2*i + 1] = outExt[2*i + 1];
123       }
124     }
125   return status;
126 }
127 //----------------------------------------------------------------------------
128 // This method is passed a input and output regions, and executes the filter
129 // algorithm to fill the output from the inputs based on the Wipe ivar.
ThreadedRequestData(vtkInformation * vtkNotUsed (request),vtkInformationVector ** vtkNotUsed (inputVector),vtkInformationVector * outputVector,vtkImageData *** inData,vtkImageData ** outData,int outExt[6],int id)130 void vtkImageRectilinearWipe::ThreadedRequestData(
131   vtkInformation * vtkNotUsed( request ),
132   vtkInformationVector ** vtkNotUsed( inputVector ),
133   vtkInformationVector * outputVector,
134   vtkImageData ***inData,
135   vtkImageData **outData,
136   int outExt[6], int id)
137 {
138   void *inPtr;
139   void *outPtr;
140   int wipeExt[6];
141   int wholeExt[6];
142   int whichInput = 0;
143 
144   // Make sure the inputs/output are valid
145   if (inData[0][0] == NULL)
146     {
147     vtkErrorMacro(<< "Input " << 0 << " must be specified.");
148     return;
149     }
150 
151   // this filter expects that input is the same type as output.
152   if (inData[0][0]->GetScalarType() != outData[0]->GetScalarType())
153     {
154     vtkErrorMacro(<< "Execute: input ScalarType, "
155                   << inData[0][0]->GetScalarType()
156                   << ", must match out ScalarType "
157                   << outData[0]->GetScalarType());
158     return;
159     }
160 
161   if (inData[1][0] == NULL)
162     {
163     vtkErrorMacro(<< "Input " << 1 << " must be specified.");
164     return;
165     }
166 
167   // this filter expects that inputs that have the same number of components
168   if (inData[0][0]->GetNumberOfScalarComponents() !=
169       inData[1][0]->GetNumberOfScalarComponents())
170     {
171     vtkErrorMacro(<< "Execute: input1 NumberOfScalarComponents, "
172                   << inData[0][0]->GetNumberOfScalarComponents()
173                   << ", must match out input2 NumberOfScalarComponents "
174                   << inData[1][0]->GetNumberOfScalarComponents());
175     return;
176     }
177 
178   // Wipe pattern depends on the whole extent.
179   outputVector->GetInformationObject(0)->Get(
180     vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wholeExt);
181 
182   // Each quadrant is processed separately
183   // lower left
184 
185   memcpy (wipeExt, wholeExt, 6 * sizeof (int));
186   wipeExt[2*this->Axis[0]+1] += this->Position[0];
187   wipeExt[2*this->Axis[1]+1] += this->Position[1];
188 
189   if (vtkImageRectilinearWipeClampExtents(wipeExt, outExt))
190     {
191 
192     outPtr = outData[0]->GetScalarPointerForExtent(wipeExt);
193 
194     switch (this->Wipe)
195       {
196       case VTK_WIPE_QUAD:
197         whichInput = 0;
198         break;
199       case VTK_WIPE_HORIZONTAL:
200         whichInput = 0;
201         break;
202       case VTK_WIPE_VERTICAL:
203         whichInput = 0;
204         break;
205       case VTK_WIPE_LOWER_LEFT:
206         whichInput = 0;
207         break;
208       case VTK_WIPE_LOWER_RIGHT:
209         whichInput = 1;
210         break;
211       case VTK_WIPE_UPPER_LEFT:
212         whichInput = 1;
213         break;
214       case VTK_WIPE_UPPER_RIGHT:
215         whichInput = 1;
216         break;
217       }
218     inPtr = inData[whichInput][0]->GetScalarPointerForExtent(wipeExt);
219     switch (inData[0][0]->GetScalarType())
220       {
221       vtkTemplateMacro(
222         vtkImageRectilinearWipeExecute2(this,
223                                         inData[whichInput][0],
224                                         static_cast<VTK_TT *>(inPtr),
225                                         outData[0],
226                                         static_cast<VTK_TT *>(outPtr),
227                                         wipeExt, id));
228       default:
229         vtkErrorMacro(<< "Execute: Unknown ScalarType");
230         return;
231       }
232     }
233 
234   // lower right
235   memcpy (wipeExt, wholeExt, 6 * sizeof (int));
236   wipeExt[2*this->Axis[0]] += (this->Position[0]+1);
237   wipeExt[2*this->Axis[1]+1] =
238     wipeExt[2*this->Axis[1]] + this->Position[1];
239 
240   if (vtkImageRectilinearWipeClampExtents(wipeExt, outExt))
241     {
242     switch (this->Wipe)
243       {
244       case VTK_WIPE_QUAD:
245         whichInput = 1;
246         break;
247       case VTK_WIPE_HORIZONTAL:
248         whichInput = 1;
249         break;
250       case VTK_WIPE_VERTICAL:
251         whichInput = 0;
252         break;
253       case VTK_WIPE_LOWER_LEFT:
254         whichInput = 1;
255         break;
256       case VTK_WIPE_LOWER_RIGHT:
257         whichInput = 0;
258         break;
259       case VTK_WIPE_UPPER_LEFT:
260         whichInput = 1;
261         break;
262       case VTK_WIPE_UPPER_RIGHT:
263         whichInput = 1;
264         break;
265       }
266     inPtr = inData[whichInput][0]->GetScalarPointerForExtent(wipeExt);
267     outPtr = outData[0]->GetScalarPointerForExtent(wipeExt);
268     switch (inData[0][0]->GetScalarType())
269       {
270       vtkTemplateMacro(
271         vtkImageRectilinearWipeExecute2(this,
272                                         inData[whichInput][0],
273                                         static_cast<VTK_TT *>(inPtr),
274                                         outData[0],
275                                         static_cast<VTK_TT *>(outPtr),
276                                         wipeExt, id));
277       default:
278         vtkErrorMacro(<< "Execute: Unknown ScalarType");
279         return;
280       }
281     }
282 
283   // upper left
284   memcpy (wipeExt, wholeExt, 6 * sizeof (int));
285   wipeExt[2*this->Axis[0]+1] = wipeExt[2*this->Axis[0]] + this->Position[0];
286   wipeExt[2*this->Axis[1]] += (this->Position[1] + 1);
287 
288   if (vtkImageRectilinearWipeClampExtents(wipeExt, outExt))
289     {
290 
291     switch (this->Wipe)
292       {
293       case VTK_WIPE_QUAD:
294         whichInput = 1;
295         break;
296       case VTK_WIPE_HORIZONTAL:
297         whichInput = 0;
298         break;
299       case VTK_WIPE_VERTICAL:
300         whichInput = 1;
301         break;
302       case VTK_WIPE_LOWER_LEFT:
303         whichInput = 1;
304         break;
305       case VTK_WIPE_LOWER_RIGHT:
306         whichInput = 1;
307         break;
308       case VTK_WIPE_UPPER_LEFT:
309         whichInput = 0;
310         break;
311       case VTK_WIPE_UPPER_RIGHT:
312         whichInput = 1;
313         break;
314       }
315     inPtr = inData[whichInput][0]->GetScalarPointerForExtent(wipeExt);
316     outPtr = outData[0]->GetScalarPointerForExtent(wipeExt);
317     switch (inData[0][0]->GetScalarType())
318       {
319       vtkTemplateMacro(
320         vtkImageRectilinearWipeExecute2(this,
321                                         inData[whichInput][0],
322                                         static_cast<VTK_TT *>(inPtr),
323                                         outData[0],
324                                         static_cast<VTK_TT *>(outPtr),
325                                         wipeExt, id));
326       default:
327         vtkErrorMacro(<< "Execute: Unknown ScalarType");
328         return;
329       }
330     }
331 
332   // upper right
333   memcpy (wipeExt, wholeExt, 6 * sizeof (int));
334   wipeExt[2*this->Axis[0]] += (this->Position[0] + 1);
335   wipeExt[2*this->Axis[1]] += (this->Position[1] + 1);
336 
337   if (vtkImageRectilinearWipeClampExtents(wipeExt, outExt))
338     {
339     switch (this->Wipe)
340       {
341       case VTK_WIPE_QUAD:
342         whichInput = 0;
343         break;
344       case VTK_WIPE_HORIZONTAL:
345         whichInput = 1;
346         break;
347       case VTK_WIPE_VERTICAL:
348         whichInput = 1;
349         break;
350       case VTK_WIPE_LOWER_LEFT:
351         whichInput = 1;
352         break;
353       case VTK_WIPE_LOWER_RIGHT:
354         whichInput = 1;
355         break;
356       case VTK_WIPE_UPPER_LEFT:
357         whichInput = 1;
358         break;
359       case VTK_WIPE_UPPER_RIGHT:
360         whichInput = 0;
361         break;
362       }
363     inPtr = inData[whichInput][0]->GetScalarPointerForExtent(wipeExt);
364     outPtr = outData[0]->GetScalarPointerForExtent(wipeExt);
365     switch (inData[0][0]->GetScalarType())
366       {
367       vtkTemplateMacro(
368         vtkImageRectilinearWipeExecute2(this,
369                                         inData[whichInput][0],
370                                         static_cast<VTK_TT *>(inPtr),
371                                         outData[0],
372                                         static_cast<VTK_TT *>(outPtr),
373                                         wipeExt, id));
374       default:
375         vtkErrorMacro(<< "Execute: Unknown ScalarType");
376         return;
377       }
378     }
379 }
380 
PrintSelf(ostream & os,vtkIndent indent)381 void vtkImageRectilinearWipe::PrintSelf(ostream& os, vtkIndent indent)
382 {
383   this->Superclass::PrintSelf(os,indent);
384   os << indent << "Position: (" << this->Position[0] << ", "
385      << this->Position[1] << ")\n";
386   os << indent << "Position: (" << this->Axis[0] << ", "
387      << this->Axis[1] << ", " << this->Axis[1] << ")\n";
388   os << indent << "Wipe: ";
389   switch (this->Wipe)
390     {
391     case VTK_WIPE_QUAD:
392       os << "Quad" << endl;
393       break;
394     case VTK_WIPE_HORIZONTAL:
395       os << "Horizontal" << endl;
396       break;
397     case VTK_WIPE_VERTICAL:
398       os << "Vertical" << endl;
399       break;
400     case VTK_WIPE_LOWER_LEFT:
401       os << "LowerLeft" << endl;
402       break;
403     case VTK_WIPE_LOWER_RIGHT:
404       os << "LowerRight" << endl;
405       break;
406     case VTK_WIPE_UPPER_LEFT:
407       os << "UpperLeft" << endl;
408       break;
409     case VTK_WIPE_UPPER_RIGHT:
410       os << "UpperRight" << endl;
411       break;
412     }
413 }
414 
415