1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkImageMirrorPad.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 "vtkImageMirrorPad.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(vtkImageMirrorPad);
24 
25 //----------------------------------------------------------------------------
26 // Just clip the request.
ComputeInputUpdateExtent(int inExt[6],int outExt[6],int wExtent[6])27 void vtkImageMirrorPad::ComputeInputUpdateExtent(int inExt[6],
28                                                  int outExt[6],
29                                                  int wExtent[6])
30 {
31   int idx;
32 
33   // initialize inExt
34   memcpy(inExt,wExtent,6*sizeof(int));
35 
36   // a simple approximation to the required extent
37   // basically get the whole extent for an axis unless a fully
38   // contained subset is being requested. If so then use that.
39   for (idx = 0; idx < 3; idx++)
40     {
41     if (outExt[idx*2] >= wExtent[idx*2] &&
42         outExt[idx*2+1] <= wExtent[idx*2+1])
43       {
44       inExt[idx*2] = outExt[idx*2];
45       inExt[idx*2+1] = outExt[idx*2+1];
46       }
47     }
48 }
49 
50 
51 //----------------------------------------------------------------------------
52 template <class T>
vtkImageMirrorPadExecute(vtkImageMirrorPad * self,vtkImageData * inData,int * wExtent,vtkImageData * outData,T * outPtr,int outExt[6],int id)53 void vtkImageMirrorPadExecute(vtkImageMirrorPad *self,
54                               vtkImageData *inData,
55                               int *wExtent,
56                               vtkImageData *outData, T *outPtr,
57                               int outExt[6], int id)
58 {
59   int idxC, idxX, idxY, idxZ;
60   int maxX, maxY, maxZ;
61   vtkIdType inInc[3];
62   int inIncStart[3];
63   vtkIdType inIncX, inIncY, inIncZ;
64   vtkIdType outIncX, outIncY, outIncZ;
65   unsigned long count = 0;
66   unsigned long target;
67   int idx;
68   int inIdxStart[3];
69   int inIdx[3];
70   T *inPtr, *inPtrX, *inPtrY, *inPtrZ;
71   int maxC, inMaxC;
72 
73   // find the region to loop over
74   inMaxC = inData->GetNumberOfScalarComponents();
75   maxC = outData->GetNumberOfScalarComponents();
76   maxX = outExt[1] - outExt[0];
77   maxY = outExt[3] - outExt[2];
78   maxZ = outExt[5] - outExt[4];
79   target = static_cast<unsigned long>((maxZ+1)*(maxY+1)/50.0);
80   target++;
81 
82   // Get increments to march through data
83   inData->GetIncrements(inIncX, inIncY, inIncZ);
84   outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ);
85 
86   // find the starting point
87   for (idx = 0; idx < 3; idx++)
88     {
89     inIdxStart[idx] = outExt[idx*2];
90     inIncStart[idx] = 1;
91     while (inIdxStart[idx] < wExtent[idx*2])
92       {
93       inIncStart[idx] = -inIncStart[idx];
94       inIdxStart[idx] = inIdxStart[idx] + (wExtent[idx*2+1] - wExtent[idx*2] + 1);
95       }
96     while (inIdxStart[idx] > wExtent[idx*2+1])
97       {
98       inIncStart[idx] = -inIncStart[idx];
99       inIdxStart[idx] = inIdxStart[idx] - (wExtent[idx*2+1] - wExtent[idx*2] + 1);
100       }
101     // if we are heading negative then we need to mirror the offset
102     if (inIncStart[idx] < 0)
103       {
104       inIdxStart[idx] = wExtent[idx*2+1] - inIdxStart[idx] + wExtent[idx*2];
105       }
106     }
107   inPtr = static_cast<T *>(inData->GetScalarPointer(inIdxStart[0], inIdxStart[1], inIdxStart[2]));
108 
109   // Loop through output pixels
110   inPtrZ = inPtr;
111   inIdx[2] = inIdxStart[2];
112   inInc[2] = inIncStart[2];
113   for (idxZ = 0; idxZ <= maxZ; idxZ++)
114     {
115     inPtrY = inPtrZ;
116     inIdx[1] = inIdxStart[1];
117     inInc[1] = inIncStart[1];
118     for (idxY = 0; !self->AbortExecute && idxY <= maxY; idxY++)
119       {
120       inPtrX = inPtrY;
121       inIdx[0] = inIdxStart[0];
122       inInc[0] = inIncStart[0];
123       if (!id)
124         {
125         if (!(count%target))
126           {
127           self->UpdateProgress(count/(50.0*target));
128           }
129         count++;
130         }
131 
132       // if components are same much faster
133       if ((maxC == inMaxC) && (maxC == 1))
134         {
135         for (idxX = 0; idxX <= maxX; idxX++)
136           {
137           // Pixel operation
138           *outPtr = *inPtrX;
139           outPtr++;
140           inIdx[0] += inInc[0];
141           inPtrX = inPtrX + inInc[0]*inIncX;
142           if (inIdx[0] < wExtent[0] || inIdx[0] > wExtent[1])
143             {
144             inInc[0] *= -1;
145             inIdx[0] += inInc[0];
146             inPtrX = inPtrX + inInc[0]*inIncX;
147             }
148           }
149         }
150       else // components are not the same
151         {
152         for (idxX = 0; idxX <= maxX; idxX++)
153           {
154           for (idxC = 0; idxC < maxC; idxC++)
155             {
156             // Pixel operation
157             if (idxC < inMaxC)
158               {
159               *outPtr = *(inPtrX + idxC);
160               }
161             else
162               {
163               *outPtr = *(inPtrX + idxC%inMaxC);
164               }
165             outPtr++;
166             }
167           inIdx[0] += inInc[0];
168           inPtrX = inPtrX + inInc[0]*inIncX;
169           if (inIdx[0] < wExtent[0] || inIdx[0] > wExtent[1])
170             {
171             inInc[0] *= -1;
172             inIdx[0] += inInc[0];
173             inPtrX = inPtrX + inInc[0]*inIncX;
174             }
175           }
176         }
177 
178       outPtr += outIncY;
179       inIdx[1] += inInc[1];
180       inPtrY = inPtrY + inInc[1]*inIncY;
181       if (inIdx[1] < wExtent[2] || inIdx[1] > wExtent[3])
182         {
183         inInc[1] *= -1;
184         inIdx[1] += inInc[1];
185         inPtrY = inPtrY + inInc[1]*inIncY;
186         }
187       }
188     outPtr += outIncZ;
189     inIdx[2] += inInc[2];
190     inPtrZ = inPtrZ + inInc[2]*inIncZ;
191     if (inIdx[2] < wExtent[4] || inIdx[2] > wExtent[5])
192       {
193       inInc[2] *= -1;
194       inIdx[2] += inInc[2];
195       inPtrZ = inPtrZ + inInc[2]*inIncZ;
196       }
197     }
198 }
199 
200 
201 
202 //----------------------------------------------------------------------------
203 // This method is passed a input and output data, and executes the filter
204 // algorithm to fill the output from the input.
205 // It just executes a switch statement to call the correct function for
206 // the regions data types.
ThreadedRequestData(vtkInformation * vtkNotUsed (request),vtkInformationVector ** inputVector,vtkInformationVector * vtkNotUsed (outputVector),vtkImageData *** inData,vtkImageData ** outData,int outExt[6],int id)207 void vtkImageMirrorPad::ThreadedRequestData(
208   vtkInformation * vtkNotUsed( request ),
209   vtkInformationVector** inputVector,
210   vtkInformationVector * vtkNotUsed( outputVector ),
211   vtkImageData ***inData,
212   vtkImageData **outData,
213   int outExt[6], int id)
214 {
215   // return if nothing to do
216   if (outExt[1] < outExt[0] ||
217       outExt[3] < outExt[2] ||
218       outExt[5] < outExt[4])
219     {
220     return;
221     }
222 
223   void *outPtr = outData[0]->GetScalarPointerForExtent(outExt);
224 
225    // get the whole extent
226   int wExt[6];
227   vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
228   inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),wExt);
229 
230   // this filter expects that input is the same type as output.
231   if (inData[0][0]->GetScalarType() != outData[0]->GetScalarType())
232     {
233     vtkErrorMacro(<< "Execute: input ScalarType, "
234                   << inData[0][0]->GetScalarType()
235                   << ", must match out ScalarType "
236                   << outData[0]->GetScalarType());
237     return;
238     }
239 
240   switch (inData[0][0]->GetScalarType())
241     {
242     vtkTemplateMacro(
243       vtkImageMirrorPadExecute(this, inData[0][0], wExt,
244                                outData[0], static_cast<VTK_TT *>(outPtr),
245                                outExt, id));
246     default:
247       vtkErrorMacro(<< "Execute: Unknown ScalarType");
248       return;
249     }
250 }
251 
252 
253 
254 
255 
256 
257