1 /*========================================================================= 2 * 3 * Copyright Insight Software Consortium 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0.txt 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 *=========================================================================*/ 18 19 #ifndef itkConstantBoundaryImageNeighborhoodPixelAccessPolicy_h 20 #define itkConstantBoundaryImageNeighborhoodPixelAccessPolicy_h 21 22 #include "itkIndex.h" 23 #include "itkOffset.h" 24 #include "itkSize.h" 25 26 namespace itk 27 { 28 namespace Experimental 29 { 30 31 /** 32 * \class ConstantBoundaryImageNeighborhoodPixelAccessPolicy 33 * ImageNeighborhoodPixelAccessPolicy class for ShapedImageNeighborhoodRange. 34 * Allows getting and setting the value of a pixel, located in a specified 35 * neighborhood location, at a specified offset. Uses a constant as value 36 * for pixels outside the image border. 37 * 38 * \see ShapedNeighborhoodIterator 39 * \see ConstantBoundaryCondition 40 * \ingroup ImageIterators 41 * \ingroup ITKCommon 42 */ 43 template <typename TImage> 44 class ConstantBoundaryImageNeighborhoodPixelAccessPolicy final 45 { 46 private: 47 using NeighborhoodAccessorFunctorType = typename TImage::NeighborhoodAccessorFunctorType; 48 using PixelType = typename TImage::PixelType; 49 using InternalPixelType = typename TImage::InternalPixelType; 50 51 using ImageDimensionType = typename TImage::ImageDimensionType; 52 static constexpr ImageDimensionType ImageDimension = TImage::ImageDimension; 53 54 using IndexType = Index<ImageDimension>; 55 using OffsetType = Offset<ImageDimension>; 56 using ImageSizeType = Size<ImageDimension>; 57 using ImageSizeValueType = SizeValueType; 58 59 // Index value to the image buffer, indexing the current pixel. -1 is used to indicate out-of-bounds. 60 const IndexValueType m_PixelIndexValue; 61 62 // A reference to the accessor of the image. 63 const NeighborhoodAccessorFunctorType& m_NeighborhoodAccessor; 64 65 // The constant whose value is returned a pixel value outside the image is queried. 66 const PixelType m_Constant; 67 68 69 // Private helper function. Tells whether the pixel at 'pixelIndex' is inside the image. IsInside(const IndexType & pixelIndex,const ImageSizeType & imageSize)70 static bool IsInside( 71 const IndexType& pixelIndex, 72 const ImageSizeType& imageSize) ITK_NOEXCEPT 73 { 74 bool result = true; 75 76 for (ImageDimensionType i = 0; i < ImageDimension; ++i) 77 { 78 const IndexValueType indexValue = pixelIndex[i]; 79 80 // Note: Do not 'quickly' break or return out of the for-loop when the 81 // result is false! For performance reasons (loop unrolling, etc.) it 82 // appears preferable to complete the for-loop iteration in this case! 83 result = result && 84 (indexValue >= 0) && 85 (static_cast<ImageSizeValueType>(indexValue) < imageSize[i]); 86 } 87 return result; 88 } 89 90 91 // Private helper function. Calculates and returns the index value of the 92 // current pixel within the image buffer. CalculatePixelIndexValue(const OffsetType & offsetTable,const IndexType & pixelIndex)93 static IndexValueType CalculatePixelIndexValue( 94 const OffsetType& offsetTable, 95 const IndexType& pixelIndex) ITK_NOEXCEPT 96 { 97 IndexValueType result = 0; 98 99 for (ImageDimensionType i = 0; i < ImageDimension; ++i) 100 { 101 result += pixelIndex[i] * offsetTable[i]; 102 } 103 return result; 104 } 105 106 public: 107 /** This type is necessary to tell the ShapedImageNeighborhoodRange that the 108 * constructor accepts a pixel value as (optional) extra parameter. */ 109 using PixelAccessParameterType = PixelType; 110 111 // Deleted member functions: 112 ConstantBoundaryImageNeighborhoodPixelAccessPolicy() = delete; 113 ConstantBoundaryImageNeighborhoodPixelAccessPolicy& operator=(const ConstantBoundaryImageNeighborhoodPixelAccessPolicy&) = delete; 114 115 // Explicitly-defaulted functions: 116 ~ConstantBoundaryImageNeighborhoodPixelAccessPolicy() = default; 117 ConstantBoundaryImageNeighborhoodPixelAccessPolicy( 118 const ConstantBoundaryImageNeighborhoodPixelAccessPolicy&) = default; 119 120 /** Constructor called directly by the pixel proxy of 121 * ShapedImageNeighborhoodRange. */ 122 ConstantBoundaryImageNeighborhoodPixelAccessPolicy( 123 const ImageSizeType& imageSize, 124 const OffsetType& offsetTable, 125 const NeighborhoodAccessorFunctorType& neighborhoodAccessor, 126 const IndexType& pixelIndex, 127 const PixelType constant = {}) ITK_NOEXCEPT 128 : 129 m_PixelIndexValue 130 { 131 IsInside(pixelIndex, imageSize) ? CalculatePixelIndexValue(offsetTable, pixelIndex) : -1 132 }, 133 m_NeighborhoodAccessor(neighborhoodAccessor), 134 m_Constant{constant} 135 { 136 } 137 138 139 /** Retrieves the pixel value from the image buffer, at the current 140 * index. When the index is out of bounds, it returns the constant 141 * value specified during construction. */ GetPixelValue(const InternalPixelType * const imageBufferPointer)142 PixelType GetPixelValue(const InternalPixelType* const imageBufferPointer) const ITK_NOEXCEPT 143 { 144 return (m_PixelIndexValue < 0) ? 145 m_Constant : 146 m_NeighborhoodAccessor.Get(imageBufferPointer + m_PixelIndexValue); 147 } 148 149 /** Sets the value of the image buffer at the current index value to the 150 * specified value. */ SetPixelValue(InternalPixelType * const imageBufferPointer,const PixelType & pixelValue)151 void SetPixelValue(InternalPixelType* const imageBufferPointer, const PixelType& pixelValue) const ITK_NOEXCEPT 152 { 153 if (m_PixelIndexValue >= 0) 154 { 155 m_NeighborhoodAccessor.Set(imageBufferPointer + m_PixelIndexValue, pixelValue); 156 } 157 } 158 }; 159 160 } // namespace Experimental 161 } // namespace itk 162 163 #endif 164