[Insight-users] template instantation patterns?

Luis Ibanez luis.ibanez@kitware.com
Wed, 06 Nov 2002 10:26:48 -0500


Hi Harri,

This is a sensitive topic that has been raised
on the past, in particular by Jarek Sacha.
(you may want to look in the list archives
for the subject "roadmap for ITK development")

There is no total concensus about how this
*should* be done. Here are the basic options
and some of the arguments behind them.

1) Decide the image types at compile time
2) Decide the image types at run time

Option (1) is what ITK is now.
Option (2) is what VTK is using.

VTK also uses templates for managing multiple
types of images but the templated code is hidden
inside .cxx files and is selected with switch
statements. The VTK user is not directly exposed
to the image type. VTK users can however explicitly
specify the image type to be used by a particular
filter. This is certainly convenient for users
because it simplifies development, speeds up
compilation and facilitates wrapping for interpreted
languages.

ITK, on the other hand, fully expose the templated
code and forces the user to make decisions about
specific types. The trade-off followed in ITK is
to make type conversion only during IO and display.

The ImageFileReader<> in ITK is able to read files
containing images of different types but will always
convert the input data to a type specified by the
user at compile time. This allows to have the
flexibility of loading different types of files, yet
knowing how the data will be processed in the pipeline.
You may want to take a look at the Insight/Code/IO
directory and the ImageIO classes that implement
the type conversions at run time. This includes
byte swapping and castings.

My personal argument in favor of the ITK way is
that the main purpouse of ITK is Medical Image
Processing. ITK is not Photoshop. The representation
type used for medical data is not a trivial issue.
There are good reasons for deciding to use 16 bits/pixel
for a mamography, namely: If there is a calcification
present, you will see it in 16 bits and you won't see
it in 8 bits. That makes the difference between
realizing that a patient has cancer or not. This
binary fact is certainly more important than the
programmer's compfort while developing an application.

Hidding pixel type decisions expose applications to
the risk of using undesirable types for processing the
image. You don't want a filter in the pipeline making
decisions about casting a mamogram to 8 bits without
you being fully aware of this happening.

One intermediate option is to combine in a single
application sections of code that allow for run time
type selection (e.g. IO / Display ) then adding
casting filters (itk::CastImageFilter<>) to connect
these sections to others where the types are fully
specified. You can even go to the point of defining
traits for your entire application and making the
application be a class templated over those traits.
This last option has the advantage of collecting
all the types in a single section of code from which
you can control the setup of the whole application.

You can see an example of an application templated
over a type in:

   Insight/Examples/MultiResMIRegistration/Common

Take a look at the file:

   MIMApplicationBase.h

where a full set of template parameters are used.
The same set is then reduced in SimpleApp.h and
finally it is instantiated in:

     MultiResMIRegistration.cxx

NOTE that the "Examples" directory has recently
been renamed "Applications". If you are using a
recent cvs checkout, the file in question will
be located in

Insight/Applications/MultiResMIRegistration/Common


----


Please let us know if you have further questions,


Thanks


     Luis


=================================================

Harri Tapio Jaalinoja wrote:
> Hi!
> 
> This is not directly related to ITK, more a generic programming problem,
> but since ITK uses templates a lot, maybe you have encountered something
> similar:
> 
> I use BSoft library to read in image files. The package takes care of
> getting the endianess, data type etc correctly, and returns me a struct
> that includes among other things a pointer to the data and an enumeration
> that tells me the type of data.
> 
> My code now looks something like this:
> 
>   // BSoft library call to read the image file
>   Bimage* p = read_img(argv[1], 0, -1);
> 
>   itk::ImportImageFilter<float, 3>::Pointer breader =
>     itk::ImportImageFilter<float, 3>::New();
> 
>   // here is the pointer to the image data
>   float* data = (float *)p->data;
>   breader->SetImportPointer(data ,p->x * p->y * p->z, false);
> 
> This compiles ok.
> 
> The problem above obviously is that it states directly that the data type
> is "float", when it can be many other things as well. Can you suggest an
> elegant way to code this in a way that allows the data type be set at
> runtime? Do I just have to copy the above snippet in switch cases for all
> the possible data types? Or maybe make a template of the above, so at
> least the switch cases will be a bit smaller? Actually the code that would
> go in the switch case is longer, since I would also have to declare all
> the filters along the pipeline in the same manner.
> 
> Thanks for your input!
> 
> Harri
> 
> _______________________________________________
> Insight-users mailing list
> Insight-users@public.kitware.com
> http://public.kitware.com/mailman/listinfo/insight-users
> 
>