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 #ifndef itkVectorImage_h 19 #define itkVectorImage_h 20 21 #include "itkImageRegion.h" 22 #include "itkImportImageContainer.h" 23 #include "itkDefaultVectorPixelAccessor.h" 24 #include "itkDefaultVectorPixelAccessorFunctor.h" 25 #include "itkVectorImageNeighborhoodAccessorFunctor.h" 26 #include "itkWeakPointer.h" 27 28 namespace itk 29 { 30 /** \class VectorImage 31 * \brief Templated n-dimensional vector image class. 32 * 33 * This class differs from Image in that it is intended to represent multiple 34 * images. Each pixel represents \e k measurements, each of datatype \e TPixel. 35 * The memory organization of the resulting image is as follows: 36 * ... Pi0 Pi1 Pi2 Pi3 P(i+1)0 P(i+1)1 P(i+1)2 P(i+1)3 P(i+2)0 ... 37 * where Pi0 represents the 0th measurement of the pixel at index i. 38 * 39 * Conceptually, a <tt>VectorImage< TPixel, 3 ></tt> is the same as a 40 * <tt>Image< VariableLengthVector< TPixel >, 3 ></tt>. The difference lies in the memory 41 * organization. The latter results in a fragmented 42 * organization with each location in the Image holding a pointer to an \c VariableLengthVector 43 * holding the actual pixel. The former stores the \e k pixels instead of a 44 * pointer reference, which apart from avoiding fragmentation of memory also avoids 45 * storing a 8 bytes of pointer reference for each pixel. 46 * The parameter \e k can be set using \c SetVectorLength. 47 * 48 * The API of the class is such that it returns a pixeltype VariableLengthVector< TPixel > when 49 * queried, with the data internally pointing to the buffer. (the container does not 50 * manage the memory). Similarly SetPixel calls can be made with VariableLengthVector< TPixel >. 51 * 52 * The API of this class is similar to Image. 53 * 54 * \par Caveats: 55 * When using Iterators on this image, you cannot use the it.Value(). You must use 56 * Set/Get() methods instead. 57 * 58 * \note 59 * This work is part of the National Alliance for Medical Image Computing 60 * (NAMIC), funded by the National Institutes of Health through the NIH Roadmap 61 * for Medical Research, Grant U54 EB005149. 62 * 63 * \sa DefaultVectorPixelAccessor 64 * \sa DefaultVectorPixelAccessorFunctor 65 * \sa VectorImageToImagePixelAccessor 66 * \sa VectorImageToImageAdaptor 67 * \sa Image 68 * \sa ImportImageContainer 69 * 70 * 71 * \ingroup ImageObjects 72 * \ingroup ITKCommon 73 * 74 * \wiki 75 * \wikiexample{IO/ReadVectorImage,Read an image file with an unknown number of components} 76 * \wikiexample{VectorImages/VectorImage,Create a vector image} 77 * \wikiexample{VectorImages/NeighborhoodIterator,NeighborhoodIterator on a VectorImage} 78 * \endwiki 79 */ 80 template< typename TPixel, unsigned int VImageDimension = 3 > 81 class ITK_TEMPLATE_EXPORT VectorImage: 82 public ImageBase< VImageDimension > 83 { 84 public: 85 ITK_DISALLOW_COPY_AND_ASSIGN(VectorImage); 86 87 /** Standard class type aliases */ 88 using Self = VectorImage; 89 using Superclass = ImageBase< VImageDimension >; 90 using Pointer = SmartPointer< Self >; 91 using ConstPointer = SmartPointer< const Self >; 92 using ConstWeakPointer = WeakPointer< const Self >; 93 94 /** Method for creation through the object factory. */ 95 itkNewMacro(Self); 96 97 /** Run-time type information (and related methods). */ 98 itkTypeMacro(VectorImage, ImageBase); 99 100 /** Pixel type alias support Used to declare pixel type in filters 101 * or other operations. This is not the actual pixel type contained in 102 * the buffer, ie m_Buffer. The image exhibits an external API of an 103 * VariableLengthVector< T > and internally stores its data as type T. */ 104 using PixelType = VariableLengthVector< TPixel >; 105 106 /** This is the actual pixel type contained in the buffer. Each vector 107 * pixel is composed of 'm_VectorLength' contiguous InternalPixelType. 108 */ 109 using InternalPixelType = TPixel; 110 111 /** Typedef alias for PixelType */ 112 using ValueType = PixelType; 113 114 using IOPixelType = InternalPixelType; 115 116 /** Accessor type that convert data between internal and external 117 * representations. */ 118 using AccessorType = DefaultVectorPixelAccessor< InternalPixelType >; 119 120 /** Functor to provide a common API between DefaultPixelAccessor and 121 * DefaultVectorPixelAccessor */ 122 using AccessorFunctorType = DefaultVectorPixelAccessorFunctor< Self >; 123 124 /** Typedef for the functor used to access a neighborhood of pixel 125 * pointers. */ 126 using NeighborhoodAccessorFunctorType = VectorImageNeighborhoodAccessorFunctor<Self>; 127 128 /** Dimension of the image. This constant is used by functions that are 129 * templated over image type (as opposed to being templated over pixel type 130 * and dimension) when they need compile time access to the dimension of 131 * the image. */ 132 static constexpr unsigned int ImageDimension = VImageDimension; 133 134 /** Index type alias support An index is used to access pixel values. */ 135 using IndexType = typename Superclass::IndexType; 136 using IndexValueType = typename Superclass::IndexValueType; 137 138 /** Offset type alias support An offset is used to access pixel values. */ 139 using OffsetType = typename Superclass::OffsetType; 140 141 /** Size type alias support A size is used to define region bounds. */ 142 using SizeType = typename Superclass::SizeType; 143 144 /** Container used to store pixels in the image. */ 145 using PixelContainer = ImportImageContainer< SizeValueType, InternalPixelType >; 146 147 /** Direction type alias support A matrix of direction cosines. */ 148 using DirectionType = typename Superclass::DirectionType; 149 150 /** Region type alias support A region is used to specify a subset of an image. 151 */ 152 using RegionType = typename Superclass::RegionType; 153 154 /** Spacing type alias support Spacing holds the size of a pixel. The 155 * spacing is the geometric distance between image samples. */ 156 using SpacingType = typename Superclass::SpacingType; 157 158 /** Origin type alias support The origin is the geometric coordinates 159 * of the index (0,0). */ 160 using PointType = typename Superclass::PointType; 161 162 /** A pointer to the pixel container. */ 163 using PixelContainerPointer = typename PixelContainer::Pointer; 164 using PixelContainerConstPointer = typename PixelContainer::ConstPointer; 165 166 /** Offset type alias (relative position between indices) */ 167 using OffsetValueType = typename Superclass::OffsetValueType; 168 169 using VectorLengthType = unsigned int; 170 171 /** 172 * \brief A structure which enable changing any image class' pixel 173 * type to another. 174 * 175 * Since the pixel type of this class is a VariableLengthVector of 176 * TPixelType, the following two rebinds result in the same type to 177 * enable usage with the numeric trait's type. 178 * 179 \code 180 typename InputImageType::template template Rebind<double>::Type RealImageType1; 181 typename InputImageType::template template Rebind<VariableLengthVector<double> >::Type RealImageType2; 182 \endcode 183 * 184 * \sa Image::Rebind 185 * \deprecated Use template alias RebindImageType instead 186 */ 187 template <typename UPixelType, unsigned int NUImageDimension = VImageDimension> 188 struct Rebind 189 { 190 using Type = itk::VectorImage<UPixelType, NUImageDimension>; 191 }; 192 193 /// \cond HIDE_SPECIALIZATION_DOCUMENTATION 194 template <typename UElementType, unsigned int NUImageDimension> 195 struct Rebind< VariableLengthVector< UElementType >, NUImageDimension> 196 { 197 using Type = itk::VectorImage<UElementType, NUImageDimension>; 198 }; 199 /// \endcond 200 201 template <typename UPixelType, unsigned int NUImageDimension = VImageDimension> 202 using RebindImageType = typename Rebind<UPixelType, NUImageDimension>::Type; 203 204 /** Allocate the image memory. The size of the image must 205 * already be set, e.g. by calling SetRegions(). */ 206 void Allocate(bool UseDefaultConstructor = false) override; 207 208 /** Restore the data object to its initial state. This means releasing 209 * memory. */ 210 void Initialize() override; 211 212 /** Fill the image buffer with a value. Be sure to call Allocate() 213 * first. */ 214 void FillBuffer(const PixelType & value); 215 216 /** \brief Set a pixel value. 217 * 218 * Allocate() needs to have been called first -- for efficiency, 219 * this function does not check that the image has actually been 220 * allocated yet. */ 221 void SetPixel(const IndexType & index, const PixelType & value) 222 { 223 OffsetValueType offset = m_VectorLength * this->FastComputeOffset(index); 224 225 for ( VectorLengthType i = 0; i < m_VectorLength; i++ ) 226 { 227 ( *m_Buffer )[offset + i] = value[i]; 228 } 229 } 230 231 /** \brief Get a pixel (read only version). 232 * 233 * For efficiency, this function does not check that the 234 * image has actually been allocated yet. Note that the method returns a 235 * pixel on the stack. */ 236 const PixelType GetPixel(const IndexType & index) const 237 { 238 OffsetValueType offset = m_VectorLength * this->FastComputeOffset(index); 239 240 // Do not create a local for this method, to use return value 241 // optimization. 242 return PixelType(&( ( *m_Buffer )[offset] ), m_VectorLength); 243 } 244 245 /** \brief Get a "reference" to a pixel. This result cannot be used 246 * as an lvalue because the pixel is converted on the fly to a 247 * VariableLengthVector. 248 * 249 * To use the results to modify this image, return value 250 * optimization must be relied upon. 251 * 252 * For efficiency, this function does not check that the 253 * image has actually been allocated yet. */ 254 PixelType GetPixel(const IndexType & index) 255 { 256 OffsetValueType offset = m_VectorLength * this->FastComputeOffset(index); 257 258 // Correctness of this method relies of return value optimization, do 259 // not create a local for the value. 260 return PixelType(&( ( *m_Buffer )[offset] ), m_VectorLength); 261 } 262 263 /** \brief Access a pixel. This result cannot be used as an lvalue 264 * because the pixel is converted on the fly to a 265 * VariableLengthVector. 266 * 267 * To use the results to modify this image, return value 268 * optimization must be relied upon. 269 * 270 * For efficiency, this function does not check that the 271 * image has actually been allocated yet. */ 272 PixelType operator[](const IndexType & index) { return this->GetPixel(index); } 273 274 /** \brief Access a pixel. 275 * 276 * For efficiency, this function does not check that the 277 * image has actually been allocated yet. */ 278 const PixelType operator[](const IndexType & index) const { return this->GetPixel(index); } 279 280 /** Return a pointer to the beginning of the buffer. This is used by 281 * the image iterator class. */ 282 InternalPixelType * GetBufferPointer() 283 { 284 return m_Buffer ? m_Buffer->GetBufferPointer() : nullptr; 285 } 286 const InternalPixelType * GetBufferPointer() const 287 { 288 return m_Buffer ? m_Buffer->GetBufferPointer() : nullptr; 289 } 290 291 /** Return a pointer to the container. */ 292 PixelContainer * GetPixelContainer() { return m_Buffer.GetPointer(); } 293 294 /** Return a pointer to the container. */ 295 const PixelContainer * GetPixelContainer() const { return m_Buffer.GetPointer(); } 296 297 /** Set the container to use. Note that this does not cause the 298 * DataObject to be modified. */ 299 void SetPixelContainer(PixelContainer *container); 300 301 /** Graft the data and information from one image to another. This 302 * is a convenience method to setup a second image with all the meta 303 * information of another image and use the same pixel 304 * container. Note that this method is different than just using two 305 * SmartPointers to the same image since separate DataObjects are 306 * still maintained. This method is similar to 307 * ImageSource::GraftOutput(). The implementation in ImageBase 308 * simply calls CopyInformation() and copies the region ivars. 309 * The implementation here refers to the superclass' implementation 310 * and then copies over the pixel container. */ 311 virtual void Graft(const Self *data); 312 313 /** Return the Pixel Accessor object */ 314 AccessorType GetPixelAccessor() { return AccessorType(m_VectorLength); } 315 316 /** Return the Pixel Accesor object */ 317 const AccessorType GetPixelAccessor() const { return AccessorType(m_VectorLength); } 318 319 /** Return the NeighborhoodAccessor functor */ 320 NeighborhoodAccessorFunctorType GetNeighborhoodAccessor() 321 { 322 return NeighborhoodAccessorFunctorType(m_VectorLength); 323 } 324 325 /** Return the NeighborhoodAccessor functor */ 326 const NeighborhoodAccessorFunctorType GetNeighborhoodAccessor() const 327 { 328 return NeighborhoodAccessorFunctorType(m_VectorLength); 329 } 330 331 /** Set/Get macros for the length of each vector in the vector image */ 332 itkSetMacro(VectorLength, VectorLengthType); 333 itkGetConstReferenceMacro(VectorLength, VectorLengthType); 334 335 /** Get/Set the number of components each pixel has, ie the VectorLength */ 336 unsigned int GetNumberOfComponentsPerPixel() const override; 337 338 void SetNumberOfComponentsPerPixel(unsigned int n) override; 339 340 protected: 341 VectorImage(); 342 void PrintSelf(std::ostream & os, Indent indent) const override; 343 344 ~VectorImage() override = default; 345 void Graft(const DataObject *data) override; 346 using Superclass::Graft; 347 private: 348 /** Length of the "vector pixel" */ 349 VectorLengthType m_VectorLength{0}; 350 351 /** Memory for the current buffer. */ 352 PixelContainerPointer m_Buffer; 353 }; 354 } // end namespace itk 355 356 #ifndef ITK_MANUAL_INSTANTIATION 357 #include "itkVectorImage.hxx" 358 #endif 359 360 #endif 361