Cloned library of VTK-5.0.0 with extra build files for internal package management.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

338 lines
11 KiB

/*=========================================================================
Program: Visualization Toolkit
Module: $RCSfile: vtkImageMagnify.cxx,v $
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#include "vtkImageMagnify.h"
#include "vtkImageData.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include "vtkStreamingDemandDrivenPipeline.h"
vtkCxxRevisionMacro(vtkImageMagnify, "$Revision: 1.50 $");
vtkStandardNewMacro(vtkImageMagnify);
//----------------------------------------------------------------------------
// Constructor: Sets default filter to be identity.
vtkImageMagnify::vtkImageMagnify()
{
this->Interpolate = 0;
this->MagnificationFactors[0] =
this->MagnificationFactors[1] =
this->MagnificationFactors[2] = 1;
}
//----------------------------------------------------------------------------
// Computes any global image information associated with regions.
int vtkImageMagnify::RequestInformation (
vtkInformation * vtkNotUsed(request),
vtkInformationVector **inputVector,
vtkInformationVector *outputVector)
{
// get the info objects
vtkInformation* outInfo = outputVector->GetInformationObject(0);
vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
double spacing[3];
int idx;
double outSpacing[3];
int inExt[6], outExt[6];
inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), inExt);
inInfo->Get(vtkDataObject::SPACING(), spacing);
for (idx = 0; idx < 3; idx++)
{
// Scale the output extent
outExt[idx*2] = inExt[idx*2] * this->MagnificationFactors[idx];
outExt[idx*2+1] = outExt[idx*2] +
(inExt[idx*2+1] - inExt[idx*2] + 1)*this->MagnificationFactors[idx] - 1;
// Change the data spacing
outSpacing[idx] = spacing[idx] / (double)(this->MagnificationFactors[idx]);
}
outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),outExt,6);
outInfo->Set(vtkDataObject::SPACING(),outSpacing,3);
return 1;
}
//----------------------------------------------------------------------------
// This method computes the Region of input necessary to generate outRegion.
// It assumes offset and size are multiples of Magnify Factors.
int vtkImageMagnify::RequestUpdateExtent (
vtkInformation * vtkNotUsed(request),
vtkInformationVector **inputVector,
vtkInformationVector *outputVector)
{
// get the info objects
vtkInformation* outInfo = outputVector->GetInformationObject(0);
vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
int outExt[6], inExt[6];
outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), outExt);
this->InternalRequestUpdateExtent(inExt, outExt);
inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), inExt, 6);
return 1;
}
void vtkImageMagnify::InternalRequestUpdateExtent(int *inExt, int *outExt)
{
int idx;
for (idx = 0; idx < 3; idx++)
{
// For Min. Round Down
inExt[idx*2] = (int)(floor((double)(outExt[idx*2]) /
(double)(this->MagnificationFactors[idx])));
inExt[idx*2+1] = (int)(floor((double)(outExt[idx*2+1]) /
(double)(this->MagnificationFactors[idx])));
}
}
//----------------------------------------------------------------------------
// The templated execute function handles all the data types.
// 2d even though operation is 1d.
// Note: Slight misalignment (pixel replication is not nearest neighbor).
template <class T>
void vtkImageMagnifyExecute(vtkImageMagnify *self,
vtkImageData *inData, T *inPtr, int inExt[6],
vtkImageData *outData, T *outPtr,
int outExt[6], int id)
{
int idxC, idxX, idxY, idxZ;
int inIdxX, inIdxY, inIdxZ;
int inMaxX, inMaxY, inMaxZ;
int maxC, maxX, maxY, maxZ;
vtkIdType inIncX, inIncY, inIncZ;
vtkIdType outIncX, outIncY, outIncZ;
unsigned long count = 0;
unsigned long target;
int interpolate;
int magXIdx, magX;
int magYIdx, magY;
int magZIdx, magZ;
T *inPtrZ, *inPtrY, *inPtrX, *outPtrC;
double iMag, iMagP = 0.0, iMagPY = 0.0, iMagPZ = 0.0, iMagPYZ = 0.0;
T dataP = 0, dataPX = 0, dataPY = 0, dataPZ = 0;
T dataPXY = 0, dataPXZ = 0, dataPYZ = 0, dataPXYZ = 0;
int interpSetup;
interpolate = self->GetInterpolate();
magX = self->GetMagnificationFactors()[0];
magY = self->GetMagnificationFactors()[1];
magZ = self->GetMagnificationFactors()[2];
iMag = 1.0/(magX*magY*magZ);
// find the region to loop over
maxC = outData->GetNumberOfScalarComponents();
maxX = outExt[1] - outExt[0];
maxY = outExt[3] - outExt[2];
maxZ = outExt[5] - outExt[4];
target = (unsigned long)(maxC*(maxZ+1)*(maxY+1)/50.0);
target++;
// Get increments to march through data
inData->GetIncrements(inIncX, inIncY, inIncZ);
outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ);
// Now I am putting in my own boundary check because of ABRs and FMRs
// And I do not understand (nor do I care to figure out) what
// Ken is doing with his checks. (Charles)
inMaxX = inExt[1];
inMaxY = inExt[3];
inMaxZ = inExt[5];
inData->GetExtent(idxC, inMaxX, idxC, inMaxY, idxC, inMaxZ);
// Loop through ouput pixels
for (idxC = 0; idxC < maxC; idxC++)
{
inPtrZ = inPtr + idxC;
inIdxZ = inExt[4];
outPtrC = outPtr + idxC;
magZIdx = magZ - outExt[4]%magZ - 1;
for (idxZ = 0; idxZ <= maxZ; idxZ++, magZIdx--)
{
inPtrY = inPtrZ;
inIdxY = inExt[2];
magYIdx = magY - outExt[2]%magY - 1;
for (idxY = 0; !self->AbortExecute && idxY <= maxY; idxY++, magYIdx--)
{
if (!id)
{
if (!(count%target))
{
self->UpdateProgress(count/(50.0*target));
}
count++;
}
if (interpolate)
{
// precompute some values for interpolation
iMagP = (magYIdx + 1)*(magZIdx + 1)*iMag;
iMagPY = (magY - magYIdx - 1)*(magZIdx + 1)*iMag;
iMagPZ = (magYIdx + 1)*(magZ - magZIdx - 1)*iMag;
iMagPYZ = (magY - magYIdx - 1)*(magZ - magZIdx - 1)*iMag;
}
magXIdx = magX - outExt[0]%magX - 1;
inPtrX = inPtrY;
inIdxX = inExt[0];
interpSetup = 0;
for (idxX = 0; idxX <= maxX; idxX++, magXIdx--)
{
// Pixel operation
if (!interpolate)
{
*outPtrC = *inPtrX;
}
else
{
// setup data values for interp, overload dataP as an
// indicator of if this has been done yet
if (!interpSetup)
{
int tiX, tiY, tiZ;
dataP = *inPtrX;
// Now I am putting in my own boundary check because of
// ABRs and FMRs
// And I do not understand (nor do I care to figure out) what
// Ken was doing with his checks. (Charles)
if (inIdxX < inMaxX)
{
tiX = inIncX;
}
else
{
tiX = 0;
}
if (inIdxY < inMaxY)
{
tiY = inIncY;
}
else
{
tiY = 0;
}
if (inIdxZ < inMaxZ)
{
tiZ = inIncZ;
}
else
{
tiZ = 0;
}
dataPX = *(inPtrX + tiX);
dataPY = *(inPtrX + tiY);
dataPZ = *(inPtrX + tiZ);
dataPXY = *(inPtrX + tiX + tiY);
dataPXZ = *(inPtrX + tiX + tiZ);
dataPYZ = *(inPtrX + tiY + tiZ);
dataPXYZ = *(inPtrX + tiX + tiY + tiZ);
interpSetup = 1;
}
*outPtrC = (T)
((double)dataP*(magXIdx + 1)*iMagP +
(double)dataPX*(magX - magXIdx - 1)*iMagP +
(double)dataPY*(magXIdx + 1)*iMagPY +
(double)dataPXY*(magX - magXIdx - 1)*iMagPY +
(double)dataPZ*(magXIdx + 1)*iMagPZ +
(double)dataPXZ*(magX - magXIdx - 1)*iMagPZ +
(double)dataPYZ*(magXIdx + 1)*iMagPYZ +
(double)dataPXYZ*(magX - magXIdx - 1)*iMagPYZ);
}
outPtrC += maxC;
if (!magXIdx)
{
inPtrX += inIncX;
++inIdxX;
magXIdx = magX;
interpSetup = 0;
}
}
outPtrC += outIncY;
if (!magYIdx)
{
inPtrY += inIncY;
++inIdxY;
magYIdx = magY;
}
}
outPtrC += outIncZ;
if (!magZIdx)
{
inPtrZ += inIncZ;
++inIdxZ;
magZIdx = magZ;
}
}
}
}
void vtkImageMagnify::ThreadedRequestData(
vtkInformation *vtkNotUsed(request),
vtkInformationVector **vtkNotUsed(inputVector),
vtkInformationVector *vtkNotUsed(outputVector),
vtkImageData ***inData,
vtkImageData **outData,
int outExt[6], int id)
{
int inExt[6];
this->InternalRequestUpdateExtent(inExt, outExt);
void *inPtr = inData[0][0]->GetScalarPointerForExtent(inExt);
void *outPtr = outData[0]->GetScalarPointerForExtent(outExt);
// this filter expects that input is the same type as output.
if (inData[0][0]->GetScalarType() != outData[0]->GetScalarType())
{
vtkErrorMacro("Execute: input ScalarType, "
<< inData[0][0]->GetScalarType()
<< ", must match out ScalarType "
<< outData[0]->GetScalarType());
return;
}
switch (inData[0][0]->GetScalarType())
{
vtkTemplateMacro(
vtkImageMagnifyExecute( this, inData[0][0],
(VTK_TT *)(inPtr), inExt, outData[0],
(VTK_TT *)(outPtr),
outExt, id));
default:
vtkErrorMacro(<< "Execute: Unknown ScalarType");
return;
}
}
void vtkImageMagnify::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
os << indent << "MagnificationFactors: ( "
<< this->MagnificationFactors[0] << ", "
<< this->MagnificationFactors[1] << ", "
<< this->MagnificationFactors[2] << " )\n";
os << indent << "Interpolate: " << (this->Interpolate ? "On\n" : "Off\n");
}