diff --git a/ChangeLog.md b/ChangeLog.md index b922c77879..5ce4c2ff89 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -65,6 +65,8 @@ the camera center). (Bertrand Kerautret [#1070](https://github.com/DGtal-team/DGtal/pull/1070)) + - Adding raw I/O capabilities for non integral types and signed integers. + (Roland Denis [#1084](https://github.com/DGtal-team/DGtal/pull/1084)) ## Bug Fixes diff --git a/src/DGtal/io/doc/moduleIO.dox b/src/DGtal/io/doc/moduleIO.dox index c1566e6db1..91b587b405 100644 --- a/src/DGtal/io/doc/moduleIO.dox +++ b/src/DGtal/io/doc/moduleIO.dox @@ -99,7 +99,10 @@ Hence, for image writers, some functors may return a DGtal::Color or a scalar | | Longvol | Volumetric file format (long) | the functor should return a DGtal::uint64_t | LongvolWriter | Simplevol project, http://liris.cnrs.fr/david.coeurjolly | | | HDF5 | HDF5 file with 3D UInt8 image dataset(s) | the functor should return a DGtal::uint8_t | HDF5Writer | with @a WITH_HDF5 build flag, http://www.hdfgroup.org/HDF5/ | | | any 3D ITK format | Any 3D ITK image | the functor should return a ITKIOTrait::ValueOut | ITKWriter | with @a WITH_ITK build flag, http://www.itk.org/ | -| nD | Raw8 | raw binary file format on 8bits | the functor should return an unsigned char | RawWriter | | +| nD | Raw8 | raw binary file format on 8bits | the functor should return an unsigned char | RawWriter | | +| | Raw16 | raw binary file format on 16bits | the functor should return an unsigned short | RawWriter | | +| | Raw32 | raw binary file format on 32bits | the functor should return an unsigned int | RawWriter | | +| | Raw | raw binary file format for any type | the functor should return the same type as specified in the template parameter of RawWriter::exportRaw | RawWriter | | @note Since DGtal doesn't integrate ITK by default, ITK image should by writen directly using the ITKWriter class. @@ -113,7 +116,7 @@ For scalar value format (PGM, Vol, Longvol, Raw, ...), the associated template c -The class GenericWriter (DGtal/io/reader/GenericWriter.h) allows to +The class GenericWriter allows to automatically export any image (2d, 3d, nd) from its filename. The class is templated with an image container type, a dimension value (given by default by the image container dimension), a value type, (also given @@ -180,7 +183,9 @@ DGtal::GenericWriter >::expo | | HDF5 | HDF5 file with 3D UInt8 image dataset(s) | HDF5Reader | with @a WITH_HDF5 build flag, http://www.hdfgroup.org/HDF5/ | | | any 3D ITK format | Any file format in the ITK library (mhd, mha, ...) | ITKReader | with @a WITH_ITK build flag, http://www.itk.org/ | | nD | Raw8 | raw binary file format on 8bits | RawReader | | +| | Raw16 | raw binary file format on 16bits | RawReader | | | | Raw32 | raw binary file format on 32bits | RawReader | | +| | Raw | raw binary file format for any type | RawReader | | @note Since DGtal doesn't integrate ITK by default, ITK image should by read directly using the ITKReader class. @code @@ -188,7 +193,7 @@ DGtal::GenericWriter >::expo @endcode -The class GenericReader (DGtal/io/reader/GenericReader.h) allows to +The class GenericReader allows to automatically import any image (2d, 3d, nd) from its filename. The class is templated with an image container type, a dimension value (given by default by the image container dimension), a value type, diff --git a/src/DGtal/io/readers/GenericReader.h b/src/DGtal/io/readers/GenericReader.h index 2a4e052c97..f5186dad03 100644 --- a/src/DGtal/io/readers/GenericReader.h +++ b/src/DGtal/io/readers/GenericReader.h @@ -119,7 +119,7 @@ namespace DGtal * Template partial specialisation for volume images of dimension 3 **/ template - struct GenericReader + struct GenericReader { BOOST_CONCEPT_ASSERT(( concepts::CImage )) ; /** @@ -154,42 +154,50 @@ namespace DGtal static TContainer importWithValueFunctor(const std::string &filename, const TFunctor &aFunctor, unsigned int x=0, - unsigned int y=0, unsigned int z=0) throw(DGtal::IOException){ - BOOST_CONCEPT_ASSERT(( concepts::CUnaryFunctor )) ; - DGtal::IOException dgtalio; - std::string extension = filename.substr(filename.find_last_of(".") + 1); - - if(extension=="vol") - return VolReader::importVol( filename, aFunctor ); - - if(extension=="longvol") - return LongvolReader::importLongvol( filename, aFunctor ); - - if(extension=="pgm3d"|| extension=="pgm3D" || extension=="p3d" || extension=="pgm") - return PGMReader::importPGM3D(filename, aFunctor); - - if(extension=="raw") - { - ASSERT(x!=0 && y!=0 && z!=0); - typename TContainer::Point pt (x,y,z); - return RawReader< TContainer, TFunctor >::importRaw8 ( filename, pt, aFunctor ); - } + unsigned int y=0, unsigned int z=0) throw( DGtal::IOException ) + { + BOOST_CONCEPT_ASSERT(( concepts::CUnaryFunctor )) ; + DGtal::IOException dgtalio; + const std::string extension = filename.substr(filename.find_last_of(".") + 1); + + if ( extension == "vol" ) + { + return VolReader::importVol( filename, aFunctor ); + } + else if ( extension == "longvol" ) + { + return LongvolReader::importLongvol( filename, aFunctor ); + } + else if ( extension == "pgm3d" || extension == "pgm3D" || extension == "p3d" || extension == "pgm" ) + { + return PGMReader::importPGM3D(filename, aFunctor); + } + else if ( extension == "raw" ) + { + ASSERT( x != 0 && y != 0 && z != 0 ); + typename TContainer::Point const pt (x, y, z); + return RawReader< TContainer, TFunctor >::template importRaw( filename, pt, aFunctor ); + } #ifdef WITH_HDF5 - if (extension=="h5") - return HDF5Reader::importHDF5_3D(filename, "UInt8Array3D", aFunctor); + if ( extension == "h5" ) + return HDF5Reader::importHDF5_3D(filename, "UInt8Array3D", aFunctor); #endif #ifdef WITH_ITK - if(extension=="dcm") - return DicomReader::importDicom(filename, aFunctor); - if(extension=="mha" || extension=="mhd") - return ITKReader::importITK(filename, aFunctor); + if ( extension == "dcm" ) + { + return DicomReader::importDicom(filename, aFunctor); + } + else if ( extension == "mha" || extension == "mhd" ) + { + return ITKReader::importITK(filename, aFunctor); + } #endif - trace.error() << "Extension " << extension<< " not yet implemented in DGtal GenericReader." << std::endl; - throw dgtalio; - } + trace.error() << "Extension " << extension<< " in 3D, not yet implemented in DGtal GenericReader." << std::endl; + throw dgtalio; + } }; @@ -234,31 +242,37 @@ namespace DGtal static TContainer importWithValueFunctor(const std::string &filename, const TFunctor &aFunctor, unsigned int x=0, - unsigned int y=0, unsigned int z=0) throw(DGtal::IOException){ - BOOST_CONCEPT_ASSERT(( concepts::CUnaryFunctor )) ; - DGtal::IOException dgtalio; - std::string extension = filename.substr(filename.find_last_of(".") + 1); - - if(extension=="longvol") - return LongvolReader::importLongvol( filename, aFunctor ); - - if(extension=="raw") - { - ASSERT(x!=0 && y!=0 && z!=0); - typename TContainer::Point pt (x,y,z); - return RawReader< TContainer, TFunctor >::importRaw32 ( filename, pt, aFunctor ); - } + unsigned int y=0, unsigned int z=0) throw( DGtal::IOException ) + { + BOOST_CONCEPT_ASSERT(( concepts::CUnaryFunctor )) ; + DGtal::IOException dgtalio; + const std::string extension = filename.substr( filename.find_last_of(".") + 1 ); + + if ( extension == "longvol" ) + { + return LongvolReader::importLongvol( filename, aFunctor ); + } + else if ( extension == "raw" ) + { + ASSERT( x != 0 && y != 0 && z != 0 ); + typename TContainer::Point const pt (x, y, z); + return RawReader< TContainer, TFunctor >::importRaw32 ( filename, pt, aFunctor ); + } #ifdef WITH_ITK - if(extension=="dcm") - return DicomReader::importDicom(filename, aFunctor); - if(extension=="mha" || extension=="mhd") - return ITKReader::importITK(filename, aFunctor); + if ( extension == "dcm" ) + { + return DicomReader::importDicom(filename, aFunctor); + } + else if ( extension == "mha" || extension == "mhd" ) + { + return ITKReader::importITK(filename, aFunctor); + } #endif - trace.error() << "Extension " << extension<< " not yet implemented in DGtal GenericReader." << std::endl; - throw dgtalio; - } + trace.error() << "Extension " << extension<< " not yet implemented in DGtal GenericReader." << std::endl; + throw dgtalio; + } }; @@ -299,39 +313,39 @@ namespace DGtal **/ template static TContainer importWithColorFunctor(const std::string &filename, - const TFunctor &aFunctor, + const TFunctor &aFunctor, unsigned int x=0, - unsigned int y=0) throw(DGtal::IOException) - { - BOOST_CONCEPT_ASSERT(( concepts::CUnaryFunctor )) ; - DGtal::IOException dgtalio; - //Getting image extension - std::string extension = filename.substr(filename.find_last_of(".") + 1); - - if(extension=="ppm") - return PPMReader::importPPM(filename, aFunctor); - - if(extension=="raw"){ - ASSERT(x!=0 && y!=0); - typename TContainer::Point pt (x,y); - return RawReader< TContainer, TFunctor >::importRaw8 ( filename, pt , aFunctor); - } - - - if( extension=="gif" || extension=="jpg" || extension=="png" || extension=="jpeg" || extension=="bmp") - { + unsigned int y=0) throw( DGtal::IOException ) + { + BOOST_CONCEPT_ASSERT(( concepts::CUnaryFunctor )) ; + DGtal::IOException dgtalio; + //Getting image extension + const std::string extension = filename.substr( filename.find_last_of(".") + 1 ); + + if ( extension == "ppm" ) + { + return PPMReader::importPPM(filename, aFunctor); + } + else if ( extension == "raw" ) + { + ASSERT( x != 0 && y != 0 ); + typename TContainer::Point const pt (x,y); + return RawReader< TContainer, TFunctor >::template importRaw( filename, pt, aFunctor); + } + else if ( extension == "gif" || extension == "jpg" || extension == "png" || extension == "jpeg" || extension == "bmp" ) + { #ifdef WITH_MAGICK - MagickReader reader; - return reader.importImage( filename, aFunctor ); + MagickReader reader; + return reader.importImage( filename, aFunctor ); #else - trace.error() << "Extension " << extension<< " not yet implemented in DGtal but you can add Magick option to deal with this image type." << std::endl; - throw dgtalio; + trace.error() << "Extension " << extension<< " not yet implemented in DGtal but you can add Magick option to deal with this image type." << std::endl; + throw dgtalio; #endif - } + } - trace.error() << "Extension " << extension<< " not yet implemented in DGtal GenericReader." << std::endl; - throw dgtalio; - } + trace.error() << "Extension " << extension<< " in 2D, not yet implemented in DGtal GenericReader." << std::endl; + throw dgtalio; + } /** @@ -348,32 +362,34 @@ namespace DGtal template static TContainer importWithValueFunctor(const std::string &filename, const TFunctor &aFunctor, unsigned int x=0, - unsigned int y=0) throw(DGtal::IOException){ - BOOST_CONCEPT_ASSERT(( concepts::CUnaryFunctor )) ; - - DGtal::IOException dgtalio; - //Getting image extension - std::string extension = filename.substr(filename.find_last_of(".") + 1); - - if(extension=="raw"){ - ASSERT(x!=0 && y!=0); - typename TContainer::Point pt (x,y); - return RawReader< TContainer, TFunctor >::importRaw8 ( filename, pt, aFunctor ); - } - - - if(extension=="pgm") - return PGMReader::importPGM(filename, aFunctor); + unsigned int y=0) throw( DGtal::IOException ) + { + BOOST_CONCEPT_ASSERT(( concepts::CUnaryFunctor )) ; + + DGtal::IOException dgtalio; + //Getting image extension + const std::string extension = filename.substr( filename.find_last_of(".") + 1 ); + + if ( extension == "raw" ) + { + ASSERT( x!= 0 && y != 0); + typename TContainer::Point const pt (x,y); + return RawReader< TContainer, TFunctor >::importRaw8( filename, pt, aFunctor ); + } + else if ( extension == "pgm" ) + { + return PGMReader::importPGM(filename, aFunctor); + } #ifdef WITH_HDF5 - if (extension=="h5") - return HDF5Reader::importHDF5(filename, "image8bit", aFunctor); + if (extension=="h5") + return HDF5Reader::importHDF5(filename, "image8bit", aFunctor); #endif - trace.error() << "Extension " << extension<< " not yet implemented in DGtal GenericReader." << std::endl; - throw dgtalio; + trace.error() << "Extension " << extension<< " not yet implemented in DGtal GenericReader." << std::endl; + throw dgtalio; - } + } }; @@ -417,33 +433,37 @@ namespace DGtal static TContainer importWithColorFunctor(const std::string &filename, const TFunctor &aFunctor, unsigned int x=0, unsigned int y=0) throw(DGtal::IOException) -{ - //warnings - BOOST_VERIFY(x==x); - BOOST_VERIFY(y==y); - - BOOST_CONCEPT_ASSERT(( concepts::CUnaryFunctor )) ; - DGtal::IOException dgtalio; - //Getting image extension - std::string extension = filename.substr(filename.find_last_of(".") + 1); - - if(extension=="ppm") - return PPMReader::importPPM(filename, aFunctor); - - if( extension=="gif" || extension=="jpg" || extension=="png" || extension=="jpeg" || extension=="bmp") - { + { + + BOOST_CONCEPT_ASSERT(( concepts::CUnaryFunctor )) ; + DGtal::IOException dgtalio; + //Getting image extension + const std::string extension = filename.substr(filename.find_last_of(".") + 1); + + if ( extension == "ppm" ) + { + return PPMReader::importPPM(filename, aFunctor); + } + else if ( extension == "raw" ) + { + ASSERT( x != 0 && y != 0 ); + typename TContainer::Point const pt (x,y); + return RawReader< TContainer, TFunctor >::template importRaw( filename, pt, aFunctor); + } + else if ( extension == "gif" || extension == "jpg" || extension == "png" || extension == "jpeg" || extension == "bmp" ) + { #ifdef WITH_MAGICK - MagickReader reader; - return reader.importImage( filename, aFunctor ); + MagickReader reader; + return reader.importImage( filename, aFunctor ); #else - trace.error() << "Extension " << extension<< " not yet implemented in DGtal but you can add Magick option to deal with this image type." << std::endl; - throw dgtalio; + trace.error() << "Extension " << extension<< " not yet implemented in DGtal but you can add Magick option to deal with this image type." << std::endl; + throw dgtalio; #endif - } + } - trace.error() << "Extension " << extension<< " not yet implemented in DGtal GenericReader." << std::endl; - throw dgtalio; - } + trace.error() << "Extension " << extension<< " not yet implemented in DGtal GenericReader." << std::endl; + throw dgtalio; + } /** @@ -452,38 +472,41 @@ namespace DGtal * * @tparam TFunctor The type of the functor (should verify the concept CUnaryFunctor ). * @param aFunctor to transform input unsigned char of image value into the given image type. - * + * ** @param x specify the x image size to be used with raw format. * @param y specify the y image size to be used with raw format. **/ template static TContainer importWithValueFunctor(const std::string &filename, const TFunctor &aFunctor, unsigned int x=0, - unsigned int y=0) throw(DGtal::IOException){ - BOOST_CONCEPT_ASSERT(( concepts::CUnaryFunctor )) ; - - DGtal::IOException dgtalio; - //Getting image extension - std::string extension = filename.substr(filename.find_last_of(".") + 1); - - if(extension=="raw"){ - ASSERT(x!=0 && y!=0); - typename TContainer::Point pt (x,y); - return RawReader< TContainer, TFunctor >::importRaw32 ( filename, pt, aFunctor ); - } - - if(extension=="pgm") - return PGMReader::importPGM(filename, aFunctor); + unsigned int y=0) throw(DGtal::IOException) + { + BOOST_CONCEPT_ASSERT(( concepts::CUnaryFunctor )) ; + + DGtal::IOException dgtalio; + //Getting image extension + const std::string extension = filename.substr(filename.find_last_of(".") + 1); + + if ( extension == "raw" ) + { + ASSERT( x != 0 && y != 0); + typename TContainer::Point const pt (x,y); + return RawReader< TContainer, TFunctor >::importRaw8 ( filename, pt, aFunctor ); + } + else if ( extension == "pgm ") + { + return PGMReader::importPGM(filename, aFunctor); + } #ifdef WITH_HDF5 - if (extension=="h5") - return HDF5Reader::importHDF5(filename, "image8bit", aFunctor); + if (extension=="h5") + return HDF5Reader::importHDF5(filename, "image8bit", aFunctor); #endif - trace.error() << "Extension " << extension<< " not yet implemented in DGtal GenericReader." << std::endl; - throw dgtalio; + trace.error() << "Extension " << extension<< " not yet implemented in DGtal GenericReader." << std::endl; + throw dgtalio; - } + } }; diff --git a/src/DGtal/io/readers/GenericReader.ih b/src/DGtal/io/readers/GenericReader.ih index a544a42d7e..f032bb3cdd 100644 --- a/src/DGtal/io/readers/GenericReader.ih +++ b/src/DGtal/io/readers/GenericReader.ih @@ -34,30 +34,29 @@ /////////////////////////////////////////////////////////////////////////////// // IMPLEMENTATION of inline functions. - - - - template inline TContainer -DGtal::GenericReader::import(const std::string &filename, - std::vector dimSpace) throw(DGtal::IOException){ +DGtal::GenericReader:: +import( const std::string & filename, + std::vector dimSpace + ) throw( DGtal::IOException ) +{ DGtal::IOException dgtalio; - std::string extension = filename.substr(filename.find_last_of(".") + 1); - if(extension!="raw") + const std::string extension = filename.substr( filename.find_last_of(".") + 1 ); + if ( extension != "raw" ) { - trace.error() << "Extension " << extension<< " not yet implemented in n dimension for DGtal GenericReader (only raw images are actually implemented in Nd." << std::endl; + trace.error() << "Extension " << extension << " not yet implemented in " << TDim << "D for DGtal GenericReader (only raw images are actually implemented in Nd using any value type)." << std::endl; throw dgtalio; } else { typename TContainer::Point aPointDim; - for(unsigned int i=0; i< dimSpace.size(); i++) + for ( unsigned int i = 0; i < dimSpace.size(); i++) { - aPointDim[i]= dimSpace[i]; + aPointDim[ i ] = dimSpace[ i ]; } - return RawReader< TContainer >::importRaw8 ( filename, aPointDim ); + return RawReader< TContainer >::template importRaw ( filename, aPointDim ); } } @@ -66,34 +65,41 @@ DGtal::GenericReader::import(const std::string &filena template inline TContainer -DGtal::GenericReader::import(const std::string &filename, - unsigned int x, unsigned int y, unsigned int z) throw(DGtal::IOException) +DGtal::GenericReader:: +import( const std::string & filename, + unsigned int x, + unsigned int y, + unsigned int z + ) throw( DGtal::IOException ) { DGtal::IOException dgtalio; - std::string extension = filename.substr(filename.find_last_of(".") + 1); + const std::string extension = filename.substr( filename.find_last_of(".") + 1 ); - if(extension=="vol") - return VolReader::importVol( filename ); - - if(extension=="longvol") - return LongvolReader::importLongvol( filename ); - - if(extension=="pgm3d"|| extension=="pgm3D" ||extension=="p3d" || extension=="pgm") - return PGMReader::importPGM3D(filename); - - if(extension=="raw") + if ( extension == "vol" ) { - ASSERT(x!=0 && y!=0 && z!=0); - typename TContainer::Point pt (x,y,z); - return RawReader< TContainer >::importRaw8 ( filename, pt ); + return VolReader::importVol( filename ); + } + else if ( extension == "longvol" ) + { + return LongvolReader::importLongvol( filename ); + } + else if ( extension == "pgm3d" || extension == "pgm3D" || extension == "p3d" || extension == "pgm" ) + { + return PGMReader::importPGM3D( filename ); + } + else if ( extension == "raw" ) + { + ASSERT( x != 0 && y != 0 && z != 0 ); + typename TContainer::Point const pt(x, y, z); + return RawReader< TContainer >::template importRaw( filename, pt ); } #ifdef WITH_HDF5 - if (extension=="h5") - return HDF5Reader::importHDF5_3D(filename, "UInt8Array3D"); + if ( extension == "h5" ) + return HDF5Reader::importHDF5_3D( filename, "UInt8Array3D" ); #endif - trace.error() << "Extension " << extension<< " not yet implemented in DGtal GenericReader." << std::endl; + trace.error() << "Extension " << extension << " in 3D, not yet implemented in DGtal GenericReader." << std::endl; throw dgtalio; } @@ -102,24 +108,29 @@ DGtal::GenericReader::import(const std::string &filename, template inline TContainer -DGtal::GenericReader::import(const std::string &filename, - unsigned int x, unsigned int y, unsigned int z) throw(DGtal::IOException) +DGtal::GenericReader:: +import( const std::string & filename, + unsigned int x, + unsigned int y, + unsigned int z + ) throw( DGtal::IOException ) { DGtal::IOException dgtalio; - std::string extension = filename.substr(filename.find_last_of(".") + 1); - - if(extension=="longvol") - return LongvolReader::importLongvol( filename ); + const std::string extension = filename.substr( filename.find_last_of(".") + 1 ); - if(extension=="raw") + if ( extension == "longvol" ) + { + return LongvolReader::importLongvol( filename ); + } + else if ( extension == "raw" ) { - ASSERT(x!=0 && y!=0 && z!=0); - typename TContainer::Point pt (x,y,z); + ASSERT( x != 0 && y != 0 && z != 0 ); + typename TContainer::Point const pt(x, y, z); return RawReader< TContainer >::importRaw32 ( filename, pt ); } - trace.error() << "Extension " << extension<< " not yet implemented in DGtal GenericReader." << std::endl; + trace.error() << "Extension " << extension << " with DGtal::uint32_t in 3D, not yet implemented in DGtal GenericReader." << std::endl; throw dgtalio; } @@ -128,32 +139,37 @@ DGtal::GenericReader::import(const std::string & template inline TContainer -DGtal::GenericReader::import(const std::string &filename, - unsigned int x, unsigned int y) throw(DGtal::IOException) +DGtal::GenericReader:: +import( const std::string &filename, + unsigned int x, + unsigned int y + ) throw( DGtal::IOException ) { DGtal::IOException dgtalio; //Getting image extension - std::string extension = filename.substr(filename.find_last_of(".") + 1); - - if(extension=="pgm") - return PGMReader::importPGM(filename); - - if(extension=="ppm") - return PPMReader::importPPM(filename); - - if(extension=="raw"){ - ASSERT(x!=0 && y!=0); - typename TContainer::Point pt (x,y); - return RawReader< TContainer >::importRaw8 ( filename, pt ); - } + const std::string extension = filename.substr( filename.find_last_of(".") + 1 ); + if ( extension == "pgm" ) + { + return PGMReader::importPGM(filename); + } + else if ( extension == "ppm" ) + { + return PPMReader::importPPM(filename); + } + else if ( extension == "raw" ) + { + ASSERT( x != 0 && y != 0 ); + typename TContainer::Point const pt (x, y); + return RawReader::template importRaw( filename, pt ); + } #ifdef WITH_HDF5 - if (extension=="h5") + if ( extension == "h5" ) return HDF5Reader::importHDF5(filename, "image8bit"); #endif - if( extension=="gif" || extension=="jpg" || extension=="png" || extension=="jpeg" || extension=="bmp") + if( extension == "gif" || extension == "jpg" || extension == "png" || extension == "jpeg" || extension == "bmp" ) { #ifdef WITH_MAGICK MagickReader reader; @@ -164,7 +180,7 @@ DGtal::GenericReader::import(const std::string &filename, #endif } - trace.error() << "Extension " << extension<< " not yet implemented in DGtal GenericReader." << std::endl; + trace.error() << "Extension " << extension<< " in 2D, not yet implemented in DGtal GenericReader." << std::endl; throw dgtalio; } @@ -173,27 +189,32 @@ DGtal::GenericReader::import(const std::string &filename, template inline TContainer -DGtal::GenericReader::import(const std::string &filename, - unsigned int x, unsigned int y) - throw(DGtal::IOException) +DGtal::GenericReader:: +import( const std::string &filename, + unsigned int x, + unsigned int y + ) throw( DGtal::IOException ) { DGtal::IOException dgtalio; //Getting image extension - std::string extension = filename.substr(filename.find_last_of(".") + 1); + const std::string extension = filename.substr( filename.find_last_of(".") + 1 ); - if(extension=="ppm") - return PPMReader::importPPM(filename); - - if(extension=="pgm") - return PGMReader::importPGM(filename); - - if(extension=="raw"){ - ASSERT(x!=0 && y!=0); - typename TContainer::Point pt (x,y); - return RawReader< TContainer >::importRaw32 ( filename, pt ); - } + if ( extension == "ppm" ) + { + return PPMReader::importPPM(filename); + } + else if ( extension == "pgm" ) + { + return PGMReader::importPGM(filename); + } + else if ( extension == "raw" ) + { + ASSERT( x != 0 && y != 0); + typename TContainer::Point const pt (x,y); + return RawReader::importRaw32( filename, pt ); + } - if( extension=="gif" || extension=="jpg" || extension=="png" || extension=="jpeg" || extension=="bmp") + if ( extension == "gif" || extension == "jpg" || extension == "png" || extension == "jpeg" || extension == "bmp" ) { #ifdef WITH_MAGICK MagickReader reader; @@ -204,7 +225,7 @@ DGtal::GenericReader::import(const std::string & #endif } - trace.error() << "Extension " << extension<< " not yet implemented in DGtal GenericReader." << std::endl; + trace.error() << "Extension " << extension<< " with DGtal::uint32_t in 2D, not yet implemented in DGtal GenericReader." << std::endl; throw dgtalio; } diff --git a/src/DGtal/io/readers/RawReader.h b/src/DGtal/io/readers/RawReader.h index e80b8f86ac..33bcd7a65b 100644 --- a/src/DGtal/io/readers/RawReader.h +++ b/src/DGtal/io/readers/RawReader.h @@ -55,22 +55,26 @@ namespace DGtal // template class RawReader /** * Description of template class 'RawReader'

- * \brief Aim: implements methods to read a "Vol" file format. + * \brief Aim: Raw binary import of an Image. * - * The main import method "importRaw8" returns an instance of the template - * parameter TImageContainer. + * The import methods \c importRaw8, \c importRaw16 and \c importRaw32 read raw files (little-endian format) + * containing unsigned integer values of, respectively, 8 bits, 16 bits and 32 bits width. + * The method \c importRaw can read any type of values, signed integers, floating point types or + * even structures. + * + * All these methods return an instance of the template parameter \c TImageContainer. A functor can be specified to convert raw values to image values. * * Example usage: * @code * ... - * typedef SpaceND Space3; - * typedef HyperRectDomain TDomain; + * typedef DGtal::SpaceND Space3; + * typedef DGtal::HyperRectDomain TDomain; * typedef TDomain::Point Point; * * //Default image container = STLVector - * typedef ImageSelector::Type Image; + * typedef DGtal::ImageSelector::Type Image; * - * RawReader reader; + * DGtal::RawReader reader; * Image image = reader.importRaw8("data.raw"); * * trace.info() << image <) . * + * @see RawWriter * @see testRawReader.cpp */ template #include ////////////////////////////////////////////////////////////////////////////// @@ -116,7 +117,8 @@ FILE* DGtal::raw_reader_read_word( FILE* fin, Word& aValue ) { aValue = 0; - for (unsigned size = 0; size < sizeof( Word ); ++size) - aValue |= getc(fin) << (8 * size); + for ( std::size_t i = 0; i < sizeof( Word ); ++i ) + reinterpret_cast(&aValue)[i] = getc(fin); + return fin; } diff --git a/src/DGtal/io/writers/GenericWriter.h b/src/DGtal/io/writers/GenericWriter.h index 90f4908c56..46d97c6d37 100644 --- a/src/DGtal/io/writers/GenericWriter.h +++ b/src/DGtal/io/writers/GenericWriter.h @@ -60,10 +60,10 @@ namespace DGtal /** * Description of template class 'GenericWriter'

* \brief Aim: Provide a mechanism to save image (2D or 3D) into file with the best saver loader according to an filename (by parsing the extension). - * + * * The typical use is very simple: * - First include the header of the generic reader (and StdDefs) and define image type: - @code + @code #include "DGTal/io/readers/GenericWriter.h" #include "DGtal/helpers/StdDefs.h" typedef DGtal::ImageContainerBySTLMap Image3D; @@ -80,28 +80,28 @@ namespace DGtal * exportFile function (see below). * @tparam TContainer the container (mainly an ImageContainer like ImageContainerBySTLVector or ImageContainerBySTLMap). * @tparam Tdim the dimension of the container (by default given by the container). - * @tparam TValue the value type of data contained in the image (by default given by the container) + * @tparam TValue the value type of data contained in the image (by default given by the container) * @tparam TFunctor a functor type to apply image transformation before saving the image (by default set to functors::Identity). * * */ - template struct GenericWriter { - BOOST_CONCEPT_ASSERT(( concepts::CConstImage )) ; + BOOST_CONCEPT_ASSERT(( concepts::CConstImage )) ; /** * Export an image. - * @param filename the filename of the saved image (with a extension name). - * @param anImage the image to be saved. - * @param aFunctor to apply image transformation before saving. + * @param filename the filename of the saved image (with a extension name). + * @param anImage the image to be saved. + * @param aFunctor to apply image transformation before saving. * **/ - static bool exportFile(const std::string &filename, - const TContainer &anImage, + static bool exportFile(const std::string &filename, + const TContainer &anImage, const TFunctor & aFunctor = TFunctor() ) throw(DGtal::IOException); }; @@ -112,47 +112,22 @@ namespace DGtal template struct GenericWriter { - BOOST_CONCEPT_ASSERT(( concepts::CUnaryFunctor )) ; - BOOST_CONCEPT_ASSERT(( concepts::CConstImage )) ; - + BOOST_CONCEPT_ASSERT(( concepts::CUnaryFunctor )) ; + BOOST_CONCEPT_ASSERT(( concepts::CConstImage )) ; + /** * Export a volume image. - * @param filename the filename of the saved image (with a extension name). + * @param filename the filename of the saved image (with a extension name). * @param anImage the image to be saved. * @param datasetName the dataset name to export. - * @param aFunctor to apply image transformation before saving. + * @param aFunctor to apply image transformation before saving. * **/ static bool exportFile(const std::string &filename, const TContainer &anImage, const std::string &datasetName="UInt8Array3D", - const TFunctor & aFunctor = TFunctor() ) throw(DGtal::IOException); - - }; - - /** - * GenericWriter - * Template partial specialisation for volume images of dimension 3 and DGtal::uint32_t value type (which allows to export raw file format). - **/ - template - struct GenericWriter - { - BOOST_CONCEPT_ASSERT(( concepts::CUnaryFunctor )) ; - BOOST_CONCEPT_ASSERT(( concepts::CConstImage )) ; - - /** - * Export a volume image. - * @param filename the filename of the saved image (with a extension name). - * @param anImage the image to be saved. - * @param datasetName the dataset name to export. - * @param aFunctor to apply image transformation before saving. - * - **/ - static bool exportFile(const std::string &filename, - const TContainer &anImage, - const std::string &datasetName="UInt32Array3D", const TFunctor & aFunctor = TFunctor() ) throw(DGtal::IOException); - + }; - + /** * GenericWriter * Template partial specialisation for volume images of dimension 3 and DGtal::uint64_t value type (which allows to export longvol file format). @@ -161,19 +136,19 @@ namespace DGtal struct GenericWriter { - BOOST_CONCEPT_ASSERT(( concepts::CUnaryFunctor )) ; - BOOST_CONCEPT_ASSERT(( concepts::CConstImage )) ; - + BOOST_CONCEPT_ASSERT(( concepts::CUnaryFunctor )) ; + BOOST_CONCEPT_ASSERT(( concepts::CConstImage )) ; + /** * Export a volume image. - * @param filename the filename of the saved image (with a extension name). - * @param anImage the image to be saved. - * @param aFunctor to apply image transformation before saving. + * @param filename the filename of the saved image (with a extension name). + * @param anImage the image to be saved. + * @param aFunctor to apply image transformation before saving. * **/ static bool exportFile(const std::string &filename, const TContainer &anImage, - const TFunctor & aFunctor = TFunctor() ) throw(DGtal::IOException); + const TFunctor & aFunctor = TFunctor() ) throw(DGtal::IOException); }; @@ -185,17 +160,17 @@ namespace DGtal template struct GenericWriter { - BOOST_CONCEPT_ASSERT(( concepts::CConstImage )) ; + BOOST_CONCEPT_ASSERT(( concepts::CConstImage )) ; /** * Export a volume image. - * @param filename the filename of the saved image (with a extension name). + * @param filename the filename of the saved image (with a extension name). * @param anImage the image to be saved. * @param datasetName the dataset name to export. - * @param aFunctor to apply image transformation before saving. + * @param aFunctor to apply image transformation before saving. * **/ - static bool exportFile(const std::string &filename, - const TContainer &anImage, + static bool exportFile(const std::string &filename, + const TContainer &anImage, const std::string &datasetName="UInt8Array3D", const TFunctor & aFunctor = TFunctor() ) throw(DGtal::IOException); @@ -208,36 +183,36 @@ namespace DGtal template struct GenericWriter { - BOOST_CONCEPT_ASSERT(( concepts::CConstImage )) ; - + BOOST_CONCEPT_ASSERT(( concepts::CConstImage )) ; + /** - * Export the 2D image file. - * @param filename the filename of the saved image (with a extension name). + * Export the 2D image file. + * @param filename the filename of the saved image (with a extension name). * @param anImage the image to be saved. - * @param aFunctor to apply image transformation before saving. + * @param aFunctor to apply image transformation before saving. * **/ - static bool exportFile(const std::string &filename, + static bool exportFile(const std::string &filename, const TContainer &anImage, const TFunctor & aFunctor = TFunctor() ) throw(DGtal::IOException); - }; + }; /** * GenericWriter - * Template partial specialisation for images of dimension 2 and Functor returning a Color object + * Template partial specialisation for images of dimension 2 and Functor returning a Color object **/ template struct GenericWriter > { - BOOST_CONCEPT_ASSERT(( concepts::CConstImage )) ; - + BOOST_CONCEPT_ASSERT(( concepts::CConstImage )) ; + /** - * Export the 2D image file. - * @param filename the filename of the saved image (with a extension name). + * Export the 2D image file. + * @param filename the filename of the saved image (with a extension name). * @param anImage the image to be saved. - * @param aFunctor to apply image transformation before saving: transform scalar value to Color by using HueShadeColorMap. + * @param aFunctor to apply image transformation before saving: transform scalar value to Color by using HueShadeColorMap. * **/ /** @@ -247,9 +222,9 @@ namespace DGtal static bool exportFile(const std::string &filename, const TContainer &anImage, const HueShadeColorMap & aFunctor ) throw(DGtal::IOException); - - }; - + + }; + /** * GenericWriter * Template partial specialisation for images of dimension 2 and unsigned char value type (which allows to export pgm, ppm file format ). @@ -257,56 +232,31 @@ namespace DGtal template struct GenericWriter { - BOOST_CONCEPT_ASSERT(( concepts::CConstImage )) ; + BOOST_CONCEPT_ASSERT(( concepts::CConstImage )) ; /** - * Export the 2D image file. - * @param filename the filename of the saved image (with a extension name). + * Export the 2D image file. + * @param filename the filename of the saved image (with a extension name). * @param anImage the image to be saved. - * @param aFunctor to apply image transformation before saving. + * @param aFunctor to apply image transformation before saving. * **/ static bool exportFile(const std::string &filename, const TContainer &anImage, - const TFunctor & aFunctor = TFunctor() ) throw(DGtal::IOException); - - }; - - - /** - * GenericWriter Template partial specialisation for images of - * dimension 2 and DGtal::uint32_tvalue type (which allows to export - * raw 32 bits file format ). - **/ - template - struct GenericWriter - { - BOOST_CONCEPT_ASSERT(( concepts::CConstImage )) ; - /** - * Export the 2D image file. - * @param filename the filename of the saved image (with a extension name). - * @param anImage the image to be saved. - * @param aFunctor to apply image transformation before saving. - * - **/ - static bool exportFile(const std::string &filename, const TContainer &anImage, - const TFunctor & aFunctor = TFunctor() ) throw(DGtal::IOException); - - }; + const TFunctor & aFunctor = TFunctor() ) throw(DGtal::IOException); + }; /** * 'operator>>' for exporting an ImageContainer. * This operator automatically selects the best method according to * the filename extension (pgm, pgm3D, raw, vol). - * + * * @param aContainer the container to be exported. - * @param aFilename the filename of the file to be exported. - * @return true, if the export was successful. + * @param aFilename the filename of the file to be exported. + * @return true, if the export was successful. */ template bool operator >> ( const TImageContainer & aContainer, const std::string & aFilename ) throw (DGtal::IOException); - - } // namespace DGtal diff --git a/src/DGtal/io/writers/GenericWriter.ih b/src/DGtal/io/writers/GenericWriter.ih index 550ce0ac0f..21b0dfeff2 100644 --- a/src/DGtal/io/writers/GenericWriter.ih +++ b/src/DGtal/io/writers/GenericWriter.ih @@ -46,59 +46,67 @@ // Implementation of inline functions // -template +template < typename TContainer, int TDim, typename TValue, typename TFunctor > inline bool -DGtal::GenericWriter::exportFile(const std::string &filename, - const TContainer &anImage, - const TFunctor & aFunctor) throw(DGtal::IOException){ +DGtal::GenericWriter:: +exportFile( const std::string & filename, + const TContainer & anImage, + const TFunctor & aFunctor + ) throw( DGtal::IOException ) +{ DGtal::IOException dgtalio; - std::string extension = filename.substr(filename.find_last_of(".") + 1); - if(extension!="raw"){ - trace.error() << "Extension " << extension<< " not yet implemented in n dimension (only raw images are actually implemented in Nd." << std::endl; - throw dgtalio; - }else{ - return RawWriter< TContainer >::exportRaw8 ( filename, anImage, aFunctor ); - } + const std::string extension = filename.substr( filename.find_last_of(".") + 1 ); + if(extension != "raw") + { + trace.error() << "Extension " << extension << " in " << TDim <<"D, not yet implemented in DGtal GenericWriter (only raw images are actually implemented in Nd using any value type)." << std::endl; + throw dgtalio; + } + else + { + return RawWriter::template exportRaw( filename, anImage, aFunctor ); + } return true; } - - - - -template +template < typename TContainer, typename TValue, typename TFunctor > inline bool -DGtal::GenericWriter::exportFile(const std::string &filename, - const TContainer &anImage, - const std::string & datasetName, - const TFunctor & aFunctor ) throw(DGtal::IOException) +DGtal::GenericWriter:: +exportFile( const std::string & filename, + const TContainer & anImage, + const std::string & datasetName, + const TFunctor & aFunctor + ) throw( DGtal::IOException ) { DGtal::IOException dgtalio; - std::string extension = filename.substr(filename.find_last_of(".") + 1); - - //to remove doc warnings - BOOST_VERIFY(datasetName==datasetName); - BOOST_VERIFY(anImage==anImage); - BOOST_VERIFY(aFunctor==aFunctor); - if -#ifdef WITH_HDF5 - ( (extension=="h5") || -#endif - (extension=="vol" || extension=="pgm3d"|| extension=="pgm3D" ||extension=="p3d" || extension=="raw" || extension=="pgm") + const std::string extension = filename.substr( filename.find_last_of(".") + 1 ); + + // To remove compiler warnings + boost::ignore_unused_variable_warning( datasetName ); + + if ( #ifdef WITH_HDF5 - ) + extension == "h5" || #endif - { - trace.error() << "Value type of " << extension<< " file extension should be unsigned char." - << std::endl; - throw dgtalio; - }else{ - trace.error() << "Extension " << extension<< " not yet implemented in DGtal." << std::endl; - throw dgtalio; - } + extension == "vol" || extension == "pgm3d" || extension == "pgm3D" || extension == "p3d" || extension == "pgm" + ) + { + trace.error() << "Value type of " << extension << " file extension should be unsigned char." + << std::endl; + throw dgtalio; + } + else if ( extension == "raw" ) + { + return RawWriter::template exportRaw( filename, anImage, aFunctor ); + } + else + { + trace.error() << "Extension " << extension << " in 3D, not yet implemented in DGtal GenericWriter." << std::endl; + throw dgtalio; + } + return false; } @@ -108,18 +116,29 @@ DGtal::GenericWriter::exportFile(const std::str template inline bool -DGtal::GenericWriter::exportFile(const std::string &filename, - const TContainer &anImage, - const TFunctor & aFunctor ) throw(DGtal::IOException){ +DGtal::GenericWriter:: +exportFile( const std::string & filename, + const TContainer & anImage, + const TFunctor & aFunctor + ) throw( DGtal::IOException ) +{ DGtal::IOException dgtalio; - std::string extension = filename.substr(filename.find_last_of(".") + 1); - - if(extension=="longvol"){ - return VolWriter::exportLongvol( filename, anImage ,aFunctor); - }else{ - trace.error() << "Extension " << extension<< " with DGtal::uint64_t , not yet implemented in DGtal." << std::endl; - throw dgtalio; - } + const std::string extension = filename.substr( filename.find_last_of(".") + 1 ); + + if ( extension == "longvol" ) + { + return VolWriter::exportLongvol( filename, anImage , aFunctor ); + } + else if ( extension == "raw" ) + { + return RawWriter::template exportRaw( filename, anImage, aFunctor ); + } + else + { + trace.error() << "Extension " << extension<< " with DGtal::uint64_t in 3D, not yet implemented in DGtal GenericWriter." << std::endl; + throw dgtalio; + } + return false; } @@ -128,168 +147,139 @@ DGtal::GenericWriter::exportFile(const template inline bool -#ifdef WITH_HDF5 -DGtal::GenericWriter::exportFile(const std::string &filename, - const TContainer &anImage, - const std::string &datasetName, - const TFunctor & aFunctor ) throw(DGtal::IOException) -#else -DGtal::GenericWriter::exportFile(const std::string &filename, - const TContainer &anImage, - const std::string &datasetName, - const TFunctor & aFunctor ) throw(DGtal::IOException) -#endif +DGtal::GenericWriter:: +exportFile( const std::string & filename, + const TContainer & anImage, + const std::string & datasetName, + const TFunctor & aFunctor + ) throw( DGtal::IOException ) { DGtal::IOException dgtalio; - std::string extension = filename.substr(filename.find_last_of(".") + 1); + const std::string extension = filename.substr( filename.find_last_of(".") + 1 ); #ifdef WITH_HDF5 - if (extension=="h5") + if ( extension == "h5" ) { - return HDF5Writer::exportHDF5_3D(filename, anImage, datasetName, aFunctor); + return HDF5Writer::exportHDF5_3D( filename, anImage, datasetName, aFunctor ); } else #else boost::ignore_unused_variable_warning(datasetName); #endif - if (extension=="vol") + if ( extension == "vol" ) { - return VolWriter::exportVol(filename, anImage, aFunctor); - } else if(extension=="pgm3d"|| extension=="pgm3D" ||extension=="p3d" || extension=="pgm" ) + return VolWriter::exportVol( filename, anImage, aFunctor ); + } + else if ( extension == "pgm3d" || extension == "pgm3D" || extension == "p3d" || extension == "pgm" ) { - return PGMWriter::exportPGM3D(filename, anImage, aFunctor); - } else if(extension=="raw" ) + return PGMWriter::exportPGM3D( filename, anImage, aFunctor ); + } + else if( extension == "raw" ) { - return RawWriter< TContainer, TFunctor >::exportRaw8(filename, anImage, aFunctor); - } + return RawWriter< TContainer, TFunctor >::exportRaw8( filename, anImage, aFunctor ); + } else { - trace.error() << "Extension " << extension<< " not yet implemented in DGtal." << std::endl; - throw dgtalio; - } - return false; -} + trace.error() << "Extension " << extension<< " with unsigned char in 3D, not yet implemented in DGtal GenericWriter." << std::endl; + throw dgtalio; + } - - -template -inline -bool -DGtal::GenericWriter::exportFile(const std::string &filename, - const TContainer &anImage, const std::string & datasetName, - const TFunctor & aFunctor ) throw(DGtal::IOException) -{ - boost::ignore_unused_variable_warning(datasetName); - - DGtal::IOException dgtalio; - std::string extension = filename.substr(filename.find_last_of(".") + 1); - if(extension=="raw"){ - trace.info() << "export raw 32 bits" << std::endl; - return RawWriter< TContainer, TFunctor >::exportRaw32(filename, anImage, aFunctor); - } else { - trace.error() << "Extension " << extension<< " not yet implemented in DGtal with 32 bit format." << std::endl; - throw dgtalio; - } return false; } - - template inline bool -DGtal::GenericWriter::exportFile(const std::string &filename, - const TContainer &anImage, - const TFunctor & aFunctor ) throw(DGtal::IOException) +DGtal::GenericWriter:: +exportFile( const std::string & filename, + const TContainer & anImage, + const TFunctor & aFunctor + ) throw( DGtal::IOException ) { - //compiler warnings - BOOST_VERIFY(aFunctor==aFunctor); - BOOST_VERIFY(anImage==anImage); - DGtal::IOException dgtalio; - std::string extension = filename.substr(filename.find_last_of(".") + 1); - if(extension=="pgm" ||extension=="pbm"){ - trace.error() << "Value type of " << extension<< " file extension should be unsigned char." << std::endl; - throw dgtalio; - }else{ - trace.error() << "Extension " << extension<< " not yet implemented in DGtal." << std::endl; - throw dgtalio; - } - return false; -} + const std::string extension = filename.substr( filename.find_last_of(".") + 1 ); + if ( extension == "pgm" || extension == "pbm" ) + { + trace.error() << "Value type of " << extension<< " file extension should be unsigned char." << std::endl; + throw dgtalio; + } + else if ( extension == "raw" ) + { + return RawWriter< TContainer, TFunctor >::template exportRaw( filename, anImage, aFunctor ); + } + else + { + trace.error() << "Extension " << extension<< " in 2D, not yet implemented in DGtal GenericWriter." << std::endl; + throw dgtalio; + } -template -inline -bool -DGtal::GenericWriter >::exportFile(const std::string &filename, - const TContainer &anImage, - const DGtal::HueShadeColorMap & aFunctor ) throw(DGtal::IOException){ - DGtal::IOException dgtalio; - std::string extension = filename.substr(filename.find_last_of(".") + 1); - if(extension=="ppm"){ - return PPMWriter >::exportPPM(filename, anImage, aFunctor); - }else{ - trace.error() << "Extension " << extension<< " not yet implemented in DGtal with specific HueShadeColorMap functor." << std::endl; - throw dgtalio; - } return false; } - -template +template inline bool -DGtal::GenericWriter::exportFile(const std::string &filename, - const TContainer &anImage, - const TFunctor & aFunctor ) throw(DGtal::IOException) +DGtal::GenericWriter >:: +exportFile( const std::string & filename, + const TContainer & anImage, + const DGtal::HueShadeColorMap & aFunctor + ) throw( DGtal::IOException ) { DGtal::IOException dgtalio; - //Getting image extension - std::string extension = filename.substr(filename.find_last_of(".") + 1); - if(extension=="pgm"){ - return PGMWriter::exportPGM(filename, anImage, aFunctor); - } if(extension=="raw"){ - return RawWriter::exportRaw8(filename, anImage, aFunctor); - } else{ - trace.error() << "Extension " << extension<< " not yet implemented in generic writer." << std::endl; - throw dgtalio; - } + const std::string extension = filename.substr( filename.find_last_of(".") + 1 ); + if ( extension == "ppm" ) + { + return PPMWriter >::exportPPM( filename, anImage, aFunctor ); + } + else if ( extension == "raw" ) + { + return RawWriter< TContainer, DGtal::HueShadeColorMap >::template exportRaw( filename, anImage, aFunctor ); + } + else + { + trace.error() << "Extension " << extension<< " in 2D, not yet implemented in DGtal GenericWriter with specific HueShadeColorMap functor." << std::endl; + throw dgtalio; + } - return true; + return false; } template inline bool -DGtal::GenericWriter::exportFile(const std::string &filename, - const TContainer &anImage, - const TFunctor & aFunctor ) throw(DGtal::IOException) +DGtal::GenericWriter:: +exportFile( const std::string & filename, + const TContainer & anImage, + const TFunctor & aFunctor + ) throw( DGtal::IOException ) { DGtal::IOException dgtalio; //Getting image extension - std::string extension = filename.substr(filename.find_last_of(".") + 1); - if(extension=="raw"){ - return RawWriter::exportRaw32(filename, anImage, aFunctor); - } else{ - trace.error() << "Extension " << extension<< " not yet implemented in generic writer." << std::endl; - throw dgtalio; - } + const std::string extension = filename.substr(filename.find_last_of(".") + 1); + if ( extension == "pgm" ) + { + return PGMWriter::exportPGM( filename, anImage, aFunctor ); + } + else if ( extension == "raw" ) + { + return RawWriter::exportRaw8( filename, anImage, aFunctor ); + } + else + { + trace.error() << "Extension " << extension<< " with unsigned char in 2D, not yet implemented in DGtal GenericWriter." << std::endl; + throw dgtalio; + } return true; } - - - - template inline bool DGtal::operator >> ( const TImageContainer & aContainer, const std::string & aFilename ) throw (DGtal::IOException) { - return DGtal::GenericWriter::exportFile(aFilename, aContainer); + return DGtal::GenericWriter::exportFile(aFilename, aContainer); } diff --git a/src/DGtal/io/writers/RawWriter.h b/src/DGtal/io/writers/RawWriter.h index ef46eaed1a..5c4b102815 100644 --- a/src/DGtal/io/writers/RawWriter.h +++ b/src/DGtal/io/writers/RawWriter.h @@ -58,11 +58,41 @@ namespace DGtal * Description of template struct 'RawWriter'

* \brief Aim: Raw binary export of an Image. * + * The export methods \c exportRaw8, \c exportRaw16 and \c exportRaw32 write raw files (little-endian format) + * with unsigned integer values of, respectively, 8 bits, 16 bits and 32 bits width. + * The method \c exportRaw can write any type of values, signed integers, floating point types or + * even structures. + * * A functor can be specified to convert image values to raw values - * (unsigned char for exportRaw8). + * (e.g. unsigned char for \c exportRaw8). + * + * Example usage: + * @code + * ... + * typedef DGtal::SpaceND Space; + * typedef DGtal::HyperRectDomain Domain; + * typedef Domain::Point Point; + * + * //Default image container = STLVector + * typedef DGtal::ImageSelector::Type Image; + * + * Domain domain( Point::diagonal(0), Point::diagonal(10) ); + * Image image( domain ); + * + * ... // Filling the image. + * + * DGtal::RawWriter writer; + * if ( writer.exportRaw8( "data.raw", image ) ) + * trace.info() << "Image successfully exported." << endl; + * else + * trace.info() << "Error while exporting image." << endl; + * @endcode * * @tparam TImage the Image type. * @tparam TFunctor the type of functor used in the export. + * + * @see RawReader + * @see testRawReader.cpp */ template struct RawWriter @@ -74,7 +104,7 @@ namespace DGtal typedef TFunctor Functor; /** - * Export an Image to Raw format. + * Export an Image to Raw format (any value type, in little-endian format). * * @tparam Word exported pixel type. * @param filename name of the output file. diff --git a/src/DGtal/io/writers/RawWriter.ih b/src/DGtal/io/writers/RawWriter.ih index 987ac22913..4362d7b739 100644 --- a/src/DGtal/io/writers/RawWriter.ih +++ b/src/DGtal/io/writers/RawWriter.ih @@ -28,6 +28,7 @@ ////////////////////////////////////////////////////////////////////////////// +#include #include #include ////////////////////////////////////////////////////////////////////////////// @@ -101,8 +102,9 @@ template std::ostream& DGtal::raw_writer_write_word(std::ostream& outs, Word value) { - for (unsigned size = sizeof(Word); size; --size, value >>= 8) - outs.put(static_cast(value & 0xFF)); + for ( std::size_t i = 0; i < sizeof(Word); ++i ) + outs.put( reinterpret_cast(&value)[i] ); + return outs; } diff --git a/tests/io/readers/testRawReader.cpp b/tests/io/readers/testRawReader.cpp index f1ff954c6e..4cea95c22a 100644 --- a/tests/io/readers/testRawReader.cpp +++ b/tests/io/readers/testRawReader.cpp @@ -17,10 +17,14 @@ /** * @file testRawReader.cpp * @ingroup Tests + * * @author David Coeurjolly (\c david.coeurjolly@liris.cnrs.fr ) * Laboratoire d'InfoRmatique en Image et Systèmes d'information - LIRIS (CNRS, UMR 5205), CNRS, France * - * @date 2010/07/29 + * @autor Roland Denis (\c roland.denis@univ-smb.fr ) + * LAboratory of MAthematics - LAMA (CNRS, UMR 5127), University of Savoie, France + * + * @date 10/12/2015 * * Functions for testing class RawReader. * @@ -28,17 +32,18 @@ */ /////////////////////////////////////////////////////////////////////////////// -#include -#include "DGtal/base/Common.h" - -#include "DGtal/kernel/SpaceND.h" -#include "DGtal/kernel/domains/HyperRectDomain.h" -#include "DGtal/images/ImageSelector.h" -#include "DGtal/io/writers/PGMWriter.h" -#include "DGtal/io/readers/RawReader.h" +#include "DGtalCatch.h" +#include +#include +#include +#include +#include +#include +#include -#include "ConfigTest.h" +#include +#include /////////////////////////////////////////////////////////////////////////////// @@ -46,77 +51,280 @@ using namespace std; using namespace DGtal; /////////////////////////////////////////////////////////////////////////////// -// Functions for testing class RawReader. -/////////////////////////////////////////////////////////////////////////////// -/** - * Example of a test. To be completed. - * + +/** Compares an image to the reference data. + * @tparam Image Image type. + * @param anImage The image to test. */ -bool testRawReader2D() +template < + typename Image +> +void testImageOnRef( Image const& anImage ) { - unsigned int nbok = 0; - unsigned int nb = 0; - - trace.beginBlock ( "Testing Raw reader ..." ); + typedef typename Image::Domain Domain; + typedef typename Domain::Point Point; - typedef SpaceND<2> Space2; - typedef HyperRectDomain TDomain; - typedef TDomain::Vector Vector; + // Checking domain + INFO( "Checking domain" ) + REQUIRE( anImage.domain().lowerBound() == Point::diagonal(0) ); + REQUIRE( anImage.domain().upperBound() == Point::diagonal(4) ); - typedef SpaceND<3> Space3; - typedef HyperRectDomain TDomain3; - typedef TDomain3::Vector Vector3; - - //Default image selector = STLVector - typedef ImageSelector::Type Image; - typedef ImageSelector::Type Image32; - - std::string filename = testPath + "samples/raw2D-64x64.raw"; - - Vector ext(16,16); - - Image image = RawReader::importRaw8( filename , ext); + // Checking values + INFO( "Checking values" ) + const Domain domain = anImage.domain(); + for ( typename Domain::ConstIterator it = domain.begin(), itEnd = domain.end(); it != itEnd; ++it ) + { + const Point pt = *it; + const unsigned int refValue = anImage.dimension == 2 ? + 1000000 * pt[0] * pt[1] + : 250000 * pt[0] * pt[1] * pt[2]; - ///FIXME: check io errors - trace.info() << image <::exportPGM("export-raw-reader.pgm",image); - - /// @todo re-import the PGM and compare with raw2D-64x64 +/** Reads and compares a raw file to the reference data. + * @tparam N Dimension of the image. + */ +template < + DGtal::Dimension N +> +void testRawReaderOnRef() +{ + REQUIRE( N >= 2 ); + REQUIRE( N <= 3 ); - std::string filename2 = testPath + "samples/raw32bits5x5x5.raw"; - Vector3 ext2(5,5,5); - Image32 image2 = RawReader::importRaw32( filename2, ext2 ); - TDomain3::Point pointA(2,3,4); - - trace.info() << "Value of point " << pointA << " value :" << image2(pointA) << std::endl; - + typedef SpaceND Space; + typedef HyperRectDomain Domain; + typedef typename ImageSelector::Type Image; + typedef typename Domain::Vector Vector; + + // Generating file name + std::string fileName = testPath + "samples/"; + if ( N == 2) + fileName += "raw32bits5x5.raw"; + else + fileName += "raw32bits5x5x5.raw"; + + // Reading file + const Vector extent = Vector::diagonal(5); - nbok += image2(pointA)== 250000*2*3*4 ? 1 : 0; - nb++; - trace.info() << "(" << nbok << "/" << nb << ") " - << "true == true" << std::endl; - trace.endBlock(); + INFO( "Reading file with importRaw32" << fileName ); + Image imageRaw32 = RawReader::importRaw32( fileName, extent ); + testImageOnRef( imageRaw32 ); + + INFO( "Reading file with importRaw" << fileName ); + Image imageRaw = RawReader::template importRaw< unsigned int >( fileName, extent ); + testImageOnRef( imageRaw ); +} + +/** Compares an image to a generated data. + * @tparam Image Image type. + * @param[out] anImage The image. + * @param aSeed Seed for the generator. + */ +template < + typename Image +> +void generateRefImage( Image & anImage, typename Image::Value aSeed ) +{ + typedef typename Image::Domain Domain; + typedef typename Domain::Point Point; + + const Domain domain = anImage.domain(); - return nbok == nb; + for ( typename Domain::ConstIterator it = domain.begin(), itEnd = domain.end(); it != itEnd; ++it ) + { + const Point pt = *it; + const typename Image::Value refValue = aSeed * Linearizer::getIndex( pt, domain ); + anImage.setValue( pt, refValue ); + } +} + +/** Checks reading a previously writed file. + * @tparam N Dimension of the image. + * @tparam T Value type. + * @tparam RawIO Class with writer and reader, templated by the image type. + * @param aSeed Seed to generate image values. + */ +template < + DGtal::Dimension N, + typename T, + template class RawIO +> +void testWriteAndRead( T aSeed ) +{ + typedef SpaceND Space; + typedef HyperRectDomain Domain; + typedef typename ImageSelector::Type Image; + typedef typename Domain::Point Point; + + Point upperPt; + upperPt[ 0 ] = 8; + for ( Dimension i = 1; i < N; ++i ) + upperPt[ i ] = upperPt[ i-1 ] * ( i == 1 ? 4 : 2 ); + + const Domain domain( Point::diagonal(0), upperPt ); + Image refImage( domain ); + generateRefImage( refImage, aSeed ); + + INFO( "Writing image" ); + RawIO::write( "export-raw-writer.raw", refImage ); + + INFO( "Reading image" ); + Image image = RawIO::read( "export-raw-writer.raw", upperPt + Point::diagonal(1) ); + + INFO( "Comparing image values" ); + for ( typename Domain::ConstIterator it = domain.begin(), itEnd = domain.end(); it != itEnd; ++it ) + { + const Point pt = *it; + INFO( "At point " << pt ); + REQUIRE( image( pt ) == refImage( pt ) ); + } } +// Some RawIO classes +template < typename Image > +struct RawIO8 +{ + static inline Image read( std::string const& filename, typename Image::Domain::Vector const& extent ) + { + return DGtal::RawReader::importRaw8( filename, extent ); + } + + static inline bool write( std::string const& filename, Image const& anImage ) + { + return DGtal::RawWriter::exportRaw8( filename, anImage ); + } +}; + +template < typename Image > +struct RawIO16 +{ + static inline Image read( std::string const& filename, typename Image::Domain::Vector const& extent ) + { + return DGtal::RawReader::importRaw16( filename, extent ); + } + + static inline bool write( std::string const& filename, Image const& anImage ) + { + return DGtal::RawWriter::exportRaw16( filename, anImage ); + } +}; + +template < typename Image > +struct RawIO32 +{ + static inline Image read( std::string const& filename, typename Image::Domain::Vector const& extent ) + { + return DGtal::RawReader::importRaw32( filename, extent ); + } + + static inline bool write( std::string const& filename, Image const& anImage ) + { + return DGtal::RawWriter::exportRaw32( filename, anImage ); + } +}; + +template < typename Image > +struct RawIO +{ + static inline Image read( std::string const& filename, typename Image::Domain::Vector const& extent ) + { + return DGtal::RawReader::template importRaw< typename Image::Value>( filename, extent ); + } + + static inline bool write( std::string const& filename, Image const& anImage ) + { + return DGtal::RawWriter::template exportRaw< typename Image::Value>( filename, anImage ); + } +}; + /////////////////////////////////////////////////////////////////////////////// -// Standard services - public : -int main( int argc, char** argv ) +TEST_CASE( "Checking RawReader with reference files in 2D", "[reader][2D][raw][raw32][uint32]" ) { - trace.beginBlock ( "Testing class RawReader" ); - trace.info() << "Args:"; - for ( int i = 0; i < argc; ++i ) - trace.info() << " " << argv[ i ]; - trace.info() << endl; + testRawReaderOnRef<2>(); +} - bool res = testRawReader2D(); // && ... other tests - trace.emphase() << ( res ? "Passed." : "Error." ) << endl; - trace.endBlock(); - return res ? 0 : 1; +TEST_CASE( "Checking RawReader with reference files in 3D", "[reader][3D][raw][raw32][uint32]" ) +{ + testRawReaderOnRef<3>(); } -// // -/////////////////////////////////////////////////////////////////////////////// + +// Signed and unsigned char +TEST_CASE( "Checking writing & reading uint8 in 2D with generic IO", "[reader][writer][2D][raw][uint8]" ) +{ + testWriteAndRead<2, DGtal::uint8_t, RawIO>( 1 ); +} + +TEST_CASE( "Checking writing & reading uint8 in 2D with 8bits IO", "[reader][writer][2D][raw8][uint8]" ) +{ + testWriteAndRead<2, DGtal::uint8_t, RawIO>( 1 ); +} + +TEST_CASE( "Checking writing & reading int8 in 2D with generic IO", "[reader][writer][2D][raw][int8]" ) +{ + testWriteAndRead<2, DGtal::int8_t, RawIO>( 1 ); +} + +// Signed and unsigned short +TEST_CASE( "Checking writing & reading uint16 in 2D with generic IO", "[reader][writer][2D][raw][uint16]" ) +{ + testWriteAndRead<2, DGtal::uint16_t, RawIO>( 1 ); +} + +TEST_CASE( "Checking writing & reading uint16 in 2D with 16bits IO", "[reader][writer][2D][raw16][uint16]" ) +{ + testWriteAndRead<2, DGtal::uint16_t, RawIO>( 1 ); +} + +TEST_CASE( "Checking writing & reading int16 in 2D with generic IO", "[reader][writer][2D][raw][int16]" ) +{ + testWriteAndRead<2, DGtal::int16_t, RawIO>( 1 ); +} + +// Signed and unsigned int +TEST_CASE( "Checking writing & reading uint32 in 2D with generic IO", "[reader][writer][2D][raw][uint32]" ) +{ + testWriteAndRead<2, DGtal::uint32_t, RawIO>( 1 ); +} + +TEST_CASE( "Checking writing & reading uint32 in 2D with 32bits IO", "[reader][writer][2D][raw32][uint32]" ) +{ + testWriteAndRead<2, DGtal::uint32_t, RawIO>( 1 ); +} + +TEST_CASE( "Checking writing & reading int32 in 2D with generic IO", "[reader][writer][2D][raw][int32]" ) +{ + testWriteAndRead<2, DGtal::int32_t, RawIO>( 1 ); +} + +// Signed and unsigned long int +TEST_CASE( "Checking writing & reading uint64 in 2D with generic IO", "[reader][writer][2D][raw][uint64]" ) +{ + testWriteAndRead<2, DGtal::uint64_t, RawIO>( 1 ); +} + +TEST_CASE( "Checking writing & reading int64 in 2D with generic IO", "[reader][writer][2D][raw][int64]" ) +{ + testWriteAndRead<2, DGtal::int64_t, RawIO>( 1 ); +} + +// Double +TEST_CASE( "Checking writing & reading double in 1D with generic IO", "[reader][writer][1D][raw][double]" ) +{ + testWriteAndRead<1, double, RawIO>( 1.23456789 ); +} + +TEST_CASE( "Checking writing & reading double in 2D with generic IO", "[reader][writer][2D][raw][double]" ) +{ + testWriteAndRead<2, double, RawIO>( 1.23456789 ); +} + +TEST_CASE( "Checking writing & reading double in 3D with generic IO", "[reader][writer][3D][raw][double]" ) +{ + testWriteAndRead<3, double, RawIO>( 1.23456789 ); +} +