[ITK] templating typdef question

Matt McCormick matt.mccormick at kitware.com
Wed Oct 29 17:28:19 EDT 2014


Hi Bernhard,

Welcome to ITK!

The basic strategy is to put all the templated code in a template
function or class.  This prevents duplicated code (the root of almost
all evil).  Then, use a switch statement and call the appropriate
templates.  An example is here [1], which is long because it switches
over both a number of pixel types and dimensions, but it demonstrates
the idea.

Inside the templated code, use for loops instead explicit assignment
to set each dimension value.  Also, use code like

  Image::SpacingType spacing;
  spacing.Fill( 1.0 );

instead of

  itk::SpacePrecisionType spacing[2];
  spacing[0] = 1.0;
  spacing[1] = 1.0;

Hope this helps,
Matt


[1] http://itk.org/ITKExamples/src/IO/ImageBase/ReadUnknownImageType/Documentation.html

On Wed, Oct 29, 2014 at 5:03 PM, Dr Bernhard Schaffer
<bschaffer at superstem.org> wrote:
> Hi,
>
> This is my second email to this list. I’m still not so familiar with
> typedefs in coding, and I’ve the current problem:
>
>
>
> I have my own “image” objects which can be 2D or 3D and of different number
> type.  If I assume they are only 2D and float I can do something like this:
>
> (The cyan lines show methods of  ‘my’ object.)
>
>
>
>
>
> const unsigned int DIMENSION = 2;
>
>
>
>           typedef itk::ImportImageFilter<float, DIMENSION >
> ImportFilterType;
>
> ImportFilterType::Pointer importFilter = ImportFilterType::New();
>
>
>
> ImportFilterType::SizeType  size;
>
>           size[0]  = MYIMAGE.GetXSIZE();
>
> size[1]  = MYIMAGE.GetYSIZE();
>
>
>
>           ImportFilterType::IndexType start;
>
>           start.Fill( 0 );
>
>
>
>           ImportFilterType::RegionType region;
>
>           region.SetIndex( start );
>
>           region.SetSize(  size  );
>
> importFilter->SetRegion( region );
>
>
>
> const itk::SpacePrecisionType origin[ DIMENSION ] = { 0.0, 0.0 };
>
>           importFilter->SetOrigin( origin );
>
>
>
>           const itk::SpacePrecisionType  spacing[ DIMENSION ] =  { 1.0, 1.0
> };
>
> importFilter->SetSpacing( spacing );
>
>
>
>           const bool importImageFilterWillOwnTheBuffer = false;
>
>
>
>           float *localBuffer = MYIMAGE.GETPOINTER();
>
>           importFilter->SetImportPointer( localBuffer, size[0]*size[1],
> importImageFilterWillOwnTheBuffer );
>
>
>
>           typedef itk::Image< float,DIMENSION >   InputImageType;
>
>           typedef itk::Image< float,DIMENSION >   OutputImageType;
>
>
>
>           typedef itk::CurvatureFlowImageFilter< InputImageType,
> OutputImageType >  FilterType;
>
>           FilterType::Pointer filter = FilterType::New();
>
>
>
>           filter->SetInput( importFilter->GetOutput() );
>
>           filter->SetTimeStep( timeStep );
>
>           filter->SetNumberOfIterations( iterations );
>
>           filter->Update();
>
>           typedef itk::ImageRegionIterator< OutputImageType >
> IteratorType;
>
>           OutputImageType::Pointer filtered = filter->GetOutput();
>
>           […]
>
>
>
> If my image is 3D I can do accordingly: (Yellow is the difference to above)
>
>
>
> const unsigned int DIMENSION = 3;
>
>
>
>           typedef itk::ImportImageFilter<float, DIMENSION >
> ImportFilterType;
>
> ImportFilterType::Pointer importFilter = ImportFilterType::New();
>
>
>
> ImportFilterType::SizeType  size;
>
>           size[0]  = MYIMAGE.GetXSIZE();
>
> size[1]  = MYIMAGE.GetYSIZE();
>
> size[2]  = MYIMAGE.GetZSIZE();
>
>
>
>
>
>           ImportFilterType::IndexType start;
>
>           start.Fill( 0 );
>
>
>
>           ImportFilterType::RegionType region;
>
>           region.SetIndex( start );
>
>           region.SetSize(  size  );
>
> importFilter->SetRegion( region );
>
>
>
> const itk::SpacePrecisionType origin[ DIMENSION ] = { 0.0, 0.0, 0.0 };
>
>           importFilter->SetOrigin( origin );
>
>
>
>           const itk::SpacePrecisionType  spacing[ DIMENSION ] =  { 1.0, 1.0,
> 1.0 };
>
> importFilter->SetSpacing( spacing );
>
>
>
>           const bool importImageFilterWillOwnTheBuffer = false;
>
> float *localBuffer = MYIMAGE.GETPOINTER();
>
>           importFilter->SetImportPointer( localBuffer,
> size[0]*size[1]*size[2], importImageFilterWillOwnTheBuffer );
>
>
>
>           typedef itk::Image< float,DIMENSION >   InputImageType;
>
>           typedef itk::Image< float,DIMENSION >   OutputImageType;
>
>
>
>           typedef itk::CurvatureFlowImageFilter< InputImageType,
> OutputImageType >  FilterType;
>
>           FilterType::Pointer filter = FilterType::New();
>
>
>
>           filter->SetInput( importFilter->GetOutput() );
>
>           filter->SetTimeStep( timeStep );
>
>           filter->SetNumberOfIterations( iterations );
>
>           filter->Update();
>
>           typedef itk::ImageRegionIterator< OutputImageType >
> IteratorType;
>
>           OutputImageType::Pointer filtered = filter->GetOutput();
>
>           […]
>
>
>
> The problem I have is the following. I can query my object about its
> dimensionality, but I can’t do the following:
>
>
>
> const unsigned int DIMENSION = MYIMAGE.GETDIMENSIONALITY();
>
>
>
> because the typedefs are evaluated on compilation not on runtime.   So my
> way around this is, to actually duplicate  all the code and have both my
> examples in a switch-case:
>
>
>
>           switch(MYIMAGE.GETDIMENSIONALITY())
>
>           {
>
>           case(2):
>
>                     {
>
> … EXAMPLE 2D as above
>
> }
>
>                    break;
>
>           case(3):
>
>                     {
>
> … EXAMPLE 3D as above
>
> }
>
>                    break;
>
> }
>
>
>
> Which is rather obvious code duplication. Is there a better way to do this?
> (there has to!)  The problem branches out, if I also allow the type float to
> be specified by my object as in
>
>           switch(MYIMAGE.GETDATATYPE())
>
>           {
>
>           case(1):…float…;
>
>           case(2):…double…;
>
>           case(3):…
>
>>
> }
>
>
>
>
>
> I would very much appreciate a few lines of (pseudo-) code showing me how I
> can do this better.
>
>
>
> Thank you very much,
>
>    Best regards,
>
>    Bernhard
>
>
>
>
> _______________________________________________
> Community mailing list
> Community at itk.org
> http://public.kitware.com/mailman/listinfo/community
>


More information about the Community mailing list