1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
|
#include "LookupTableIntensityMappingFilter.h"
#include "RLEImageRegionIterator.h"
#include <itkRGBAPixel.h>
#include "LookupTableTraits.h"
template<class TInputImage, class TOutputImage>
LookupTableIntensityMappingFilter<TInputImage, TOutputImage>
::LookupTableIntensityMappingFilter()
{
// The image and the LUT are inputs
this->SetNumberOfIndexedInputs(4);
}
template<class TInputImage, class TOutputImage>
void
LookupTableIntensityMappingFilter<TInputImage, TOutputImage>
::SetLookupTable(LookupTableType *lut)
{
m_LookupTable = lut;
this->SetNthInput(1, lut);
}
template<class TInputImage, class TOutputImage>
void
LookupTableIntensityMappingFilter<TInputImage, TOutputImage>
::SetImageMinInput(InputPixelObject *input)
{
m_InputMin = input;
this->SetNthInput(2, input);
}
template<class TInputImage, class TOutputImage>
void
LookupTableIntensityMappingFilter<TInputImage, TOutputImage>
::SetImageMaxInput(InputPixelObject *input)
{
m_InputMax = input;
this->SetNthInput(3, input);
}
template<class TInputImage, class TOutputImage>
void
LookupTableIntensityMappingFilter<TInputImage, TOutputImage>
::ThreadedGenerateData(const OutputImageRegionType ®ion,
itk::ThreadIdType threadId)
{
// Get the input, output and the LUT
const InputImageType *input = this->GetInput();
OutputImageType *output = this->GetOutput(0);
// Get the pointer to the zero value in the LUT
OutputPixelType *lutp =
m_LookupTable->GetBufferPointer()
- m_LookupTable->GetLargestPossibleRegion().GetIndex()[0];
// Range of the input image
InputPixelType input_min = m_InputMin->Get();
InputPixelType input_max = m_InputMax->Get();
// Compute the shift and scale factors that map the input values into
// the LUT values. These are ignored for integral pixel types, but used
// for floating point types
float lutScale;
InputPixelType lutShift;
LookupTableTraits<InputPixelType>::ComputeLinearMappingToLUT(
input_min, input_max, lutScale, lutShift);
// Define the iterators
itk::ImageRegionConstIterator<TInputImage> inputIt(input, region);
itk::ImageRegionIterator<TOutputImage> outputIt(output, region);
// Perform the intensity mapping using the LUT (no bounds checking!)
while( !inputIt.IsAtEnd() )
{
// Get the input intensity
InputPixelType xin = inputIt.Get();
OutputPixelType xout;
// TODO: we need to handle out of bounds voxels in non-orthogonal slicing
// better than this, i.e., via a special value reserved for such voxels.
// Right now, defaulting to zero is a DISASTER!
if(xin == 0 && (input_min > 0 || input_max < 0))
{
// Special case: intensity is actually outside of the min/max range
xout.Fill(0);
}
else
{
// Find the corresponding LUT offset
int lut_offset = LookupTableTraits<InputPixelType>::ComputeLUTOffset(
lutScale, lutShift, xin);
xout = *(lutp + lut_offset);
}
outputIt.Set(xout);
++inputIt;
++outputIt;
}
}
template<class TInputImage, class TOutputImage>
typename LookupTableIntensityMappingFilter<TInputImage, TOutputImage>::OutputPixelType
LookupTableIntensityMappingFilter<TInputImage, TOutputImage>
::MapPixel(const InputPixelType &xin)
{
// Make sure all the inputs are up to date
m_InputMin->Update();
m_InputMax->Update();
m_LookupTable->Update();
// Get the pointer to the zero value in the LUT
OutputPixelType *lutp =
m_LookupTable->GetBufferPointer()
- m_LookupTable->GetLargestPossibleRegion().GetIndex()[0];
// Range of the input image
InputPixelType input_min = m_InputMin->Get();
InputPixelType input_max = m_InputMax->Get();
// Compute the shift and scale factors that map the input values into
// the LUT values. These are ignored for integral pixel types, but used
// for floating point types
float lutScale;
InputPixelType lutShift;
LookupTableTraits<InputPixelType>::ComputeLinearMappingToLUT(
input_min, input_max, lutScale, lutShift);
// Get the input intensity
OutputPixelType xout;
// TODO: we need to handle out of bounds voxels in non-orthogonal slicing
// better than this, i.e., via a special value reserved for such voxels.
// Right now, defaulting to zero is a DISASTER!
if(xin == 0 && (input_min > 0 || input_max < 0))
{
// Special case: intensity is actually outside of the min/max range
xout.Fill(0);
}
else
{
// Find the corresponding LUT offset
int lut_offset = LookupTableTraits<InputPixelType>::ComputeLUTOffset(
lutScale, lutShift, xin);
xout = *(lutp + lut_offset);
}
return xout;
}
// Declare specific instances that will exist
template class LookupTableIntensityMappingFilter<
itk::Image<short, 2>, itk::Image< itk::RGBAPixel<unsigned char> > >;
template class LookupTableIntensityMappingFilter<
itk::Image<float, 2>, itk::Image< itk::RGBAPixel<unsigned char> > >;
|