KWStyle - itkImageBase.h
 
Matrix View
Description

1 /*=========================================================================
2
3   Program:   Insight Segmentation & Registration Toolkit
4   Module:    $RCSfile: itkImageBase.h.html,v $
5   Language:  C++
6   Date:      $Date: 2006/01/17 19:15:36 $
7   Version:   $Revision: 1.4 $
8
9   Copyright (c) Insight Software Consortium. All rights reserved.
10   See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
11
12   Portions of this code are covered under the VTK copyright.
13   See VTKCopyright.txt or http://www.kitware.com/VTKCopyright.htm for details.
14
15      This software is distributed WITHOUT ANY WARRANTY; without even 
16      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
17 IND *****PURPOSE.  See the above copyright notices for more information.
18
19 =========================================================================*/
20 #ifndef __itkImageBase_h
21 #define __itkImageBase_h
22
23 #include "itkDataObject.h"
24 #include "itkProcessObject.h"
25 #include "itkIndex.h"
26 #include "itkOffset.h"
27 #include "itkSize.h"
28 #include "itkFixedArray.h"
29 #include "itkPoint.h"
30 #include "itkMatrix.h"
31 #include "itkImageHelper.h"
32 #include <vnl/vnl_matrix_fixed.txx>
33
34 #include "itkImageRegion.h"
35
36 namespace itk
37 {
38
39 /**
40  * Due to a bug in MSVC, an enum value cannot be accessed out of a template
41  * parameter until the template class opens.  In order for templated classes
42  * to access the dimension of an image template parameter in defining their
43  * own dimension, this class is needed as a work-around.
44  */
45 template <typename TImage>
46 struct GetImageDimension
47 {
48   itkStaticConstMacro(ImageDimension, unsigned int, TImage::ImageDimension);
49 }; 
50   
51 /** \class ImageBase
52  * \brief Base class for templated image classes.
53  *
54  * ImageBase is the base class for the templated Image
55  * classes. ImageBase is templated over the dimension of the image. It
56  * provides the API and ivars that depend solely on the dimension of
57  * the image.  ImageBase does not store any of the image (pixel) data.
58  * Storage for the pixels and the pixel access methods are defined in
59  * subclasses of ImageBase, namely Image and ImageAdaptor.
60  *
61  * There are three sets of meta-data describing an image. These are "Region"
62  * objects that define a portion of an image via a starting index for the 
63  * image array and a size. The ivar LargestPossibleRegion defines the size 
64  * and starting index of the image dataset. The entire image dataset, however,
65  * may not be resident in memory. The region of the image that is resident in
66  * memory is defined by the "BufferedRegion". The Buffer is a contiguous block
67  * of memory.  The third set of meta-data defines a region of interest, called
68  * the "RequestedRegion". The RequestedRegion is used by the pipeline
69  * execution model to define what a filter is requested to produce. 
70  *
71  * [RegionIndex, RegionSize] C [BufferIndex, BufferSize]
72  *                           C [ImageIndex, ImageSize]
73  *
74  * \ingroup ImageObjects
75  * \ingroup ITKSystemObjects
76  *
77  */
78 template<unsigned int VImageDimension=2>
79 class ITK_EXPORT ImageBase : public DataObject
80 {
81 public:
82   /** Standard typedefs. */
83   typedef ImageBase           Self;
84 TDA   typedef DataObject  Superclass;
85   typedef SmartPointer<Self>  Pointer;
86 TDA   typedef SmartPointer<const Self>  ConstPointer;
87   
88   /** Method for creation through the object factory. */
89   itkNewMacro(Self);
90
91   /** Run-time type information (and related methods). */
92   itkTypeMacro(ImageBase, DataObject);
93
94   /** Dimension of the image.  This constant is used by functions that are
95    * templated over image type (as opposed to being templated over pixel
96    * type and dimension) when they need compile time access to the dimension
97    * of the image. */
98   itkStaticConstMacro(ImageDimension, unsigned int, VImageDimension );
99
100   /** Index typedef support. An index is used to access pixel values. */
101   typedef Index<VImageDimension>  IndexType;
102 TDA   typedef typename IndexType::IndexValueType  IndexValueType;
103   
104   /** Offset typedef support. An offset represent relative position
105    * between indices. */
106   typedef Offset<VImageDimension>  OffsetType;
107 TDA   typedef typename OffsetType::OffsetValueType OffsetValueType;
108
109   /** Size typedef support. A size is used to define region bounds. */
110   typedef Size<VImageDimension>  SizeType;
111 TDA   typedef typename SizeType::SizeValueType SizeValueType;
112     
113 LEN   /** Region typedef support. A region is used to specify a subset of an image. */
114   typedef ImageRegion<VImageDimension>  RegionType;
115
116   /** Spacing typedef support.  Spacing holds the size of a pixel.  The
117    * spacing is the geometric distance between image samples. ITK only
118    * supports positive spacing value: negative values may cause
119    * undesirable results.*/
120   typedef Vector<double, VImageDimension> SpacingType;
121
122   /** Origin typedef support.  The origin is the geometric coordinates
123    * of the index (0,0). */
124   typedef Point<double, VImageDimension> PointType;
125
126   /** Direction typedef support.  The Direction is a matix of
127    * direction cosines that specify the direction between samples. */
128   typedef Matrix<double, VImageDimension, VImageDimension> DirectionType;
129
130   /** Restore object to initialized state. */
131   void Initialize();
132
133   /** Image dimension. The dimension of an image is fixed at construction. */
134   static unsigned int GetImageDimension() 
135     { return VImageDimension; }
136
137   /** Set the origin of the image. The origin is the geometric
138    * coordinates of the image origin.  It is stored internally
139    * as double but may be set from float.
140    * \sa GetOrigin() */
141   itkSetMacro(Origin, PointType);
142   virtual void SetOrigin( const double origin[VImageDimension] );
143   virtual void SetOrigin( const float origin[VImageDimension] );
144
145   /** Set the direction cosines of the image. The direction cosines
146    * are vectors that point from one pixel to the next.
147    * \sa GetDirection() */
148   virtual void SetDirection( const DirectionType direction );
149
150   /** Get the direction cosines of the image. The direction cosines
151    * are vectors that point from one pixel to the next.
152    * For ImageBase and Image, the default direction is identity. */
153   itkGetConstReferenceMacro(Direction, DirectionType);
154
155   /** Set the spacing (size of a pixel) of the image. The
156    * spacing is the geometric distance between image samples.
157    * It is stored internally as double, but may be set from
158    * float. \sa GetSpacing() */
159   itkSetMacro(Spacing, SpacingType);
160   virtual void SetSpacing( const double spacing[VImageDimension] );
161   virtual void SetSpacing( const float spacing[VImageDimension] );
162
163   /** Get the spacing (size of a pixel) `of the image. The
164    * spacing is the geometric distance between image samples.
165    * The value returned is a pointer to a double array.
166    * For ImageBase and Image, the default data spacing is unity. */
167   itkGetConstReferenceMacro(Spacing, SpacingType);
168
169   /** Get the origin of the image. The origin is the geometric
170    * coordinates of the index (0,0).  The value returned is a pointer
171    * to a double array.  For ImageBase and Image, the default origin is 
172    * 0. */
173   itkGetConstReferenceMacro(Origin, PointType);
174
175   /** Set the region object that defines the size and starting index
176    * for the largest possible region this image could represent.  This
177    * is used in determining how much memory would be needed to load an
178    * entire dataset.  It is also used to determine boundary
179    * conditions.
180    * \sa ImageRegion, SetBufferedRegion(), SetRequestedRegion() */
181   virtual void SetLargestPossibleRegion(const RegionType ®ion);
182
183   /** Get the region object that defines the size and starting index
184    * for the largest possible region this image could represent.  This
185    * is used in determining how much memory would be needed to load an
186    * entire dataset.  It is also used to determine boundary
187    * conditions.
188    * \sa ImageRegion, GetBufferedRegion(), GetRequestedRegion() */
189   virtual const RegionType& GetLargestPossibleRegion() const
190     { return m_LargestPossibleRegion;};
191
192   /** Set the region object that defines the size and starting index
193    * of the region of the image currently loaded in memory. 
194    * \sa ImageRegion, SetLargestPossibleRegion(), SetRequestedRegion() */
195   virtual void SetBufferedRegion(const RegionType ®ion);
196
197   /** Get the region object that defines the size and starting index
198    * of the region of the image currently loaded in memory. 
199    * \sa ImageRegion, SetLargestPossibleRegion(), SetRequestedRegion() */
200   virtual const RegionType& GetBufferedRegion() const
201 IND **{ return m_BufferedRegion;};
202   
203   /** Set the region object that defines the size and starting index
204    * for the region of the image requested (i.e., the region of the
205    * image to be operated on by a filter). Setting the RequestedRegion
206    * does not cause the object to be modified. This method is called
207    * internally by the pipeline and therefore bypasses the modified
208    * time calculation.
209    * \sa ImageRegion, SetLargestPossibleRegion(), SetBufferedRegion() */
210   virtual void SetRequestedRegion(const RegionType ®ion);
211
212   /** Set the requested region from this data object to match the requested
213    * region of the data object passed in as a parameter.  This method 
214    * implements the API from DataObject. The data object parameter must be
215    * castable to an ImageBase. Setting the RequestedRegion does not cause
216    * the object to be modified. This method is called internally by
217    * the pipeline and therefore bypasses the modified time
218    * calculation. */
219   virtual void SetRequestedRegion(DataObject *data);
220
221   /** Get the region object that defines the size and starting index
222    * for the region of the image requested (i.e., the region of the
223    * image to be operated on by a filter).
224    * \sa ImageRegion, SetLargestPossibleRegion(), SetBufferedRegion() */
225   virtual const RegionType& GetRequestedRegion() const
226 IND **{ return m_RequestedRegion;};
227
228   /** Get the offset table.  The offset table gives increments for
229    * moving from one pixel to next in the current row, column, slice,
230    * etc..  This table if of size [VImageDimension+1], because its
231    * values are computed progressively as: {1, N1, N1*N2,
232 IND **** N1*N2*N3,...,(N1*...*Nn)} Where the values {N1,...,Nn} are the
233    * elements of the BufferedRegion::Size array.  The last element of
234    * the OffsetTable is equivalent to the BufferSize.  Having a
235    * [VImageDimension+1] size array, simplifies the implementation of
236    * some data accessing algorithms. The entries in the offset table
237    * are only valid after the BufferedRegion is set. */
238   const OffsetValueType *GetOffsetTable() const { return m_OffsetTable; };
239   
240   /** Compute an offset from the beginning of the buffer for a pixel
241    * at the specified index. The index is not checked as to whether it
242    * is inside the current buffer, so the computed offset could
243    * conceivably be outside the buffer. If bounds checking is needed,
244    * one can call ImageRegion::IsInside(ind) on the BufferedRegion
245    * prior to calling ComputeOffset. */
246
247
248 #if 1
249   inline OffsetValueType ComputeOffset(const IndexType &ind) const
250 IND **{
251     OffsetValueType offset = 0;
252 LEN     ImageHelper<VImageDimension,VImageDimension>::ComputeOffset(this->GetBufferedRegion().GetIndex(),
253 IND ****************************************************************ind,
254 IND ****************************************************************m_OffsetTable,
255 IND ****************************************************************offset);
256     return offset;
257 IND **}
258 IND #else
259   OffsetValueType ComputeOffset(const IndexType &ind) const
260 IND **{
261     // need to add bounds checking for the region/buffer?
262     OffsetValueType offset=0;
263     const IndexType &bufferedRegionIndex = this->GetBufferedRegion().GetIndex();
264   
265     // data is arranged as [][][][slice][row][col]
266     // with Index[0] = col, Index[1] = row, Index[2] = slice
267     for (int i=VImageDimension-1; i > 0; i--)
268       {
269       offset += (ind[i] - bufferedRegionIndex[i])*m_OffsetTable[i];
270       }
271     offset += (ind[0] - bufferedRegionIndex[0]);
272
273     return offset;    
274 IND **}
275 #endif
276   /** Compute the index of the pixel at a specified offset from the
277    * beginning of the buffered region. Bounds checking is not
278    * performed. Thus, the computed index could be outside the
279    * BufferedRegion. To ensure a valid index, the parameter "offset"
280    * should be between 0 and the number of pixels in the
281    * BufferedRegion (the latter can be found using
282    * ImageRegion::GetNumberOfPixels()). */
283 #if 1
284   inline IndexType ComputeIndex(OffsetValueType offset) const
285 IND **{
286     IndexType index;
287     const IndexType &bufferedRegionIndex = this->GetBufferedRegion().GetIndex();
288 LEN     ImageHelper<VImageDimension,VImageDimension>::ComputeIndex(bufferedRegionIndex,
289                                                                offset,
290                                                                m_OffsetTable,
291                                                                index);
292     return index;
293 IND **}
294 IND #else
295   IndexType ComputeIndex(OffsetValueType offset) const
296 IND **{
297     IndexType index;
298     const IndexType &bufferedRegionIndex = this->GetBufferedRegion().GetIndex();
299     
300     for (int i=VImageDimension-1; i > 0; i--)
301       {
302       index[i] = static_cast<IndexValueType>(offset / m_OffsetTable[i]);
303       offset -= (index[i] * m_OffsetTable[i]);
304       index[i] += bufferedRegionIndex[i];
305       }
306     index[0] = bufferedRegionIndex[0] + static_cast<IndexValueType>(offset);
307
308     return index;    
309 IND **}
310 #endif
311
312   /** Copy information from the specified data set.  This method is
313    * part of the pipeline execution model. By default, a ProcessObject
314    * will copy meta-data from the first input to all of its
315    * outputs. See ProcessObject::GenerateOutputInformation().  Each
316    * subclass of DataObject is responsible for being able to copy
317 WCM    * whatever meta-data it needs from from another DataObject.
318    * ImageBase has more meta-data than its DataObject.  Thus, it must
319    * provide its own version of CopyInformation() in order to copy the
320    * LargestPossibleRegion from the input parameter. */
321   virtual void CopyInformation(const DataObject *data);
322
323   /** Graft the data and information from one image to another. This
324    * is a convenience method to setup a second image with all the meta
325    * information of another image and use the same pixel
326    * container. Note that this method is different than just using two
327    * SmartPointers to the same image since separate DataObjects are
328    * still maintained. This method is similar to
329    * ImageSource::GraftOutput(). The implementation in ImageBase
330    * simply calls CopyInformation() and copies the region ivars.
331    * Subclasses of ImageBase are responsible for copying the pixel
332    * container. */
333   virtual void Graft(const DataObject *data);
334
335   /** Update the information for this DataObject so that it can be used
336    * as an output of a ProcessObject.  This method is used the pipeline
337    * mechanism to propagate information and initialize the meta data
338    * associated with a DataObject. This method calls its source's
339    * ProcessObject::UpdateOutputInformation() which determines modified
340    * times, LargestPossibleRegions, and any extra meta data like spacing,
341    * origin, etc. */
342   virtual void UpdateOutputInformation();
343
344   /** Set the RequestedRegion to the LargestPossibleRegion.  This
345    * forces a filter to produce all of the output in one execution
346    * (i.e. not streaming) on the next call to Update(). */
347   virtual void SetRequestedRegionToLargestPossibleRegion();
348
349   /** Determine whether the RequestedRegion is outside of the
350    * BufferedRegion. This method returns true if the RequestedRegion
351    * is outside the BufferedRegion (true if at least one pixel is
352    * outside). This is used by the pipeline mechanism to determine
353    * whether a filter needs to re-execute in order to satisfy the
354    * current request.  If the current RequestedRegion is already
355    * inside the BufferedRegion from the previous execution (and the
356    * current filter is up to date), then a given filter does not need
357    * to re-execute */
358   virtual bool RequestedRegionIsOutsideOfTheBufferedRegion();
359
360   /** Verify that the RequestedRegion is within the
361    * LargestPossibleRegion.  If the RequestedRegion is not within the
362    * LargestPossibleRegion, then the filter cannot possible satisfy
363    * the request. This method returns true if the request can be
364    * satisfied and returns fails if the request cannot. This method is
365    * used by PropagateRequestedRegion().  PropagateRequestedRegion()
366    * throws a InvalidRequestedRegionError exception is the requested
367    * region is not within the LargestPossibleRegion. */
368   virtual bool VerifyRequestedRegion();
369   
370 protected:
371   ImageBase();
372   ~ImageBase();
373   virtual void PrintSelf(std::ostream& os, Indent indent) const;
374
375   /** Calculate the offsets needed to move from one pixel to the next
376    * along a row, column, slice, volume, etc. These offsets are based
377    * on the size of the BufferedRegion. This should be called after
378    * the BufferedRegion is set. */
379   void ComputeOffsetTable();
380
381 protected:
382   /** Origin and spacing of physical coordinates. This variables are
383    * protected for efficiency.  They are referenced frequently by
384    * inner loop calculations. */
385   SpacingType  m_Spacing;
386   PointType   m_Origin;
387   DirectionType m_Direction;
388
389 private:
390   ImageBase(const Self&); //purposely not implemented
391   void operator=(const Self&); //purposely not implemented
392
393   /** Returns/Sets the number of components in the image. Note that for all 
394    * images this is 1. Even for Image< RGBPixel< T >, 3 >.
395    * This is > 1 only for time-series images such as itk::VectorImage. */
396   virtual unsigned int GetNumberOfComponentsPerPixel() const;
397   virtual void SetNumberOfComponentsPerPixel( unsigned int ); // always 1
398
399   OffsetValueType  m_OffsetTable[VImageDimension+1];
400
401   RegionType          m_LargestPossibleRegion;
402   RegionType          m_RequestedRegion;
403   RegionType          m_BufferedRegion;
404 };
405
406 #ifdef ITK_EXPLICIT_INSTANTIATION
407 IND ***extern template class ImageBase<2>;
408 IND ***extern template class ImageBase<3>;
409 #endif
410
411 // end namespace itk
412
413 #ifndef ITK_MANUAL_INSTANTIATION
414 #include "itkImageBase.txx"
415 #endif
416
417 #endif
418
419 EOF

Generated by KWStyle 1.0b on Tuesday January,17 at 02:14:13PM
© Kitware Inc.