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
7.7 KiB
252 lines
7.7 KiB
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: $RCSfile: vtkImageWrapPad.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 "vtkImageWrapPad.h"
|
|
|
|
#include "vtkImageData.h"
|
|
#include "vtkInformation.h"
|
|
#include "vtkInformationVector.h"
|
|
#include "vtkObjectFactory.h"
|
|
#include "vtkStreamingDemandDrivenPipeline.h"
|
|
|
|
vtkCxxRevisionMacro(vtkImageWrapPad, "$Revision: 1.33 $");
|
|
vtkStandardNewMacro(vtkImageWrapPad);
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Just clip the request.
|
|
void vtkImageWrapPad::ComputeInputUpdateExtent (int inExt[6], int outExt[6],
|
|
int wholeExtent[6])
|
|
{
|
|
int idx;
|
|
int min, max, width, imageMin, imageMax, imageWidth;
|
|
|
|
// Clip
|
|
for (idx = 0; idx < 3; ++idx)
|
|
{
|
|
min = outExt[idx * 2];
|
|
max = outExt[idx * 2 + 1];
|
|
imageMin = wholeExtent[idx * 2];
|
|
imageMax = wholeExtent[idx * 2 + 1];
|
|
if (min > max || imageMin > imageMax)
|
|
{ // Empty output request.
|
|
inExt[0] = inExt[2] = inExt[4] = 0;
|
|
inExt[1] = inExt[3] = inExt[5] = -1;
|
|
return;
|
|
}
|
|
width = max - min + 1;
|
|
imageWidth = imageMax - imageMin + 1;
|
|
|
|
// convert min max to image extent range.
|
|
min = ((min - imageMin) % imageWidth);
|
|
if (min < 0)
|
|
{ // Mod does not handle negative numbers as I think it should.
|
|
min += imageWidth;
|
|
}
|
|
min += imageMin;
|
|
max = min + width - 1;
|
|
// if request region wraps, we need the whole input
|
|
// (unless we make multiple requests! Write Update instead??)
|
|
if (max > imageMax)
|
|
{
|
|
max = imageMax;
|
|
min = imageMin;
|
|
}
|
|
|
|
inExt[idx * 2] = min;
|
|
inExt[idx * 2 + 1] = max;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// This templated function executes the filter for any type of data.
|
|
template <class T>
|
|
void vtkImageWrapPadExecute(vtkImageWrapPad *self,
|
|
vtkImageData *inData, T *vtkNotUsed(inPtr),
|
|
vtkImageData *outData, T *outPtr,
|
|
int outExt[6], int id)
|
|
{
|
|
int min0, max0;
|
|
int imageMin0, imageMax0, imageMin1, imageMax1,
|
|
imageMin2, imageMax2;
|
|
int outIdx0, outIdx1, outIdx2;
|
|
int start0, start1, start2;
|
|
int inIdx0, inIdx1, inIdx2;
|
|
vtkIdType inInc0, inInc1, inInc2;
|
|
vtkIdType outIncX, outIncY, outIncZ;
|
|
T *inPtr0, *inPtr1, *inPtr2;
|
|
unsigned long count = 0;
|
|
unsigned long target;
|
|
int inMaxC, idxC, maxC;
|
|
|
|
// Get information to march through data
|
|
inData->GetIncrements(inInc0, inInc1, inInc2);
|
|
inData->GetWholeExtent(imageMin0, imageMax0, imageMin1, imageMax1,
|
|
imageMin2, imageMax2);
|
|
outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ);
|
|
|
|
// initialize pointers to coresponding pixels.
|
|
start0 = ((outExt[0] - imageMin0) % (imageMax0-imageMin0+1)) + imageMin0;
|
|
if (start0 < 0)
|
|
{
|
|
start0 += (imageMax0-imageMin0+1);
|
|
}
|
|
start1 = ((outExt[2] - imageMin1) % (imageMax1-imageMin1+1)) + imageMin1;
|
|
if (start1 < 0)
|
|
{
|
|
start1 += (imageMax1-imageMin1+1);
|
|
}
|
|
start2 = ((outExt[4] - imageMin2) % (imageMax2-imageMin2+1)) + imageMin2;
|
|
if (start2 < 0)
|
|
{
|
|
start2 += (imageMax2-imageMin2+1);
|
|
}
|
|
inPtr2 = (T *)(inData->GetScalarPointer(start0, start1, start2));
|
|
|
|
min0 = outExt[0];
|
|
max0 = outExt[1];
|
|
inMaxC = inData->GetNumberOfScalarComponents();
|
|
maxC = outData->GetNumberOfScalarComponents();
|
|
target = (unsigned long)((outExt[5]-outExt[4]+1)*
|
|
(outExt[3]-outExt[2]+1)/50.0);
|
|
target++;
|
|
|
|
inIdx2 = start2;
|
|
for (outIdx2 = outExt[4]; outIdx2 <= outExt[5]; ++outIdx2, ++inIdx2)
|
|
{
|
|
if (inIdx2 > imageMax2)
|
|
{ // we need to wrap(rewind) the input on this axis
|
|
inIdx2 = imageMin2;
|
|
inPtr2 -= (imageMax2-imageMin2+1)*inInc2;
|
|
}
|
|
inPtr1 = inPtr2;
|
|
inIdx1 = start1;
|
|
for (outIdx1 = outExt[2];
|
|
!self->AbortExecute && outIdx1 <= outExt[3]; ++outIdx1, ++inIdx1)
|
|
{
|
|
if (!id)
|
|
{
|
|
if (!(count%target))
|
|
{
|
|
self->UpdateProgress(count/(50.0*target));
|
|
}
|
|
count++;
|
|
}
|
|
if (inIdx1 > imageMax1)
|
|
{ // we need to wrap(rewind) the input on this axis
|
|
inIdx1 = imageMin1;
|
|
inPtr1 -= (imageMax1-imageMin1+1)*inInc1;
|
|
}
|
|
inPtr0 = inPtr1;
|
|
inIdx0 = start0;
|
|
// if components are same much faster
|
|
if ((maxC == inMaxC) && (maxC == 1))
|
|
{
|
|
for (outIdx0 = min0; outIdx0 <= max0; ++outIdx0, ++inIdx0)
|
|
{
|
|
if (inIdx0 > imageMax0)
|
|
{ // we need to wrap(rewind) the input on this axis
|
|
inIdx0 = imageMin0;
|
|
inPtr0 -= (imageMax0-imageMin0+1)*inInc0;
|
|
}
|
|
// Copy Pixel
|
|
*outPtr = *inPtr0;
|
|
outPtr++; inPtr0++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (outIdx0 = min0; outIdx0 <= max0; ++outIdx0, ++inIdx0)
|
|
{
|
|
if (inIdx0 > imageMax0)
|
|
{ // we need to wrap(rewind) the input on this axis
|
|
inIdx0 = imageMin0;
|
|
inPtr0 -= (imageMax0-imageMin0+1)*inInc0;
|
|
}
|
|
for (idxC = 0; idxC < maxC; idxC++)
|
|
{
|
|
// Copy Pixel
|
|
*outPtr = inPtr0[idxC%inMaxC];
|
|
outPtr++;
|
|
}
|
|
inPtr0 += inInc0;
|
|
}
|
|
}
|
|
outPtr += outIncY;
|
|
inPtr1 += inInc1;
|
|
}
|
|
outPtr += outIncZ;
|
|
inPtr2 += inInc2;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// This method is passed a input and output data, and executes the filter
|
|
// algorithm to fill the output from the input.
|
|
// It just executes a switch statement to call the correct function for
|
|
// the regions data types.
|
|
void vtkImageWrapPad::ThreadedRequestData (
|
|
vtkInformation * vtkNotUsed( request ),
|
|
vtkInformationVector** inputVector,
|
|
vtkInformationVector * vtkNotUsed( outputVector ),
|
|
vtkImageData ***inData,
|
|
vtkImageData **outData,
|
|
int outExt[6], int id)
|
|
{
|
|
// return if nothing to do
|
|
if (outExt[1] < outExt[0] ||
|
|
outExt[3] < outExt[2] ||
|
|
outExt[5] < outExt[4])
|
|
{
|
|
return;
|
|
}
|
|
|
|
int inExt[6];
|
|
|
|
// get the whole extent
|
|
int wExt[6];
|
|
vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
|
|
inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),wExt);
|
|
this->ComputeInputUpdateExtent(inExt,outExt,wExt);
|
|
void *inPtr = inData[0][0]->GetScalarPointerForExtent(inExt);
|
|
void *outPtr = outData[0]->GetScalarPointerForExtent(outExt);
|
|
|
|
vtkDebugMacro(<< "Execute: inData = " << inData[0][0]
|
|
<< ", outData = " << outData[0]);
|
|
|
|
// 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(
|
|
vtkImageWrapPadExecute( this, inData[0][0],
|
|
(VTK_TT *)inPtr, outData[0],
|
|
(VTK_TT *)(outPtr), outExt, id));
|
|
default:
|
|
vtkErrorMacro(<< "Execute: Unknown ScalarType");
|
|
return;
|
|
}
|
|
}
|
|
|