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.

252 lines
9.1 KiB

2 years ago
/*=========================================================================
Program: Visualization Toolkit
Module: $RCSfile: vtkImageSobel3D.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 "vtkImageSobel3D.h"
#include "vtkImageData.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include "vtkStreamingDemandDrivenPipeline.h"
#include <math.h>
vtkCxxRevisionMacro(vtkImageSobel3D, "$Revision: 1.38 $");
vtkStandardNewMacro(vtkImageSobel3D);
//----------------------------------------------------------------------------
// Construct an instance of vtkImageSobel3D fitler.
vtkImageSobel3D::vtkImageSobel3D()
{
this->KernelSize[0] = 3;
this->KernelSize[1] = 3;
this->KernelSize[2] = 3;
this->KernelMiddle[0] = 1;
this->KernelMiddle[1] = 1;
this->KernelMiddle[2] = 1;
this->HandleBoundaries = 1;
}
//----------------------------------------------------------------------------
void vtkImageSobel3D::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
}
//----------------------------------------------------------------------------
int vtkImageSobel3D::RequestInformation (vtkInformation *request,
vtkInformationVector **inputVector,
vtkInformationVector *outputVector)
{
int retval =
this->Superclass::RequestInformation(request, inputVector, outputVector);
vtkInformation *outInfo = outputVector->GetInformationObject(0);
vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_DOUBLE, 3);
return retval;
}
//----------------------------------------------------------------------------
// This execute method handles boundaries.
// it handles boundaries. Pixels are just replicated to get values
// out of extent.
template <class T>
void vtkImageSobel3DExecute(vtkImageSobel3D *self,
vtkImageData *inData, T *inPtr,
vtkImageData *outData, int *outExt,
double *outPtr, int id, vtkInformation *inInfo)
{
double r0, r1, r2, *r;
// For looping though output (and input) pixels.
int min0, max0, min1, max1, min2, max2;
int outIdx0, outIdx1, outIdx2;
vtkIdType outInc0, outInc1, outInc2;
double *outPtr0, *outPtr1, *outPtr2, *outPtrV;
vtkIdType inInc0, inInc1, inInc2;
T *inPtr0, *inPtr1, *inPtr2;
// For sobel function convolution (Left Right incs for each axis)
vtkIdType inInc0L, inInc0R, inInc1L, inInc1R, inInc2L, inInc2R;
T *inPtrL, *inPtrR;
double sum;
// Boundary of input image
int inWholeMin0, inWholeMax0, inWholeMin1, inWholeMax1;
int inWholeMin2, inWholeMax2;
int inWholeExt[6];
unsigned long count = 0;
unsigned long target;
// Get boundary information
inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), inWholeExt);
inWholeMin0 = inWholeExt[0];
inWholeMax0 = inWholeExt[1];
inWholeMin1 = inWholeExt[2];
inWholeMax1 = inWholeExt[3];
inWholeMin2 = inWholeExt[4];
inWholeMax2 = inWholeExt[5];
// Get information to march through data (skip component)
inData->GetIncrements(inInc0, inInc1, inInc2);
outData->GetIncrements(outInc0, outInc1, outInc2);
min0 = outExt[0]; max0 = outExt[1];
min1 = outExt[2]; max1 = outExt[3];
min2 = outExt[4]; max2 = outExt[5];
// We want the input pixel to correspond to output
inPtr = (T *)(inData->GetScalarPointer(min0,min1,min2));
// The data spacing is important for computing the gradient.
// Scale so it has the same range as gradient.
r = inData->GetSpacing();
r0 = 0.060445 / r[0];
r1 = 0.060445 / r[1];
r2 = 0.060445 / r[2];
target = (unsigned long)((max2-min2+1)*(max1-min1+1)/50.0);
target++;
// loop through pixels of output
outPtr2 = outPtr;
inPtr2 = inPtr;
for (outIdx2 = min2; outIdx2 <= max2; ++outIdx2)
{
inInc2L = (outIdx2 == inWholeMin2) ? 0 : -inInc2;
inInc2R = (outIdx2 == inWholeMax2) ? 0 : inInc2;
outPtr1 = outPtr2;
inPtr1 = inPtr2;
for (outIdx1 = min1; !self->AbortExecute && outIdx1 <= max1; ++outIdx1)
{
if (!id)
{
if (!(count%target))
{
self->UpdateProgress(count/(50.0*target));
}
count++;
}
inInc1L = (outIdx1 == inWholeMin1) ? 0 : -inInc1;
inInc1R = (outIdx1 == inWholeMax1) ? 0 : inInc1;
outPtr0 = outPtr1;
inPtr0 = inPtr1;
for (outIdx0 = min0; outIdx0 <= max0; ++outIdx0)
{
inInc0L = (outIdx0 == inWholeMin0) ? 0 : -inInc0;
inInc0R = (outIdx0 == inWholeMax0) ? 0 : inInc0;
// compute vector.
outPtrV = outPtr0;
// 12 Plane
inPtrL = inPtr0 + inInc0L;
inPtrR = inPtr0 + inInc0R;
sum = 2.0 * (*inPtrR - *inPtrL);
sum += (double)(inPtrR[inInc1L] + inPtrR[inInc1R]
+ inPtrR[inInc2L] + inPtrR[inInc2R]);
sum += (double)(0.586 * (inPtrR[inInc1L+inInc2L] + inPtrR[inInc1L+inInc2R]
+ inPtrR[inInc1R+inInc2L] + inPtrR[inInc1R+inInc2R]));
sum -= (double)(inPtrL[inInc1L] + inPtrL[inInc1R]
+ inPtrL[inInc2L] + inPtrL[inInc2R]);
sum -= (double)(0.586 * (inPtrL[inInc1L+inInc2L] + inPtrL[inInc1L+inInc2R]
+ inPtrL[inInc1R+inInc2L] + inPtrL[inInc1R+inInc2R]));
*outPtrV = sum * r0;
++outPtrV;
// 02 Plane
inPtrL = inPtr0 + inInc1L;
inPtrR = inPtr0 + inInc1R;
sum = 2.0 * (*inPtrR - *inPtrL);
sum += (double)(inPtrR[inInc0L] + inPtrR[inInc0R]
+ inPtrR[inInc2L] + inPtrR[inInc2R]);
sum += (double)(0.586 * (inPtrR[inInc0L+inInc2L] + inPtrR[inInc0L+inInc2R]
+ inPtrR[inInc0R+inInc2L] + inPtrR[inInc0R+inInc2R]));
sum -= (double)(inPtrL[inInc0L] + inPtrL[inInc0R]
+ inPtrL[inInc2L] + inPtrL[inInc2R]);
sum -= (double)(0.586 * (inPtrL[inInc0L+inInc2L] + inPtrL[inInc0L+inInc2R]
+ inPtrL[inInc0R+inInc2L] + inPtrL[inInc0R+inInc2R]));
*outPtrV = sum * r1;
++outPtrV;
// 01 Plane
inPtrL = inPtr0 + inInc2L;
inPtrR = inPtr0 + inInc2R;
sum = 2.0 * (*inPtrR - *inPtrL);
sum += (double)(inPtrR[inInc0L] + inPtrR[inInc0R]
+ inPtrR[inInc1L] + inPtrR[inInc1R]);
sum += (double)(0.586 * (inPtrR[inInc0L+inInc1L] + inPtrR[inInc0L+inInc1R]
+ inPtrR[inInc0R+inInc1L] + inPtrR[inInc0R+inInc1R]));
sum -= (double)(inPtrL[inInc0L] + inPtrL[inInc0R]
+ inPtrL[inInc1L] + inPtrL[inInc1R]);
sum -= (double)(0.586 * (inPtrL[inInc0L+inInc1L] + inPtrL[inInc0L+inInc1R]
+ inPtrL[inInc0R+inInc1L] + inPtrL[inInc0R+inInc1R]));
*outPtrV = static_cast<double>(sum * r2);
++outPtrV;
outPtr0 += outInc0;
inPtr0 += inInc0;
}
outPtr1 += outInc1;
inPtr1 += inInc1;
}
outPtr2 += outInc2;
inPtr2 += inInc2;
}
}
//----------------------------------------------------------------------------
// This method contains a switch statement that calls the correct
// templated function for the input Data type. The output Data
// must be of type double. This method does handle boundary conditions.
// The third axis is the component axis for the output.
void vtkImageSobel3D::ThreadedRequestData(
vtkInformation *vtkNotUsed(request),
vtkInformationVector **inputVector,
vtkInformationVector *vtkNotUsed(outputVector),
vtkImageData ***inData,
vtkImageData **outData,
int outExt[6], int id)
{
void *inPtr, *outPtr;
int inExt[6], wholeExt[6];
vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wholeExt);
this->InternalRequestUpdateExtent(inExt, outExt, wholeExt);
inPtr = inData[0][0]->GetScalarPointerForExtent(inExt);
outPtr = outData[0]->GetScalarPointerForExtent(outExt);
// this filter cannot handle multi component input.
if (inData[0][0]->GetNumberOfScalarComponents() != 1)
{
vtkWarningMacro("Expecting input with only one compenent.\n");
}
// this filter expects that output is type double.
if (outData[0]->GetScalarType() != VTK_DOUBLE)
{
vtkErrorMacro(<< "Execute: output ScalarType, "
<< vtkImageScalarTypeNameMacro(outData[0]->GetScalarType())
<< ", must be double");
return;
}
switch (inData[0][0]->GetScalarType())
{
vtkTemplateMacro(
vtkImageSobel3DExecute( this, inData[0][0],
(VTK_TT *)(inPtr), outData[0], outExt,
(double *)(outPtr),id, inInfo));
default:
vtkErrorMacro(<< "Execute: Unknown ScalarType");
return;
}
}