[Insight-users] reading a vtk image

Will Schroeder will.schroeder@kitware.com
Thu, 11 Apr 2002 11:21:17 -0400


--=====================_-73023402==_
Content-Type: text/plain; charset="us-ascii"; format=flowed

Hi Pieter-

I've fixed the itkVTKImageIO reader in the beta branch. I also made some 
other changes to your example (use of std:: in front of cerr and endl; and 
the itkImageFileWriter requires an ImageIOBase subclass to be created). 
I''ll check them in later, in the mean time here are the changes. Please 
let me know immediately if you find problems.

Will

At 02:33 PM 4/11/2002 +0200, Pieter Vos wrote:
>Hi,
>
>Here are the file needed for the test.
>Good luck!
>
>Bye,
>
>Pieter Vos
>AZN Radboud
>Nijmegen
>The Netherlands

--=====================_-73023402==_
Content-Type: text/plain; charset="us-ascii"
Content-Disposition: attachment; filename="reader.cxx"

/*=========================================================================

Pieter Vos
AZN Radboud 
Nijmegen The Netherlands
mailto: pieterv@radiology.azn.nl

Thanks for the good work!

=========================================================================*/
#include <iostream>
#include "itkImageFileWriter.h"
#include "itkImageFileReader.h"
#include "itkVTKImageIO.h"
#include <itkImage.h>

// Define the dimension of the images
const unsigned int myDimension = 3;

//Declare the types of the images
typedef itk::Image<float, myDimension> FloatImageType;
  
int main()
{

  // Create a mapper (in this case a reader). A mapper
  // is templated on the input type.
  //
  itk::VTKImageIO::Pointer vtkIO;
  vtkIO = itk::VTKImageIO::New();

  // Create a source object (in this case a reader)
  itk::ImageFileReader<FloatImageType>::Pointer reader;
  reader = itk::ImageFileReader<FloatImageType>::New();
  reader->SetImageIO(vtkIO);
  std::cout <<"Getting file"<<std::endl;
  reader->SetFileName("sphere.vtk");
  try{
  	reader->Update();
  } catch (itk::ExceptionObject & e) {
    std::cerr << "exception in file reader " << std::endl;
    std::cerr << e.GetDescription() << std::endl;
    std::cerr << e.GetLocation() << std::endl;
    return EXIT_FAILURE;  
  }
  std::cout <<"Done with file"<<std::endl;
  
////////////Now write the file//////////////////////

  // Create a source object (in this case a writer)
  itk::VTKImageIO::Pointer vtkIO2;
  vtkIO2 = itk::VTKImageIO::New();

  itk::ImageFileWriter<FloatImageType>::Pointer writer;
  writer = itk::ImageFileWriter<FloatImageType>::New();
  writer->SetInput(reader->GetOutput());
  writer->SetFileName("sphere2.vtk");
  writer->SetImageIO(vtkIO2);

  try{
  	writer->Write();
  } catch (itk::ExceptionObject & e) {
    std::cerr << "exception in file writer " << std::endl;
    std::cerr << e.GetDescription() << std::endl;
    std::cerr << e.GetLocation() << std::endl;
    return EXIT_FAILURE;    	
  }
  return EXIT_SUCCESS;
}

--=====================_-73023402==_
Content-Type: text/plain; charset="us-ascii"
Content-Disposition: attachment; filename="itkVTKImageIO.h"

/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    $RCSfile: itkVTKImageIO.h,v $
  Language:  C++
  Date:      $Date: 2002/02/26 22:08:29 $
  Version:   $Revision: 1.5.2.1 $

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

  Portions of this code are covered under the VTK copyright.
  See VTKCopyright.txt or http://www.kitware.com/VTKCopyright.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 __itkVTKImageIO_h
#define __itkVTKImageIO_h

#include "itkImageIOBase.h"
#include <fstream>

namespace itk
{

class ITK_EXPORT VTKImageIO : public ImageIOBase
{
public:
  /** Standard class typedefs. */
  typedef VTKImageIO            Self;
  typedef ImageIOBase  Superclass;
  typedef SmartPointer<Self>  Pointer;
  
  /** Method for creation through the object factory. */
  itkNewMacro(Self);

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

  /*-------- This part of the interface deals with reading data. ------ */

  /** Determine the file type. Returns true if this ImageIO can read the
   * file specified. */
  virtual bool CanReadFile(const char*);
  
  /** Set the spacing and dimesion information for the current filename. */
  virtual void ReadImageInformation();
  
  /** Reads the data from disk into the memory buffer provided. */
  virtual void Read(void* buffer);

  /*-------- This part of the interfaces deals with writing data. ----- */

  /** Determine the file type. Returns true if this ImageIO can read the
   * file specified. */
  virtual bool CanWriteFile(const char*);

  /** Writes the data to disk from the memory buffer provided. Make sure
   * that the IORegion has been set properly. */
  virtual void Write(void* buffer);

protected:
  VTKImageIO();
  ~VTKImageIO();
  void PrintSelf(std::ostream& os, Indent indent) const;

  bool OpenVTKFileForReading(std::ifstream& os, const char* filename);
  bool OpenVTKFileForWriting(std::ofstream& os, const char* filename);
  void InternalReadImageInformation(std::ifstream& file);

private:
  VTKImageIO(const Self&); //purposely not implemented
  void operator=(const Self&); //purposely not implemented
};

} // end namespace itk

#endif // __itkVTKImageIO_h

--=====================_-73023402==_
Content-Type: text/plain; charset="us-ascii"
Content-Disposition: attachment; filename="itkImageFileWriter.txx"

/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    $RCSfile: itkImageFileWriter.txx,v $
  Language:  C++
  Date:      $Date: 2002/02/26 22:08:27 $
  Version:   $Revision: 1.5.2.1 $

  Copyright (c) 2002 Insight 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.

=========================================================================*/
#include "itkImageFileWriter.h"
#include "itkDataObject.h"
#include "itkImageIOFactory.h"
#include "itkCommand.h"

namespace itk
{

//---------------------------------------------------------
template <class TInputImage>
ImageFileWriter<TInputImage>
::ImageFileWriter():
  m_FileName(""),m_FilePrefix(""),m_FilePattern(""),
  m_ImageIO(0), m_UserSpecifiedImageIO(false),
  m_Region(0), m_UserSpecifiedRegion(false)
{
}


//---------------------------------------------------------
template <class TInputImage>
ImageFileWriter<TInputImage>
::~ImageFileWriter()
{
}

//---------------------------------------------------------
template <class TInputImage>
void 
ImageFileWriter<TInputImage>
::SetInput(InputImageType *input)
{
  this->ProcessObject::SetNthInput(0, input);
}


//---------------------------------------------------------
template <class TInputImage>
ImageFileWriter<TInputImage>::InputImagePointer
ImageFileWriter<TInputImage>
::GetInput()
{
  if (this->GetNumberOfInputs() < 1)
    {
    return 0;
    }
  
  return static_cast<TInputImage*>
                     (this->ProcessObject::GetInput(0).GetPointer());
}
  
//---------------------------------------------------------
template <class TInputImage>
ImageFileWriter<TInputImage>::InputImagePointer
ImageFileWriter<TInputImage>
::GetInput(unsigned int idx)
{
  return static_cast<TInputImage*>
                     (this->ProcessObject::GetInput(idx).GetPointer());
}

//---------------------------------------------------------
template <class TInputImage>
void 
ImageFileWriter<TInputImage>
::Write()
{
  InputImagePointer input = this->GetInput();
  if ( input == 0 )
    {
    itkExceptionMacro(<<"No input to writer!");
    return;
    }
  input->Update();

  if ( m_ImageIO == 0 )
    {
    itkExceptionMacro(<<"No ImageIO set, or none could be created.");
    return;
    }

  // Make sure region is within the image, crop if necessary
  ImageIORegion ioRegion(TInputImage::ImageDimension);
  ImageRegion<TInputImage::ImageDimension> region = 
        input->GetLargestPossibleRegion();
  const double *spacing = input->GetSpacing();
  const double *origin = input->GetOrigin();

  m_ImageIO->SetNumberOfDimensions(TInputImage::ImageDimension);
  for(unsigned int i=0; i<TInputImage::ImageDimension; i++)
    {
    ioRegion.SetSize(i,region.GetSize(i));
    ioRegion.SetIndex(i,region.GetIndex(i));
    m_ImageIO->SetDimensions(i,region.GetSize(i));
    m_ImageIO->SetSpacing(i,spacing[i]);
    m_ImageIO->SetOrigin(i,origin[i]);
    }

  this->Write(ioRegion);        
}

//---------------------------------------------------------
template <class TInputImage>
void 
ImageFileWriter<TInputImage>
::Write(const ImageIORegion &ioRegion)
{
  InputImagePointer input = this->GetInput();

  // make sure input is available
  if ( input == 0 )
    {
    itkExceptionMacro(<< "No input to writer!");
    return;
    }

  if ( m_ImageIO == 0 )
    {
    itkExceptionMacro(<<"No ImageIO set, or none could be created.");
    return;
    }

  // Check to see if we can write the file given the name or prefix
  //
  if ( m_FileName == "" && m_FilePrefix == "" )
    {
    itkExceptionMacro(<<"No filename or file prefix specified");
    return;
    }

  m_ImageIO->SetIORegion(ioRegion);

  // make sure the data is up-to-date
  input->Update();

  // Notify start event observers
  this->InvokeEvent( StartEvent() );

  // Actually do something
  this->GenerateData();
  
  // Notify end event observers
  this->InvokeEvent( EndEvent() );

  // Release upstream data if requested
  if ( this->GetInput(0)->ShouldIReleaseData() )
    {
    this->GetInput(0)->ReleaseData();
    }
}


//---------------------------------------------------------
template <class TInputImage>
void 
ImageFileWriter<TInputImage>
::GenerateData()
{
  InputImagePointer input = this->GetInput();

  itkDebugMacro(<<"Writing file" << m_FileName);
  
  // Make sure that the image is the right type and no more than 
  // four components.
  typedef typename InputImageType::PixelType ScalarType;

  // Set the pixel and component type; the number of components.
  m_ImageIO->SetPixelType(typeid(ScalarType));  

  // Setup the image IO for writing.
  //
  m_ImageIO->SetFileName(m_FileName.c_str());
  m_ImageIO->SetFilePrefix(m_FilePrefix.c_str());

  //okay, now extract the data as a raw buffer pointer
  void* dataPtr = (void*) input->GetBufferPointer();
  m_ImageIO->Write(dataPtr);

}


//---------------------------------------------------------
template <class TInputImage>
void 
ImageFileWriter<TInputImage>
::PrintSelf(std::ostream& os, Indent indent) const
{
  Superclass::PrintSelf(os,indent);

  os << indent << "File Name: " 
     << (m_FileName.data() ? m_FileName.data() : "(none)") << std::endl;
  os << indent << "File Prefix: " 
     << (m_FilePrefix.data() ? m_FilePrefix.data() : "(none)") << std::endl;
  os << indent << "File Pattern: " 
     << (m_FilePattern.data() ? m_FilePattern.data() : "(none)") << std::endl;

  os << indent << "Image IO: ";
  if ( m_ImageIO == 0 )
    {
    os << "(none)\n";
    }
  else
    {
    os << m_ImageIO << "\n";
    }
  
}

} // end namespace itk

--=====================_-73023402==_
Content-Type: text/plain; charset="us-ascii"
Content-Disposition: attachment; filename="itkVTKImageIO.cxx"

/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    $RCSfile: itkVTKImageIO.cxx,v $
  Language:  C++
  Date:      $Date: 2002/02/26 22:08:29 $
  Version:   $Revision: 1.7.2.1 $

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

  Portions of this code are covered under the VTK copyright.
  See VTKCopyright.txt or http://www.kitware.com/VTKCopyright.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.

=========================================================================*/
#include "itkVTKImageIO.h"
#include <cstdio>

namespace itk
{

VTKImageIO::VTKImageIO()
{
  this->SetNumberOfDimensions(2);
  m_ByteOrder = LittleEndian;
  m_FileType = ASCII;
  
}

VTKImageIO::~VTKImageIO()
{
}

bool VTKImageIO::OpenVTKFileForReading(std::ifstream& os, 
                                       const char* filename)
                                       
{
  // Make sure that we have a file to 
  if ( filename == "" )
    {
    itkExceptionMacro(<<"A FileName must be specified.");
    return false;
    }

  // Close file from any previous image
  if ( os.is_open() )
    {
    os.close();
    }
  
  // Open the new file for reading
  itkDebugMacro(<< "Initialize: opening file " << filename);

  // Actually open the file
  int openMode = std::ios::in;

#ifdef _WIN32
  openMode |= std::ios::binary;
#endif
#if defined(__GNUC__) && __GNUC__ >= 3
  os.open(filename, static_cast<std::ios_base::openmode>(openMode));
#else
  os.open(filename, openMode);
#endif
  if ( os.fail() )
    {
    itkExceptionMacro(<< "Could not open file for reading: " << filename);
    return false;
    }

  return true;
}

bool VTKImageIO::OpenVTKFileForWriting(std::ofstream& os, 
                                       const char* filename)
                                       
{
  // Make sure that we have a file to 
  if ( filename == "" )
    {
    itkExceptionMacro(<<"A FileName must be specified.");
    return false;
    }

  // Close file from any previous image
  if ( os.is_open() )
    {
    os.close();
    }
  
  // Open the new file for writing
  itkDebugMacro(<< "Initialize: opening file " << filename);

  // Actually open the file
  int openMode = std::ios::out;

#ifdef _WIN32
  openMode |= std::ios::binary;
#endif
#if defined(__GNUC__) && __GNUC__ >= 3
  os.open(filename, static_cast<std::ios_base::openmode>(openMode));
#else
  os.open(filename, openMode);
#endif
  if ( os.fail() )
    {
    itkExceptionMacro(<< "Could not open file for writing: " << filename);
    return false;
    }

  return true;
}


bool VTKImageIO::CanReadFile(const char* filename) 
{ 
  std::ifstream file;
  char buffer[256];
  std::string fname(filename);

  if ( fname.find(".vtk") >= fname.length() )
    {
    return false;
    }

  if ( ! this->OpenVTKFileForReading(file, filename) )
    {
    return false;
    }

  // Check to see if its a vtk structured points file
  file.getline(buffer,255);
  file.getline(buffer,255);
  file.getline(buffer,255);
  file.getline(buffer,255);

  fname = buffer;

  if ( fname.find("STRUCTURED_POINTS") < fname.length() ||
       fname.find("structured_points") < fname.length() )
    {
    return true;
    }
  else
    {
    return false;
    }
}
  
 
void VTKImageIO::InternalReadImageInformation(std::ifstream& file)
{
  char line[255];
  std::string text;

  if ( ! this->OpenVTKFileForReading(file, m_FileName.c_str()) )
    {
    itkExceptionMacro(<< "Cannot read requested file");
    }

  file.getline(line,255);
  file.getline(line,255);
  file.getline(line,255);
  text = line;
  if ( text.find("ASCII") < text.length() || 
       text.find("ascii") < text.length() )
    {
    this->SetFileTypeToASCII();
    }
  else if ( text.find("BINARY") < text.length() ||
            text.find("binary") < text.length() )
    {
    this->SetFileTypeToBinary();
    }
  else
    {
    itkExceptionMacro(<< "Unrecognized type");
    }
  file.getline(line,255);
  text = line;
  if ( text.find("STRUCTURED_POINTS") >= text.length() &&
       text.find("structured_points") >= text.length() )
    {
    itkExceptionMacro(<< "Not structured points, can't read");
    }

  //extract dimensions, spacing, origin
  unsigned int dims[3];
  float spacing[3];
  float origin[3];
  file.getline(line,255);
  text = line;
  int i;

  if ( text.find("DIMENSIONS") < text.length() || 
       text.find("dimensions") < text.length() )
    {
    sscanf(line, "%*s %d %d %d", dims, dims+1, dims+2);
    if ( dims[2] <= 1 )
      {
      this->SetNumberOfDimensions(2);
      }
    else
      {
      this->SetNumberOfDimensions(3);
      }
    for ( i=0; i < m_NumberOfDimensions; i++ )
      {
      m_Dimensions[i] = dims[i];
      }
    }
  else
    {
    itkExceptionMacro(<<"No dimensions defined");
    }

  // set values in case we don't find them
  m_Spacing[0] = 1.0;
  m_Spacing[1] = 1.0;
  m_Spacing[2] = 1.0;

  m_Origin[0] = 0.0;
  m_Origin[1] = 0.0;
  m_Origin[2] = 0.0;

  file.getline(line,255);
  text = line;

  for ( bool readScalars=false; !readScalars; )
    {
    if ( text.find("SPACING") < text.length() || 
         text.find("spacing") < text.length() )
      {
      sscanf(line, "%*s %f %f %f", spacing, spacing+1, spacing+2);
      for ( i=0; i < m_NumberOfDimensions; i++ )
        {
        m_Spacing[i] = spacing[i];
        }
      }

    else if ( text.find("ORIGIN") < text.length() || 
              text.find("origin") < text.length() )
      {
      sscanf(line, "%*s %f %f %f", origin, origin+1, origin+2);
      for ( i=0; i < m_NumberOfDimensions; i++ )
        {
        m_Origin[i] = origin[i];
        }
      }
  
    else if ( text.find("SCALARS") < text.length() || 
              text.find("scalars") < text.length() )
      {
      readScalars = true;

      char pixelType[256];
      sscanf(line, "%*s %*s %s", pixelType);
      text = pixelType;
      if ( text.find("float") < text.length() )
        {
        SetPixelType(FLOAT);
        SetComponentType(FLOAT);
        }
      else if ( text.find("double") < text.length() )
        {
        SetPixelType(DOUBLE);
        SetComponentType(DOUBLE);
        }
      else if ( text.find("unsigned_char") < text.length() )
        {
        SetPixelType(UCHAR);
        SetComponentType(UCHAR);
        }
      else if ( text.find("char") < text.length() )
        {
        SetPixelType(CHAR);
        SetComponentType(CHAR);
        }
      else if ( text.find("unsigned_short") < text.length() )
        {
        SetPixelType(USHORT);
        SetComponentType(USHORT);
        }
      else if ( text.find("short") < text.length() )
        {
        SetPixelType(SHORT);
        SetComponentType(SHORT);
        }
      else if ( text.find("unsigned_int") < text.length() )
        {
        SetPixelType(UINT);
        SetComponentType(UINT);
        }
      else if ( text.find("int") < text.length() )
        {
        SetPixelType(INT);
        SetComponentType(INT);
        }
      else if ( text.find("unsigned_long") < text.length() )
        {
        SetPixelType(ULONG);
        SetComponentType(ULONG);
        }
      else if ( text.find("long") < text.length() )
        {
        SetPixelType(LONG);
        SetComponentType(LONG);
        }
      else
        {
        itkExceptionMacro(<<"Unrecognized type");
        }
      }//found scalars
    
      file.getline(line,255);
      text = line;
      }
}

void VTKImageIO::Read(void* buffer)
{
  std::ifstream file;

  this->InternalReadImageInformation(file);
  
  //We are positioned at the data. The data is read depending on whether 
  //it is ASCII or binary.
  if ( m_FileType == ASCII )
    {
    this->ReadBufferAsASCII(file, buffer, this->GetComponentType(),
                            this->GetImageSizeInComponents());
    }
  else
    {
    file.read(static_cast<char*>(buffer), this->GetImageSizeInBytes());
    }
}

void VTKImageIO::ReadImageInformation()
{
  std::ifstream file;
  this->InternalReadImageInformation(file);
}

bool VTKImageIO::CanWriteFile(const char*)
{
  if ( m_FileName != "" &&
       m_FileName.find(".vtk") < m_FileName.length() )
    {
    return true;
    }
  return false;
}

void VTKImageIO::Write(void* buffer)
{
  std::ofstream file;
  if ( ! this->OpenVTKFileForWriting(file,m_FileName.c_str()) )
    {
    return;
    }

  // Check the image region for proper dimensions, etc.
  unsigned int numDims = this->GetNumberOfDimensions();
  if ( numDims < 2 || numDims > 3 )
    {
    itkExceptionMacro(<<"VTK Writer can only write 2 or 3-dimensional images");
    return;
    }
  ImageIORegion ioRegion = this->GetIORegion();

  // Write the VTK header information
  file << "# vtk DataFile Version 3.0\n"; 
  file << "VTK File Generated by Insight Segmentation and Registration Toolkit (ITK)\n";

  if ( this->GetFileType() == ASCII ) { file << "ASCII\n"; }
  else { file << "BINARY\n"; }

  // Write characteristics of the data
  file << "DATASET STRUCTURED_POINTS\n";
  if ( numDims == 2 )
    {
    file << "DIMENSIONS " << this->GetDimensions(0) << " "
         << this->GetDimensions(1) << " 1\n";
    file << "SPACING " << m_Spacing[0] << " " << m_Spacing[1] << " 1.0\n";
    file << "ORIGIN " << m_Origin[0] << " " << m_Origin[1] << " 0.0\n";
    }
  else //numDims == 3
    {
    file << "DIMENSIONS " << this->GetDimensions(0) << " "
         << this->GetDimensions(1) << " " << this->GetDimensions(2) << "\n";
    file << "SPACING " << m_Spacing[0] << " " 
         << m_Spacing[1] << " " << m_Spacing[2] << "\n";
    file << "ORIGIN " << m_Origin[0] << " "
         << m_Origin[1] << " " << m_Origin[2] << "\n";
    }

  file << "POINT_DATA " << this->GetImageSizeInPixels() << "\n";
  file << "SCALARS scalars " 
       << this->ReturnTypeAsString(this->GetComponentType()) << " "
       << this->GetNumberOfComponents() << "\n";
  file << "LOOKUP_TABLE default\n";

  // Write the actual pixel data
  if ( m_FileType == ASCII )
    {
    this->WriteBufferAsASCII(file, buffer, this->GetComponentType(),
                            this->GetImageSizeInComponents());
    }
  else //binary
    {
    file.write(static_cast<char*>(buffer), this->GetImageSizeInBytes());
    }
}

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


} // end namespace itk

--=====================_-73023402==_--