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.
 
 
 
 
 
 

408 lines
12 KiB

/*=========================================================================
Program: Visualization Toolkit
Module: $RCSfile: vtkImageStencil.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 "vtkImageStencil.h"
#include "vtkImageData.h"
#include "vtkImageStencilData.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include "vtkStreamingDemandDrivenPipeline.h"
#include <math.h>
vtkCxxRevisionMacro(vtkImageStencil, "$Revision: 1.21 $");
vtkStandardNewMacro(vtkImageStencil);
//----------------------------------------------------------------------------
vtkImageStencil::vtkImageStencil()
{
this->ReverseStencil = 0;
this->BackgroundColor[0] = 1;
this->BackgroundColor[1] = 1;
this->BackgroundColor[2] = 1;
this->BackgroundColor[3] = 1;
this->SetNumberOfInputPorts(3);
}
//----------------------------------------------------------------------------
vtkImageStencil::~vtkImageStencil()
{
}
//----------------------------------------------------------------------------
void vtkImageStencil::SetStencil(vtkImageStencilData *stencil)
{
this->SetInput(2, stencil);
}
//----------------------------------------------------------------------------
vtkImageStencilData *vtkImageStencil::GetStencil()
{
if (this->GetNumberOfInputConnections(2) < 1)
{
return NULL;
}
else
{
return vtkImageStencilData::SafeDownCast(
this->GetExecutive()->GetInputData(2, 0));
}
}
//----------------------------------------------------------------------------
void vtkImageStencil::SetBackgroundInput(vtkImageData *data)
{
this->SetInput(1, data);
}
//----------------------------------------------------------------------------
vtkImageData *vtkImageStencil::GetBackgroundInput()
{
if (this->GetNumberOfInputConnections(1) < 1)
{
return NULL;
}
else
{
return vtkImageData::SafeDownCast(
this->GetExecutive()->GetInputData(1, 0));
}
}
//----------------------------------------------------------------------------
int vtkImageStencil::RequestInformation (
vtkInformation * vtkNotUsed(request),
vtkInformationVector **inputVector,
vtkInformationVector *vtkNotUsed(outputVector))
{
// get the info object
vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
// need to set the spacing and origin of the stencil to match the output
vtkImageStencilData *stencil = this->GetStencil();
if (stencil)
{
stencil->SetSpacing(inInfo->Get(vtkDataObject::SPACING()));
stencil->SetOrigin(inInfo->Get(vtkDataObject::ORIGIN()));
}
return 1;
}
//----------------------------------------------------------------------------
// Some helper functions for 'ThreadedRequestData'
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
// copy a pixel, advance the output pointer but not the input pointer
template<class T>
inline void vtkCopyPixel(T *&out, const T *in, int numscalars)
{
do
{
*out++ = *in++;
}
while (--numscalars);
}
//----------------------------------------------------------------------------
// Convert background color from double to appropriate type
template <class T>
void vtkAllocBackground(vtkImageStencil *self, T *&background,
vtkInformation *outInfo)
{
vtkImageData *output = vtkImageData::SafeDownCast(
outInfo->Get(vtkDataObject::DATA_OBJECT()));
int numComponents = output->GetNumberOfScalarComponents();
int scalarType = output->GetScalarType();
background = new T[numComponents];
for (int i = 0; i < numComponents; i++)
{
if (i < 4)
{
if (scalarType == VTK_FLOAT || scalarType == VTK_DOUBLE)
{
background[i] = (T)self->GetBackgroundColor()[i];
}
else
{ // round float to nearest int
background[i] = (T)floor(self->GetBackgroundColor()[i] + 0.5);
}
}
else
{ // all values past 4 are set to zero
background[i] = 0;
}
}
}
//----------------------------------------------------------------------------
template <class T>
void vtkFreeBackground(vtkImageStencil *vtkNotUsed(self), T *&background)
{
delete [] background;
background = NULL;
}
//----------------------------------------------------------------------------
template <class T>
void vtkImageStencilExecute(vtkImageStencil *self,
vtkImageData *inData, T *inPtr,
vtkImageData *in2Data,T *in2Ptr,
vtkImageData *outData, T *outPtr,
int outExt[6], int id,
vtkInformation *outInfo)
{
int numscalars, inIncX;
int idX, idY, idZ;
int r1, r2, cr1, cr2, iter, rval;
vtkIdType outIncX, outIncY, outIncZ;
int inExt[6];
vtkIdType inInc[3];
int in2Ext[6];
vtkIdType in2Inc[3];
unsigned long count = 0;
unsigned long target;
T *background, *tempPtr;
// get the clipping extents
vtkImageStencilData *stencil = self->GetStencil();
// find maximum input range
inData->GetExtent(inExt);
inData->GetIncrements(inInc);
if (in2Data)
{
in2Data->GetExtent(in2Ext);
in2Data->GetIncrements(in2Inc);
}
// Get Increments to march through data
outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ);
numscalars = inData->GetNumberOfScalarComponents();
target = (unsigned long)
((outExt[5]-outExt[4]+1)*(outExt[3]-outExt[2]+1)/50.0);
target++;
// set color for area outside of input volume extent
vtkAllocBackground(self, background, outInfo);
// Loop through output pixels
for (idZ = outExt[4]; idZ <= outExt[5]; idZ++)
{
for (idY = outExt[2]; idY <= outExt[3]; idY++)
{
if (!id)
{
if (!(count%target))
{
self->UpdateProgress(count/(50.0*target));
}
count++;
}
iter = 0;
if (self->GetReverseStencil())
{ // flag that we want the complementary extents
iter = -1;
}
cr1 = outExt[0];
for (;;)
{
rval = 0;
r1 = outExt[1] + 1;
r2 = outExt[1];
if (stencil)
{
rval = stencil->GetNextExtent(r1, r2, outExt[0], outExt[1],
idY, idZ, iter);
}
else if (iter < 0)
{
r1 = outExt[0];
r2 = outExt[1];
rval = 1;
iter = 1;
}
tempPtr = background;
inIncX = 0;
if (in2Ptr)
{
tempPtr = in2Ptr + (in2Inc[2]*(idZ - in2Ext[4]) +
in2Inc[1]*(idY - in2Ext[2]) +
numscalars*(cr1 - in2Ext[0]));
inIncX = numscalars;
}
cr2 = r1 - 1;
for (idX = cr1; idX <= cr2; idX++)
{
vtkCopyPixel(outPtr, tempPtr, numscalars);
tempPtr += inIncX;
}
cr1 = r2 + 1; // for next time 'round
// break if no foreground extents left
if (rval == 0)
{
break;
}
tempPtr = inPtr + (inInc[2]*(idZ - inExt[4]) +
inInc[1]*(idY - inExt[2]) +
numscalars*(r1 - inExt[0]));
for (idX = r1; idX <= r2; idX++)
{
vtkCopyPixel(outPtr, tempPtr, numscalars);
tempPtr += numscalars;
}
}
outPtr += outIncY;
}
outPtr += outIncZ;
}
vtkFreeBackground(self, background);
}
//----------------------------------------------------------------------------
void vtkImageStencil::ThreadedRequestData(
vtkInformation *vtkNotUsed(request),
vtkInformationVector **inputVector,
vtkInformationVector *outputVector,
vtkImageData ***inData,
vtkImageData **outData,
int outExt[6], int id)
{
void *inPtr, *inPtr2;
void *outPtr;
vtkImageData *inData2 = this->GetBackgroundInput();
inPtr = inData[0][0]->GetScalarPointer();
outPtr = outData[0]->GetScalarPointerForExtent(outExt);
vtkInformation *outInfo = outputVector->GetInformationObject(0);
inPtr2 = NULL;
if (inData2)
{
inPtr2 = inData2->GetScalarPointer();
if (inData2->GetScalarType() != inData[0][0]->GetScalarType())
{
if (id == 0)
{
vtkErrorMacro("Execute: BackgroundInput ScalarType "
<< inData2->GetScalarType()
<< ", must match Input ScalarType "
<< inData[0][0]->GetScalarType());
}
return;
}
else if (inData2->GetNumberOfScalarComponents()
!= inData[0][0]->GetNumberOfScalarComponents())
{
if (id == 0)
{
vtkErrorMacro("Execute: BackgroundInput NumberOfScalarComponents "
<< inData2->GetNumberOfScalarComponents()
<< ", must match Input NumberOfScalarComponents "
<< inData[0][0]->GetNumberOfScalarComponents());
}
return;
}
int wholeExt1[6], wholeExt2[6];
vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
vtkInformation *inInfo2 = inputVector[1]->GetInformationObject(0);
inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),wholeExt1);
inInfo2->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),wholeExt2);
for (int i = 0; i < 6; i++)
{
if (wholeExt1[i] != wholeExt2[i])
{
if (id == 0)
{
vtkErrorMacro("Execute: BackgroundInput must have the same "
"WholeExtent as the Input");
}
return;
}
}
}
switch (inData[0][0]->GetScalarType())
{
vtkTemplateMacro(
vtkImageStencilExecute( this,
inData[0][0],
(VTK_TT *)(inPtr),
inData2,
(VTK_TT *)(inPtr2),
outData[0],
(VTK_TT *)(outPtr),
outExt,
id,
outInfo) );
default:
vtkErrorMacro("Execute: Unknown ScalarType");
return;
}
}
//----------------------------------------------------------------------------
int vtkImageStencil::FillInputPortInformation(int port, vtkInformation* info)
{
if (port == 2)
{
info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageStencilData");
info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1);
}
else
{
info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageData");
if (port == 1)
{
info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1);
}
}
return 1;
}
void vtkImageStencil::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
os << indent << "Stencil: " << this->GetStencil() << "\n";
os << indent << "ReverseStencil: " << (this->ReverseStencil ?
"On\n" : "Off\n");
os << indent << "BackgroundInput: " << this->GetBackgroundInput() << "\n";
os << indent << "BackgroundValue: " << this->BackgroundColor[0] << "\n";
os << indent << "BackgroundColor: (" << this->BackgroundColor[0] << ", "
<< this->BackgroundColor[1] << ", "
<< this->BackgroundColor[2] << ", "
<< this->BackgroundColor[3] << ")\n";
}