1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkImageResample.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 "vtkImageResample.h"
16 
17 #include "vtkAlgorithmOutput.h"
18 #include "vtkImageData.h"
19 #include "vtkInformation.h"
20 #include "vtkInformationVector.h"
21 #include "vtkObjectFactory.h"
22 #include "vtkStreamingDemandDrivenPipeline.h"
23 
24 vtkStandardNewMacro(vtkImageResample);
25 
26 //----------------------------------------------------------------------------
27 // Constructor: Sets default filter to be identity.
vtkImageResample()28 vtkImageResample::vtkImageResample()
29 {
30   this->MagnificationFactors[0] = 1.0;
31   this->MagnificationFactors[1] = 1.0;
32   this->MagnificationFactors[2] = 1.0;
33   this->OutputSpacing[0] = 0.0; // not specified
34   this->OutputSpacing[1] = 0.0; // not specified
35   this->OutputSpacing[2] = 0.0; // not specified
36   this->InterpolationMode = VTK_RESLICE_LINEAR;
37   this->Dimensionality = 3;
38 }
39 
40 //----------------------------------------------------------------------------
SetOutputSpacing(double sx,double sy,double sz)41 void vtkImageResample::SetOutputSpacing(double sx, double sy, double sz)
42 {
43   const double spacing[3] = { sx, sy, sz };
44   bool modified = false;
45 
46   for (int axis = 0; axis < 3; axis++)
47   {
48     if (this->OutputSpacing[axis] != spacing[axis])
49     {
50       this->OutputSpacing[axis] = spacing[axis];
51       if (spacing[axis] != 0.0)
52       {
53         // Delay computing the magnification factor.
54         // Input might not be set yet.
55         this->MagnificationFactors[axis] = 0.0; // Not computed yet.
56       }
57       modified = true;
58     }
59   }
60 
61   if (modified)
62   {
63     this->Modified();
64   }
65 }
66 
67 //----------------------------------------------------------------------------
SetAxisOutputSpacing(int axis,double s)68 void vtkImageResample::SetAxisOutputSpacing(int axis, double s)
69 {
70   if (axis < 0 || axis > 2)
71   {
72     vtkErrorMacro("Bad axis: " << axis);
73     return;
74   }
75 
76   double spacing[3];
77   this->GetOutputSpacing(spacing);
78   spacing[axis] = s;
79 
80   this->SetOutputSpacing(spacing);
81 }
82 
83 //----------------------------------------------------------------------------
SetMagnificationFactors(double fx,double fy,double fz)84 void vtkImageResample::SetMagnificationFactors(double fx, double fy, double fz)
85 {
86   const double factors[3] = { fx, fy, fz };
87   bool modified = false;
88 
89   for (int axis = 0; axis < 3; axis++)
90   {
91     if (this->MagnificationFactors[axis] != factors[axis])
92     {
93       this->MagnificationFactors[axis] = factors[axis];
94       // Spacing is no longer valid.
95       this->OutputSpacing[axis] = 0.0; // Not computed yet.
96       modified = true;
97     }
98   }
99 
100   if (modified)
101   {
102     this->Modified();
103   }
104 }
105 
106 //----------------------------------------------------------------------------
SetAxisMagnificationFactor(int axis,double factor)107 void vtkImageResample::SetAxisMagnificationFactor(int axis, double factor)
108 {
109   if (axis < 0 || axis > 2)
110   {
111     vtkErrorMacro("Bad axis: " << axis);
112     return;
113   }
114 
115   double factors[3];
116   this->GetMagnificationFactors(factors);
117   factors[axis] = factor;
118 
119   this->SetMagnificationFactors(factors);
120 }
121 
122 //----------------------------------------------------------------------------
GetAxisMagnificationFactor(int axis,vtkInformation * inInfo)123 double vtkImageResample::GetAxisMagnificationFactor(int axis,
124                                                     vtkInformation *inInfo)
125 {
126   if (axis < 0 || axis > 2)
127   {
128     vtkErrorMacro("Bad axis: " << axis);
129     return 0.0;
130   }
131 
132   if (this->MagnificationFactors[axis] == 0.0)
133   {
134     double *inputSpacing;
135     if ( ! this->GetInput())
136     {
137       vtkErrorMacro("GetMagnificationFactor: Input not set.");
138       return 0.0;
139     }
140     this->GetInputConnection(0, 0)->GetProducer()->UpdateInformation();
141     if (!inInfo)
142     {
143       inInfo = this->GetExecutive()->GetInputInformation(0, 0);
144     }
145     inputSpacing = inInfo->Get(vtkDataObject::SPACING());
146     this->MagnificationFactors[axis] =
147       inputSpacing[axis] / this->OutputSpacing[axis];
148 
149   }
150 
151   vtkDebugMacro("Returning magnification factor "
152                 <<  this->MagnificationFactors[axis] << " for axis "
153                 << axis);
154 
155   return this->MagnificationFactors[axis];
156 }
157 
158 
159 //----------------------------------------------------------------------------
160 // Computes any global image information associated with regions.
RequestInformation(vtkInformation * vtkNotUsed (request),vtkInformationVector ** inputVector,vtkInformationVector * outputVector)161 int vtkImageResample::RequestInformation(
162   vtkInformation *vtkNotUsed(request),
163   vtkInformationVector **inputVector,
164   vtkInformationVector *outputVector)
165 {
166   int wholeMin, wholeMax, axis, ext[6];
167   double spacing[3], factor;
168 
169   vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
170   vtkInformation *outInfo = outputVector->GetInformationObject(0);
171 
172   inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), ext);
173   inInfo->Get(vtkDataObject::SPACING(), spacing);
174 
175   for (axis = 0; axis < 3; axis++)
176   {
177     wholeMin = ext[axis*2];
178     wholeMax = ext[axis*2+1];
179 
180     // Scale the output extent
181     factor = 1.0;
182     if (axis < this->Dimensionality)
183     {
184       factor = this->GetAxisMagnificationFactor(axis, inInfo);
185     }
186 
187     wholeMin = static_cast<int>(ceil(static_cast<double>(wholeMin) * factor));
188     wholeMax = static_cast<int>(floor(static_cast<double>(wholeMax) * factor));
189 
190     // Change the data spacing
191     spacing[axis] /= factor;
192 
193     ext[axis*2] = wholeMin;
194     ext[axis*2+1] = wholeMax;
195 
196     // just in case the input spacing has changed.
197     if (this->OutputSpacing[axis] != 0.0)
198     {
199       // Cause MagnificationFactor to recompute.
200       this->MagnificationFactors[axis] = 0.0;
201     }
202   }
203 
204   outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), ext, 6);
205   outInfo->Set(vtkDataObject::SPACING(), spacing, 3);
206 
207   return 1;
208 }
209 
PrintSelf(ostream & os,vtkIndent indent)210 void vtkImageResample::PrintSelf(ostream& os, vtkIndent indent)
211 {
212   this->Superclass::PrintSelf(os,indent);
213   os << indent << "MagnificationFactors: " << this->MagnificationFactors[0]
214      << " " << this->MagnificationFactors[1]
215      << " " << this->MagnificationFactors[2] << "\n";
216   os << indent << "Dimensionality: " << this->Dimensionality << "\n";
217   os << indent << "Interpolate: " << (this->GetInterpolate() ? "On\n" : "Off\n");
218 }
219