[Insight-users] IO factory creation problem for writing
Luis Ibanez
luis . ibanez at kitware . com
Tue, 18 Jun 2002 17:26:34 -0400
Hi Hans,
Thanks for your feedback,
We are working on the integration of the changes (fixes)
that you proposed. We will be back soon.
Thanks
Luis
===================================================
Hans J. Johnson wrote:
> Hello,
>
> PROBLEM #1
> ==========
> There is a possible design problem with the way automatic
> XXXImageIOFactory works for writing of images. If you want the
> ImageFileWriter to determine the output image type automatically, the
> current implementation may fail.
> The problem is that when itk::ImageFileWriter tries to Write the image,
> it fails to find a suitable derived class of ImageIOBase. The failure
> occurs because the write function calls CreateImageIO, which then calls
> CanReadFile to determine if it is an accepable derived ImageIOBase is
> found. For this to work properly, the CreateImageIO function needs to
> call CanWriteFile from the class derived from ImageIOBase when doing the
> Write operation, and CanReadFile when doing the Read operation.
>
> CALLTREE:
> itk::PNGImageIO::CanReadFile,
> itk::ImageIOFactory::CreateImageIO,
> itk::ImageFileWriter<itk::Image<unsigned char,(unsigned int)2> >::Write
>
> I have attached a simple test to demonstrate this. Notice that if you
> first create an image that can be read, then you can use the automatic
> mechanism to write the image.
>
> Example outputs from enclosed program:
>
> [hjohnson@robin FileWriteTest]$ FileWriteTest
> Determining file output type automatically (should be PNG)
> Problem found while writing image ./newtest.png
> Unknown
> itk::ERROR: ImageFileWriter(0x8107db0): No ImageIO set, or none could be
> created.
>
> [hjohnson@robin FileWriteTest]$ FileWriteTest "BeExplicit"
> Explicitly setting file output to PNG
> File: ./newtest.png
> Image ./newtest.png Written To Disk
>
> [hjohnson@robin FileWriteTest]$ FileWriteTest
> Determining file output type automatically (should be PNG)
> File: ./newtest.png
> Image ./newtest.png Written To Disk
>
> [hjohnson@robin FileWriteTest]$ rm newtest.png
> [hjohnson@robin FileWriteTest]$ FileWriteTest
> Determining file output type automatically (should be PNG)
> Problem found while writing image ./newtest.png
> Unknown
> itk::ERROR: ImageFileWriter(0x8107db0): No ImageIO set, or none could be
> created.
>
> SOLUTION:
> ==========
> Replace function called CreateImageIO with function called CreateImageIO
> Reader, then duplicate
> that function into one called CreateImageIOWriter that is exactly the
> same except that it uses CanWriteFile() call instead of CanReadFile() call.
>
> This change only affects the following four files (including all of the
> examples):
> ./Code/IO/itkImageIOFactory.h
> ./Code/IO/itkImageIOFactory.cxx
> ./Code/IO/itkImageFileReader.txx
> ./Code/IO/itkImageFileWriter.txx
>
> patches to implement the described changes are attached to this document.
>
>
> PROBLEM #2
> ===========
> PNGImageIO::CanWriteFile(const char * filename)
> add one line ---> m_FileName=filename;
> SOLUTION
> =========
> Apply patches attached to this e-mail.
>
>
> PROBLEM #3
> ===========
> MetaImageIO::Write() not finished
> SOLUTION
> =========
> Finish writing this. I can do this if it has not yet been done.
>
> Regards,
> Hans J. Johnson
> hans-johnson@uiowa.edu
>
> PS: Is there some other more efficient way to get changes committed to
> the CVS repository? Is it possible to get CVS write access?
>
> PPS: I have written a file reader for Analyze v7.5 file format. It has
> been tested for both reading and writing of images. If anybody else
> needs this, just send me an e-mail.
>
>
>
>
> ------------------------------------------------------------------------
>
> PROJECT(FileWriteTest)
>
> #
> # Find ITK
> #
> FIND_PATH( ITK_BINARY_DIR itkConfigure.h )
>
> # Load in the values from ITK if found
> IF ( ITK_BINARY_DIR )
> LOAD_CACHE(${ITK_BINARY_DIR})
> INCLUDE (${ITK_SOURCE_DIR}/itkCMakeOptions.cmake)
> ENDIF (ITK_BINARY_DIR )
>
>
> INCLUDE_DIRECTORIES(
> ${ITK_SOURCE_DIR}/Code/BasicFilters
> ${ITK_SOURCE_DIR}/Code/Algorithms
> ${CMAKE_INSTALL_PREFIX}/include
> )
>
> LINK_DIRECTORIES(
> ${ITK_BINARY_DIR}/Code/Common
> ${ITK_BINARY_DIR}/Code/IO
> ${CMAKE_INSTALL_PREFIX}/lib
> )
>
> LINK_LIBRARIES (
> VXLNumerics
> ITKCommon
> ITKIO
> )
>
>
> ADD_EXECUTABLE(FileWriteTest FileWriteTest )
>
>
>
> ------------------------------------------------------------------------
>
> /*=========================================================================
> Program: FileWriteTest
> Module: $RCSfile: FileWriteTest.cxx,v $
> Language: C++
> \author Hans J. Johnson
> // This project is designed to test if you write out an image file
> // based on the image extension alone.
> =========================================================================*/
>
>
> #include "itkImage.h"
> #include "itkImageFileWriter.h"
> #include "itkImageIOFactory.h"
> #include "itkPNGImageIOFactory.h"
> #include "itkPNGImageIO.h"
>
> int main(int argc, char *argv[])
> {
> //Allocate Images
> enum { ImageDimension = itk::Image<unsigned char,2>::ImageDimension };
> const itk::Image<unsigned char,2>::SizeType size = {{100,100}};
> const itk::Image<unsigned char,2>::IndexType index = {{0,0}};
> itk::Image<unsigned char,2>::RegionType region;
> region.SetSize( size );
> region.SetIndex( index );
>
> itk::Image<unsigned char,2>::Pointer img = itk::Image<unsigned char,2>::New();
> img->SetLargestPossibleRegion( region );
> img->SetBufferedRegion( region );
> img->SetRequestedRegion( region );
> img->Allocate();
>
> itk::PNGImageIOFactory::RegisterOneFactory();
> itk::ImageFileWriter< itk::Image<unsigned char,2> >::Pointer ImageWriterPointer = itk::ImageFileWriter< itk::Image<unsigned char,2> > ::New();
>
> //Set the output filename
> char outputFileName[] = "./newtest.png";
> ImageWriterPointer->SetFileName(outputFileName);
> //Not Necessary if using file extensions to determine. ImageWriterPointer->SetImageIO( Analyzeio );
> //Make a png image writer
> itk::PNGImageIO::Pointer pngio;
> if(argc>1)
> {
> std::cout << "Explicitly setting file output to PNG"<< std::endl;
> pngio= itk::PNGImageIO::New();
> ImageWriterPointer->SetImageIO( pngio );
> }
> else
> {
> std::cout << "Determining file output type automatically (should be PNG)"<< std::endl;
> }
>
> //Attach input image to the writer.
> ImageWriterPointer->SetInput( img );
> //Determine file type and instantiate appropriate ImageIO class if not
> //explicitly stated with SetImageIO, then write to disk.
> try {
> ImageWriterPointer->Write();
> std::cout <<" Image "<< outputFileName << " Written To Disk" << std::endl;
> }
> catch ( itk::ExceptionObject & ex )
> {
> std::string message;
> message = "Problem found while writing image ";
> message += outputFileName;
> message += "\n";
> message += ex.GetLocation();
> message += "\n";
> message += ex.GetDescription();
> std::cerr << message << std::endl;
> }
> return 0;
> }
>
>
> ------------------------------------------------------------------------
>
> --- itkPNGImageIO.h.old Tue Jun 18 14:04:42 2002
> +++ itkPNGImageIO.h Tue Jun 18 14:05:20 2002
> @@ -48,7 +48,7 @@
>
> /** Determine the file type. Returns true if this ImageIO can read the
> * file specified. */
> - virtual bool CanReadFile(const char*);
> + virtual bool CanReadFile(const char * FileNameToCheck);
>
> /** Set the spacing and diemention information for the set filename. */
> virtual void ReadImageInformation();
> @@ -68,7 +68,7 @@
>
> /** Determine the file type. Returns true if this ImageIO can read the
> * file specified. */
> - virtual bool CanWriteFile(const char*);
> + virtual bool CanWriteFile(const char* FileNameToCheck);
>
> /** Writes the spacing and dimentions of the image.
> * Assumes SetFileName has been called with a valid file name. */
>
>
> ------------------------------------------------------------------------
>
> --- itkPNGImageIO.cxx.old Tue Jun 18 14:04:48 2002
> +++ itkPNGImageIO.cxx Tue Jun 18 14:06:49 2002
> @@ -41,9 +41,10 @@
>
>
>
> -bool PNGImageIO::CanReadFile(const char* file)
> -{
> - PNGFileWrapper pngfp(file,"rb");
> +bool PNGImageIO::CanReadFile(const char* FileNameToCheck)
> +{
> + m_FileName=FileNameToCheck;
> + PNGFileWrapper pngfp(FileNameToCheck,"rb");
> FILE* fp = pngfp.m_FilePointer;
> if(!fp)
> {
> @@ -367,8 +368,9 @@
> return;
> }
>
> -bool PNGImageIO::CanWriteFile(const char*)
> +bool PNGImageIO::CanWriteFile(const char * FileNameToCheck)
> {
> + m_FileName=FileNameToCheck;
> if ( m_FileName != "" &&
> m_FileName.find(".png") < m_FileName.length() )
> {
>
>
> ------------------------------------------------------------------------
>
> --- itkImageIOFactory.h.old Tue Jun 18 13:36:27 2002
> +++ itkImageIOFactory.h Tue Jun 18 13:36:27 2002
> @@ -43,7 +43,8 @@
> typedef ::itk::ImageIOBase::Pointer ImageIOBasePointer;
>
> /** Create the appropriate ImageIO depending on the particulars of the file. */
> - static ImageIOBasePointer CreateImageIO(const char* path);
> + static ImageIOBasePointer CreateImageIOReader(const char* path);
> + static ImageIOBasePointer CreateImageIOWriter(const char* path);
>
> protected:
> ImageIOFactory();
>
>
> ------------------------------------------------------------------------
>
> --- itkImageIOFactory.cxx.old Tue Jun 18 13:36:27 2002
> +++ itkImageIOFactory.cxx Tue Jun 18 13:36:27 2002
> @@ -19,11 +19,10 @@
>
> namespace itk
> {
> -
>
> -
> +
> ImageIOBase::Pointer
> -ImageIOFactory::CreateImageIO(const char* path)
> +ImageIOFactory::CreateImageIOReader(const char* path)
> {
> std::list<ImageIOBase::Pointer> possibleImageIO;
> std::list<LightObject::Pointer> allobjects =
> @@ -50,6 +49,38 @@
> {
> return *k;
> }
> + }
> + return 0;
> +}
> +
> +ImageIOBase::Pointer
> +ImageIOFactory::CreateImageIOWriter(const char* path)
> +{
> + std::list<ImageIOBase::Pointer> possibleImageIO;
> + std::list<LightObject::Pointer> allobjects =
> + ObjectFactoryBase::CreateAllInstance("itkImageIOBase");
> + for(std::list<LightObject::Pointer>::iterator i = allobjects.begin();
> + i != allobjects.end(); ++i)
> + {
> + ImageIOBase* io = dynamic_cast<ImageIOBase*>(i->GetPointer());
> + if(io)
> + {
> + possibleImageIO.push_back(io);
> + }
> + else
> + {
> + std::cerr << "Error ImageIO factory did not return an ImageIOBase: "
> + << (*i)->GetNameOfClass()
> + << std::endl;
> + }
> + }
> + for(std::list<ImageIOBase::Pointer>::iterator k = possibleImageIO.begin();
> + k != possibleImageIO.end(); ++k)
> + {
> + if((*k)->CanWriteFile(path))
> + {
> + return *k;
> + }
> }
> return 0;
> }
>
>
> ------------------------------------------------------------------------
>
> --- itkImageFileWriter.txx.old Tue Jun 18 13:36:27 2002
> +++ itkImageFileWriter.txx Tue Jun 18 13:36:27 2002
> @@ -101,7 +101,7 @@
>
> if ( m_ImageIO == 0 ) //try creating via factory
> {
> - m_ImageIO = ImageIOFactory::CreateImageIO(m_FileName.c_str());
> + m_ImageIO = ImageIOFactory::CreateImageIOWriter(m_FileName.c_str());
> }
>
> if ( m_ImageIO == 0 )
>
>
> ------------------------------------------------------------------------
>
> --- itkImageFileReader.txx.old Tue Jun 18 13:36:27 2002
> +++ itkImageFileReader.txx Tue Jun 18 13:36:27 2002
> @@ -82,7 +82,7 @@
> if ( m_ImageIO == 0 ) //try creating via factory
> {
> m_UserSpecified = false;
> - m_ImageIO = ImageIOFactory::CreateImageIO(m_FileName.c_str());
> + m_ImageIO = ImageIOFactory::CreateImageIOReader(m_FileName.c_str());
> }
> else
> {
>
> CMakeLists.txt
>
> Content-Type:
>
> text/plain
> Content-Encoding:
>
> 7bit
>
>
> ------------------------------------------------------------------------
> FileWriteTest.cxx
>
> Content-Type:
>
> text/plain
> Content-Encoding:
>
> 7bit
>
>
> ------------------------------------------------------------------------
> itkPNGImageIO.h.patch
>
> Content-Type:
>
> text/plain
> Content-Encoding:
>
> 7bit
>
>
> ------------------------------------------------------------------------
> itkPNGImageIO.cxx.patch
>
> Content-Type:
>
> text/plain
> Content-Encoding:
>
> 7bit
>
>
> ------------------------------------------------------------------------
> itkImageIOFactory.h.patch
>
> Content-Type:
>
> text/plain
> Content-Encoding:
>
> 7bit
>
>
> ------------------------------------------------------------------------
> itkImageIOFactory.cxx.patch
>
> Content-Type:
>
> text/plain
> Content-Encoding:
>
> 7bit
>
>
> ------------------------------------------------------------------------
> itkImageFileWriter.txx.patch
>
> Content-Type:
>
> text/plain
> Content-Encoding:
>
> 7bit
>
>
> ------------------------------------------------------------------------
> itkImageFileReader.txx.patch
>
> Content-Type:
>
> text/plain
> Content-Encoding:
>
> 7bit
>
>