[Insight-developers] ImageAdaptor and DataAccessor

Luis Ibanez ibanez at cs.unc.edu
Sat Nov 11 22:45:23 EST 2000


Hi,

I just checked in the code for ImageAdaptors,
it seems to be working fine.

The new class

   itk::ImageAdaptor<>

is responsible for exposing the pixels of 
an image as if they were of other type.

For example, an RGB image can be presented as
a float image, just by exposing only its blue
component,  or a gray level image can be 
presented as having RGB colors in it.

The choice of what to expose is done by defining
an DataAccessor type.  It contains basically two
typedefs that indicate the internal and external
types, and two methods to specify how the to convert
between the internal and external types.

The ImageAdaptor is templated over the type of
the image it encapsulates and over the DataAccessor.

ImageAdaptors can be used in any place where an 
Image is expected.

An ImageAdaptor demo is now in the repository
under Testing/Code/Common/itkImageAdaptor.cxx

-----

The only limitation is that for it to work,
the declaration of ScalarTraits and VectorTraits
should be commented out...

But in some way, it seems to be possible to use
the DataAccessor for the purpouse we are using
the Scalar and Vector traits now. 
(something to double check...)

-----

ImageAdaptors solve the casting problem too, 
because the DataAccessor can be use to define
how to convert from double to char in a particular
case.

This without having to duplicate image data, nor
having to pass the image through a 'casting' filter.


----

The Iterators classes should now be parametrized
over the image type instead of being parametrized
over the pixel type and the image dimension. This
change have been done in 

  ImageRegionSimpleIterator
  ImageLinearIterator
  ImageSliceIterator
  ImageIteratorWithIndex

That will broke code that currently use this iterators,
Sorry about that, it should be enough to change the
typedefs where you declare the iterators.




Thanks,


Luis





-------------- next part --------------
/**
 *  
 *  This program illustrates the use of Adaptors and
 *  Accessors
 *
 *  The example shows how an Adaptor can be used to 
 *  get acces only to thered component of an RGB image
 *  giving the appearance of being just a 'float' image
 *
 *  That will allow to pass the red component of this
 *  image as input or output to any filter that expects
 *  a float image
 *
 */


#include <itkImageAdaptor.h>
#include <itkScalar.h>
#include <itkImageRegionSimpleIterator.h>


//-------------------------------------
// Class RGB to be used as pixel type
//-------------------------------------
class RGB {
  public:
    float r;
    float g;
    float b;
  public:
    RGB() {
      r = g = b = 0.0;
    }
    RGB( float ir, float ig, float ib ) {
      r = ir;
      g = ig;
      b = ib;
    }
    const RGB & operator=( const RGB & c ) {
      r = c.r;
      g = c.g;
      b = c.b;
      return *this;
    }
};


//---------------------------------------------
// Accessor type that defines what part of the
// pixel type will be presented externally
//---------------------------------------------
class myRedAccessorType 
{
  public:
    typedef RGB     InternalType;
    typedef float   ExternalType;
    static inline void Set( InternalType & pixel, 
                            const ExternalType & value ) 
    {
      pixel.r = value;
    }

    static inline ExternalType Get( const InternalType & value )
    {
      return (ExternalType)(value.r);
    }
  
};



//-------------------------------------
//     Typedefs for convinience
//-------------------------------------
typedef itk::Image< RGB,   2 > myImageType;

typedef itk::ImageAdaptor< 
                  myImageType, 
                  myRedAccessorType > myRedAdaptorType;

typedef itk::ImageRegionSimpleIterator< 
                         myImageType > myIteratorType;

typedef itk::ImageRegionSimpleIterator< 
                         myRedAdaptorType > myRedIteratorType;



//-------------------------
//
//   Main code
//
//-------------------------
int main() {

  myImageType::Size size;
  size[0] = 2;
  size[1] = 2;

  myImageType::Index index;
  index[0] = 0;
  index[1] = 0;

  myImageType::Region region;
  region.SetIndex( index );
  region.SetSize(  size  );

  myImageType::Pointer myImage = myImageType::New();

  myImage->SetLargestPossibleRegion( region );
  myImage->SetBufferedRegion( region );
  myImage->SetRequestedRegion( region );
  myImage->Allocate();
  
  myIteratorType  it1( myImage, myImage->GetRequestedRegion() );
  
  // Value to initialize the pixels
  RGB color( 1.0, 0.5, 0.5 );
  
  // Initializing all the pixel in the image
  it1.Begin();
  while( !it1.IsAtEnd() )
  {
    it1.Set(color);
    ++it1;
  }

  // Reading the values to verify the image content
  it1.Begin();
  while( !it1.IsAtEnd() )
  {
    const RGB c = it1.Get();
    std::cout << c.r << "  " << c.g;
    std::cout << "  " << c.b << std::endl;
    ++it1;
  }


  myRedAdaptorType::Pointer myAdaptor = myRedAdaptorType::New();
  myAdaptor->SetImage( myImage );

 
  myRedIteratorType  it2( myAdaptor, myAdaptor->GetRequestedRegion() );

  // Set the values of the Red component of myImage, using myAdaptor
  it2.Begin();
  while( !it2.IsAtEnd() )
  {
    it2.Set(0.4);
    ++it2;
  }

  std::cout << "--- After --- " << std::endl;

  it1.Begin();
  while( !it1.IsAtEnd() )
  {
    const RGB c = it1.Get();
    std::cout << c.r << "  " << c.g;
    std::cout << "  " << c.b << std::endl;
    ++it1;
  }


  return 0;
}





More information about the Insight-developers mailing list