[Insight-users] How to transfer a set of 2D image data to a 3D image data?

HIRAKI Hideaki hhiraki at lab.nig.ac.jp
Thu, 05 Feb 2004 20:05:49 +0900

Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

vtkImageAppend in VTK can do it.
But if you want to process with itk::Image, 
the attached code may help you.


Hideaki Hiraki

"jiang" <jiang at TI.Uni-Trier.DE> wrote:
> Dear itk-users,
> I have a set of 2D image data. The type is, for example:
>   typedef   unsigned char                      PixelType;
>   typedef   itk::Image< InputPixelType, 2 >    ImageType;
> Now I want to transfer them to 3D image data:
>   typedef   itk::Image< InputPixelType, 3 >    VolumeType;
> Then transfer the volume to vtk data in order to render it. How should I do?
> Thanks a lot!
> Chunyan

Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="itkJoinSeriesImageFilter.h"


  Program:   Insight Segmentation & Registration Toolkit
  Module:    $RCSfile$
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even 
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
     PURPOSE.  See the above copyright notices for more information.

#ifndef __itkJoinSeriesImageFilter_h
#define __itkJoinSeriesImageFilter_h

#include "itkImageToImageFilter.h"

namespace itk

/** \class JoinSeriesImageFilter
 * \brief Join N-D images into an (N+1)-D image
 * Details should be described here.
 * \ingroup GeometricTransforms
template <class TInputImage, class TOutputImage>
class ITK_EXPORT JoinSeriesImageFilter:
    public ImageToImageFilter<TInputImage,TOutputImage>
  /** Standard class typedefs. */
  typedef JoinSeriesImageFilter  Self;
  typedef ImageToImageFilter<TInputImage,TOutputImage>  Superclass;
  typedef SmartPointer<Self>  Pointer;
  typedef SmartPointer<const Self>  ConstPointer;

  /** Method for creation through the object factory. */

  /** Run-time type information (and related methods). */
  itkTypeMacro(JoinSeriesImageFilter, ImageToImageFilter);

  /** Compiler can't inherit typedef? */
  typedef typename Superclass::InputImageType InputImageType;
  typedef typename Superclass::OutputImageType OutputImageType;
  typedef typename InputImageType::Pointer InputImagePointer;
  typedef typename OutputImageType::Pointer OutputImagePointer;
  typedef typename InputImageType::RegionType InputImageRegionType;
  typedef typename OutputImageType::RegionType OutputImageRegionType;

  /** Compiler can't inherit ImageDimension enumeration? */
  itkStaticConstMacro(InputImageDimension, unsigned int,
  itkStaticConstMacro(OutputImageDimension, unsigned int,

  /** IndexValueType is used to switch among the inputs and
   * is used as the index value of the new dimension */
  typedef unsigned int IndexValueType;

  /** Set/Get spacing of the new dimension */
  itkSetMacro(Spacing, double);
  itkGetMacro(Spacing, double);

  /** Set/Get origin of the new dimension */
  itkSetMacro(Origin, double);
  itkGetMacro(Origin, double);

  ~JoinSeriesImageFilter() {};
  void PrintSelf(std::ostream& os, Indent indent) const;

  /** Overrides GenerateOutputInformation() in order to produce
   * an image which has a different information than the first input.
   * \sa ProcessObject::GenerateOutputInformaton() */
  virtual void GenerateOutputInformation();

  /** Overrides GenerateInputRequestedRegion() in order to inform
   * the pipeline execution model of different input requested regions
   * than the output requested region.
   * \sa ImageToImageFilter::GenerateInputRequestedRegion() */
  virtual void GenerateInputRequestedRegion();

  /** JoinSeriesImageFilter can be implemented as a multithreaded filter.
   * \sa ImageSource::ThreadedGenerateData(),
   *     ImageSource::GenerateData() */
  virtual void ThreadedGenerateData(const OutputImageRegionType&
                                    outputRegionForThread, int threadId );

  JoinSeriesImageFilter(const Self&); //purposely not implemented
  void operator=(const Self&); //purposely not implemented

  double m_Spacing;
  double m_Origin;


} // end namespace itk
#include "itkJoinSeriesImageFilter.txx"

Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="itkJoinSeriesImageFilter.txx"

#ifndef _itkJoinSeriesImageFilter_txx
#define _itkJoinSeriesImageFilter_txx

#include "itkJoinSeriesImageFilter.h"
#include "itkProgressReporter.h"
#include "itkImageRegionConstIterator.h"
#include "itkImageRegionIterator.h"

namespace itk

template <class TInputImage, class TOutputImage>
  m_Spacing = 1.0;
  m_Origin = 0.0;

template <class TInputImage, class TOutputImage>
::PrintSelf(std::ostream& os, Indent indent) const

  os << indent << "Spacing: " << m_Spacing << std::endl;
  os << indent << "Origin: " << m_Origin << std::endl;

 * \sa UnaryFunctorImageFilter::GenerateOutputInformation()
template <class TInputImage, class TOutputImage>
  // do not call the superclass' implementation of this method since
  // this filter allows the input the output to be of different dimensions
  // get pointers to the input and output
  typename Superclass::OutputImagePointer      outputPtr = this->GetOutput();
  typename Superclass::InputImageConstPointer  inputPtr  = this->GetInput();

  if ( !outputPtr || !inputPtr)

  // Set the output image largest possible region.  Use a RegionCopier
  // so that the input and output images can be different dimensions.
  OutputImageRegionType outputLargestPossibleRegion;

  // for the new dimension, assuming the index has been set 0.

  outputPtr->SetLargestPossibleRegion( outputLargestPossibleRegion );

  // Set the output spacing and origin
  const ImageBase<InputImageDimension> *phyData;

    = dynamic_cast<const ImageBase<InputImageDimension>*>(this->GetInput());

  if (phyData)
    // Copy what we can from the image from spacing and origin of the input
    // This logic needs to be augmented with logic that select which
    // dimensions to copy
    unsigned int i;
    const typename InputImageType::SpacingType&
      inputSpacing = inputPtr->GetSpacing();
    const typename InputImageType::PointType&
      inputOrigin = inputPtr->GetOrigin();

    typename OutputImageType::SpacingType outputSpacing;
    typename OutputImageType::PointType outputOrigin;

    // copy the input to the output and fill the rest of the
    // output with zeros.
    for (i=0; i < InputImageDimension; ++i)
      outputSpacing[i] = inputSpacing[i];
      outputOrigin[i] = inputOrigin[i];
    for (; i < OutputImageDimension; ++i)
      outputSpacing[i] = 1.0;
      outputOrigin[i] = 0.0;

    // for the new dimension
    outputSpacing[InputImageDimension] = this->GetSpacing();
    outputOrigin[InputImageDimension] = this->GetOrigin();

    // set the spacing and origin
    outputPtr->SetSpacing( outputSpacing );
    outputPtr->SetOrigin( outputOrigin );
    // pointer could not be cast back down
    itkExceptionMacro(<< "itk::JoinSeriesImageFilter::GenerateOutputInformation "
                      << "cannot cast input to "
                      << typeid(ImageBase<InputImageDimension>*).name() );

template <class TInputImage, class TOutputImage>

  OutputImageRegionType outputRegion = this->GetOutput()->GetRequestedRegion();
  IndexValueType begin = outputRegion.GetIndex(InputImageDimension);
  IndexValueType end = begin + outputRegion.GetSize(InputImageDimension);
  for (IndexValueType idx = 0; idx < this->GetNumberOfInputs(); ++idx)
    InputImagePointer inputPtr = 
      const_cast<InputImageType *>(this->GetInput(idx));
    if ( !inputPtr )
      itkExceptionMacro(<< "missing input " << idx);

    InputImageRegionType inputRegion; // assuming default is null
    if ( begin <= idx && idx < end )
      this->CallCopyOutputRegionToInputRegion(inputRegion, outputRegion);

template <class TInputImage, class TOutputImage>
::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread,
                       int threadId)
  itkDebugMacro(<<"Actually executing");

  ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels());

  OutputImageRegionType outputRegion = outputRegionForThread;
  outputRegion.SetSize(InputImageDimension, 1);

  InputImageRegionType inputRegion;
  this->CallCopyOutputRegionToInputRegion(inputRegion, outputRegionForThread);

  IndexValueType begin = outputRegionForThread.GetIndex(InputImageDimension);
  IndexValueType end =
    begin + outputRegionForThread.GetSize(InputImageDimension);
  for (IndexValueType idx = begin; idx < end; ++idx)
    outputRegion.SetIndex(InputImageDimension, idx);
      outIt(this->GetOutput(), outputRegion);
      inIt(this->GetInput(idx), inputRegion);
    while( !outIt.IsAtEnd() )
      outIt.Set( inIt.Get() );

} // end namespace itk