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