Proposals:Adding Streaming Support in ITK Image Writing

From KitwarePublic
Jump to navigationJump to search

Update: Preliminary ITK image write streaming support has been added in 3.16.0

Examples can be found in

Examples/IO/VisibleHumanPasteWrite.cxx
Examples/IO/VisibleHumanStreamReadWrite.cxx

The default behaviour is to stream by splitting the highest non-singleton dimension according to the number of desired streams set on the ImageFileWriter. Only a few output image formats have write streaming capabilites at this time. MetaImage can perform write streaming.

Background

This page describes the changes that are needed in ITK ImageIO classes and the ImageFileWriter in order to support streaming.

Streaming infrastructure is already available for Reading. However only a couple of ImageIO classes fully implement support for this functionality.

This page host discussions on how streaming could be implemented for writing images. The nuance is that the ImageFileWriter should become the class that selects the image pieces and request them in sequence to the pipeline. This should be done, presumably, in collaboration with the ImageIO class that manage the image file format at hand.

Current Implementation

The current implementation has the following methods:

void ImageFileWriter::SetIORegion(const ImageIORegion & region);
virtual void ImageIOBase::SetIORegion (ImageIORegion _arg);
virtual void ImageIOBase::SetUseStreamedWriting (bool _arg);
  • These methods allows two types of streaming, updating a small subregion aka pasting, and iteratively streaming the entire image.
  • The problem with the way it is currently written is that its a rather low level method and not robust. Specifically the pipeline must be manually configured and executed before the specific ImageIORegion is written.
  • If the incoming Image to ImageFileWrite does not match the expected region ( i.e. the incoming filer does not stream) erroneous results will be generated.
  • Conversely, if the expected region matches but the class does not support streaming the the ImageIO will read outside it's bounds.
  • In addition the user must select an appropriate set of regions which are compatible with the ImageIO class and iterate the pipeline over those.
  • Also the behavior of what happens when a file exist, either of a matching format or differ, is not defined and problematic.

itkMetaImageStreamingWriterIOTest.cxx contains a sample usage.

Challenges

  • Maintaining backwards compatibility with the current functionality
  • defining what the current functionality is
  • Maintaining ROI information with the image (disk ROI != image->region)
  • Inserting into an existing image on disk that has a different pixel type
  • Extending the size of an image file on disk
  • Compression (zseek) - convert to uncompressed and then insert (and then recompress?)
  • itkImageToVTKImageFilter support

Classes

ImageFileWriter

  • Needs to be able drive the pipeline similar to StreamingImageFilter
  • Should be robust in handling unrequested regions
  • Support for just updating a subregion
  • Support for streaming entire image
  • New interface methods should follow exitsing conventions of ImageFileReader and StreamingImageFilter:
virtual void 	StreamingImageFilter::SetNumberOfStreamDivisions (unsigned int _arg);
virtual const bool & 	ImageFileReader::Set/GetUseStreaming (...)
virtual void 	ImageFileReader::UseStreamingOn/Off ()
  • The Set/Get Streaming methods are not needed, they are implicit. If the number of divisions 0 or 1 then there is not streaming, otherwise there is a request for a certain number of divisions
void SetPasteRegionIO(const ImageIORegion&)
  • This is a better name for the functionality of SetRegionIO. We are going to non-exclusively break the two types of stream (pasting a subimage, and iteratively streaming) to be controlled by the SetPasteRegionIO, and SetNumberOfStreamDivisions
void SetRegionIO(const ImageIORegion &)
  • The old functionality is not clear, this method will be marked as depreciated, and will just call SetPasteRegionIO

ImageIO

  • Don't use a class for splitting integrate the methods into the interface
virtual unsigned int GetActualNumberOfSplitsForWriting(unsigned int numberOfRequestedSplits,
                                                        const ImageIORegion &pasteRegion,
                                                        const ImageIORegion &largestPossibleRegion) const;
 virtual ImageIORegion GetSplitRegionForWriting(unsigned int ithPiece, 
                                                unsigned int numberOfActualSplits,
                                                const ImageIORegion &pasteRegion,
                                                const ImageIORegion &largestPossibleRegion) const;
  • What should the default behavior of these methods be?
  • Currently most ImageIO derived classes ignore the IORegion, potentially producing erroneous results when the buffer doesn't match *bug?*
  • for robust behavior one would expect an exception to be thrown when pasting an IORegion because over writing the whole image could destroy data!

ImageRegionSpliter vs ImageIORegionSpliter

  • Neither! The ImageRegionSpliter is a stateless class, this functionality can easily be integrated into ImageIOBase as const functions

Specific Formats

MetaImage

Nifti

MINC2