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.
329 lines
9.2 KiB
329 lines
9.2 KiB
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: $RCSfile: vtkImageMask.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 "vtkImageMask.h"
|
|
|
|
#include "vtkImageData.h"
|
|
#include "vtkInformation.h"
|
|
#include "vtkInformationVector.h"
|
|
#include "vtkObjectFactory.h"
|
|
#include "vtkStreamingDemandDrivenPipeline.h"
|
|
|
|
vtkCxxRevisionMacro(vtkImageMask, "$Revision: 1.39 $");
|
|
vtkStandardNewMacro(vtkImageMask);
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkImageMask::vtkImageMask()
|
|
{
|
|
this->NotMask = 0;
|
|
this->MaskedOutputValue = new double[3];
|
|
this->MaskedOutputValueLength = 3;
|
|
this->MaskedOutputValue[0] = this->MaskedOutputValue[1]
|
|
= this->MaskedOutputValue[2] = 0.0;
|
|
this->MaskAlpha = 1.0;
|
|
this->SetNumberOfInputPorts(2);
|
|
}
|
|
|
|
vtkImageMask::~vtkImageMask()
|
|
{
|
|
delete [] this->MaskedOutputValue;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkImageMask::SetImageInput(vtkImageData *in)
|
|
{
|
|
this->SetInput1(in);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkImageMask::SetMaskInput(vtkImageData *in)
|
|
{
|
|
this->SetInput2(in);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkImageMask::SetMaskedOutputValue(int num, double *v)
|
|
{
|
|
int idx;
|
|
|
|
if (num < 1)
|
|
{
|
|
vtkErrorMacro("Output value must have length greater than 0");
|
|
return;
|
|
}
|
|
if (num != this->MaskedOutputValueLength)
|
|
{
|
|
this->Modified();
|
|
}
|
|
|
|
if (num > this->MaskedOutputValueLength)
|
|
{
|
|
delete [] this->MaskedOutputValue;
|
|
this->MaskedOutputValue = new double[num];
|
|
this->MaskedOutputValueLength = num;
|
|
}
|
|
|
|
this->MaskedOutputValueLength = num;
|
|
for (idx = 0; idx < num; ++ idx)
|
|
{
|
|
if (this->MaskedOutputValue[idx] != v[idx])
|
|
{
|
|
this->Modified();
|
|
}
|
|
this->MaskedOutputValue[idx] = v[idx];
|
|
}
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// This templated function executes the filter for any type of data.
|
|
template <class T>
|
|
void vtkImageMaskExecute(vtkImageMask *self, int ext[6],
|
|
vtkImageData *in1Data, T *in1Ptr,
|
|
vtkImageData *in2Data, unsigned char *in2Ptr,
|
|
vtkImageData *outData, T *outPtr, int id)
|
|
{
|
|
int num0, num1, num2, numC, pixSize;
|
|
int idx0, idx1, idx2, idxC;
|
|
vtkIdType in1Inc0, in1Inc1, in1Inc2;
|
|
vtkIdType in2Inc0, in2Inc1, in2Inc2;
|
|
vtkIdType outInc0, outInc1, outInc2;
|
|
T *maskedValue;
|
|
double *v;
|
|
int nv;
|
|
int maskState;
|
|
double maskAlpha, oneMinusMaskAlpha;
|
|
unsigned long count = 0;
|
|
unsigned long target;
|
|
|
|
// create a masked output value with the correct length by cycling
|
|
numC = outData->GetNumberOfScalarComponents();
|
|
maskedValue = new T[numC];
|
|
v = self->GetMaskedOutputValue();
|
|
nv = self->GetMaskedOutputValueLength();
|
|
for (idx0 = 0, idx1 = 0; idx0 < numC; ++idx0, ++idx1)
|
|
{
|
|
if (idx1 >= nv)
|
|
{
|
|
idx1 = 0;
|
|
}
|
|
maskedValue[idx0] = (T)(v[idx1]);
|
|
}
|
|
pixSize = numC * sizeof(T);
|
|
maskState = self->GetNotMask();
|
|
maskAlpha = self->GetMaskAlpha();
|
|
oneMinusMaskAlpha = 1.0 - maskAlpha;
|
|
|
|
// Get information to march through data
|
|
in1Data->GetContinuousIncrements(ext, in1Inc0, in1Inc1, in1Inc2);
|
|
in2Data->GetContinuousIncrements(ext, in2Inc0, in2Inc1, in2Inc2);
|
|
outData->GetContinuousIncrements(ext, outInc0, outInc1, outInc2);
|
|
num0 = ext[1] - ext[0] + 1;
|
|
num1 = ext[3] - ext[2] + 1;
|
|
num2 = ext[5] - ext[4] + 1;
|
|
|
|
target = (unsigned long)(num2*num1/50.0);
|
|
target++;
|
|
|
|
// Loop through ouput pixels
|
|
for (idx2 = 0; idx2 < num2; ++idx2)
|
|
{
|
|
for (idx1 = 0; !self->AbortExecute && idx1 < num1; ++idx1)
|
|
{
|
|
if (!id)
|
|
{
|
|
if (!(count%target))
|
|
{
|
|
self->UpdateProgress(count/(50.0*target));
|
|
}
|
|
count++;
|
|
}
|
|
for (idx0 = 0; idx0 < num0; ++idx0)
|
|
{
|
|
if ( maskAlpha == 1.0 )
|
|
{
|
|
// Pixel operation
|
|
if (*in2Ptr && maskState == 1)
|
|
{
|
|
memcpy(outPtr, maskedValue, pixSize);
|
|
}
|
|
else if ( ! *in2Ptr && maskState == 0)
|
|
{
|
|
memcpy(outPtr, maskedValue, pixSize);
|
|
}
|
|
else
|
|
{
|
|
memcpy(outPtr, in1Ptr, pixSize);
|
|
}
|
|
in1Ptr += numC;
|
|
outPtr += numC;
|
|
}
|
|
else
|
|
{
|
|
// We need to do an over operation
|
|
int doMask = 0;
|
|
if ( *in2Ptr && maskState == 1 )
|
|
{
|
|
doMask = 1;
|
|
}
|
|
else if ( !*in2Ptr && maskState == 0 )
|
|
{
|
|
doMask = 1;
|
|
}
|
|
if ( doMask )
|
|
{
|
|
// Do an over operation
|
|
for ( idxC = 0; idxC < numC; ++idxC )
|
|
{
|
|
*outPtr = (T) ( oneMinusMaskAlpha * *in1Ptr + maskedValue[idxC] * maskAlpha );
|
|
++outPtr;
|
|
++in1Ptr;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Copy verbatum
|
|
for ( idxC = 0; idxC < numC; ++idxC )
|
|
{
|
|
*outPtr = *in1Ptr;
|
|
++outPtr;
|
|
++in1Ptr;
|
|
}
|
|
}
|
|
}
|
|
in2Ptr += 1;
|
|
}
|
|
in1Ptr += in1Inc1;
|
|
in2Ptr += in2Inc1;
|
|
outPtr += outInc1;
|
|
}
|
|
in1Ptr += in1Inc2;
|
|
in2Ptr += in2Inc2;
|
|
outPtr += outInc2;
|
|
}
|
|
|
|
delete [] maskedValue;
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// This method is passed a input and output Datas, and executes the filter
|
|
// algorithm to fill the output from the inputs.
|
|
// It just executes a switch statement to call the correct function for
|
|
// the Datas data types.
|
|
void vtkImageMask::ThreadedRequestData(
|
|
vtkInformation * vtkNotUsed( request ),
|
|
vtkInformationVector ** vtkNotUsed( inputVector ),
|
|
vtkInformationVector * vtkNotUsed( outputVector ),
|
|
vtkImageData ***inData,
|
|
vtkImageData **outData,
|
|
int outExt[6], int id)
|
|
{
|
|
void *inPtr1;
|
|
void *inPtr2;
|
|
void *outPtr;
|
|
int *tExt;
|
|
|
|
inPtr1 = inData[0][0]->GetScalarPointerForExtent(outExt);
|
|
inPtr2 = inData[1][0]->GetScalarPointerForExtent(outExt);
|
|
outPtr = outData[0]->GetScalarPointerForExtent(outExt);
|
|
|
|
tExt = inData[1][0]->GetExtent();
|
|
if (tExt[0] > outExt[0] || tExt[1] < outExt[1] ||
|
|
tExt[2] > outExt[2] || tExt[3] < outExt[3] ||
|
|
tExt[4] > outExt[4] || tExt[5] < outExt[5])
|
|
{
|
|
vtkErrorMacro("Mask extent not large enough");
|
|
return;
|
|
}
|
|
|
|
if (inData[1][0]->GetNumberOfScalarComponents() != 1)
|
|
{
|
|
vtkErrorMacro("Maks can have one comenent");
|
|
}
|
|
|
|
if (inData[0][0]->GetScalarType() != outData[0]->GetScalarType() ||
|
|
inData[1][0]->GetScalarType() != VTK_UNSIGNED_CHAR)
|
|
{
|
|
vtkErrorMacro(<< "Execute: image ScalarType ("
|
|
<< inData[0][0]->GetScalarType() << ") must match out ScalarType ("
|
|
<< outData[0]->GetScalarType() << "), and mask scalar type ("
|
|
<< inData[1][0]->GetScalarType() << ") must be unsigned char.");
|
|
return;
|
|
}
|
|
|
|
switch (inData[0][0]->GetScalarType())
|
|
{
|
|
vtkTemplateMacro(
|
|
vtkImageMaskExecute(this, outExt, inData[0][0],
|
|
(VTK_TT *)(inPtr1), inData[1][0],
|
|
(unsigned char *)(inPtr2),
|
|
outData[0], (VTK_TT *)(outPtr),id));
|
|
default:
|
|
vtkErrorMacro(<< "Execute: Unknown ScalarType");
|
|
return;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// The output extent is the intersection.
|
|
int vtkImageMask::RequestInformation (
|
|
vtkInformation * vtkNotUsed(request),
|
|
vtkInformationVector **inputVector,
|
|
vtkInformationVector *outputVector)
|
|
{
|
|
// get the info objects
|
|
vtkInformation* outInfo = outputVector->GetInformationObject(0);
|
|
vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
|
|
vtkInformation *inInfo2 = inputVector[1]->GetInformationObject(0);
|
|
|
|
int ext[6], ext2[6], idx;
|
|
|
|
inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),ext);
|
|
inInfo2->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),ext2);
|
|
for (idx = 0; idx < 3; ++idx)
|
|
{
|
|
if (ext2[idx*2] > ext[idx*2])
|
|
{
|
|
ext[idx*2] = ext2[idx*2];
|
|
}
|
|
if (ext2[idx*2+1] < ext[idx*2+1])
|
|
{
|
|
ext[idx*2+1] = ext2[idx*2+1];
|
|
}
|
|
}
|
|
|
|
outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),ext,6);
|
|
|
|
return 1;
|
|
}
|
|
|
|
void vtkImageMask::PrintSelf(ostream& os, vtkIndent indent)
|
|
{
|
|
this->Superclass::PrintSelf(os,indent);
|
|
|
|
int idx;
|
|
|
|
os << indent << "MaskedOutputValue: " << this->MaskedOutputValue[0];
|
|
for (idx = 1; idx < this->MaskedOutputValueLength; ++idx)
|
|
{
|
|
os << ", " << this->MaskedOutputValue[idx];
|
|
}
|
|
os << endl;
|
|
|
|
os << indent << "NotMask: " << (this->NotMask ? "On\n" : "Off\n");
|
|
os << indent << "MaskAlpha: " << this->MaskAlpha << "\n";
|
|
}
|
|
|
|
|