CVD 0.8
cvd/image_io.h
00001 /*                       
00002     This file is part of the CVD Library.
00003 
00004     Copyright (C) 2005 The Authors
00005 
00006     This library is free software; you can redistribute it and/or
00007     modify it under the terms of the GNU Lesser General Public
00008     License as published by the Free Software Foundation; either
00009     version 2.1 of the License, or (at your option) any later version.
00010 
00011     This library is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014     Lesser General Public License for more details.
00015 
00016     You should have received a copy of the GNU Lesser General Public
00017     License along with this library; if not, write to the Free Software
00018     Foundation, Inc., 
00019     51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00020 */
00021 #ifndef CVD_IMAGE_IO_H
00022 #define CVD_IMAGE_IO_H
00023 
00024 #include <cvd/config.h>
00025 
00026 #include <cvd/exceptions.h>
00027 #include <cvd/image_convert.h>
00028 #include <cvd/internal/load_and_save.h>
00029 #include <cvd/internal/name_builtin_types.h>
00030 #include <cvd/internal/name_CVD_rgb_types.h>
00031 #include <errno.h>
00032 #include <memory>
00033 #include <string>
00034 #include <fstream>
00035 #include <cctype>
00036 
00037 #include <cvd/internal/io/pnm_grok.h>
00038 #include <cvd/internal/io/save_postscript.h>
00039 #include <cvd/internal/io/bmp.h>
00040 #include <cvd/internal/io/fits.h>
00041 #include <cvd/internal/io/text.h>
00042 #include <cvd/internal/io/cvdimage.h>
00043 
00044 
00045 #ifdef CVD_HAVE_JPEG
00046     #include <cvd/internal/io/jpeg.h>
00047 #endif
00048 
00049 #ifdef CVD_HAVE_TIFF
00050     #include <cvd/internal/io/tiff.h>
00051 #endif
00052 
00053 
00054 #ifdef CVD_HAVE_PNG
00055     #include <cvd/internal/io/png.h>
00056 #endif
00057 
00058 namespace CVD
00059 {
00060     
00061 
00062 
00064     //
00065     // Image loading
00066     //
00067 
00068     #ifndef DOXYGEN_IGNORE_INTERNAL
00069     namespace ImageType
00070     {
00071         enum ImageType
00072         {
00073             Automatic= -2,
00074             Unknown = -1,
00075             PNM=0,
00076             PS=1,
00077             EPS=2,
00078             BMP=3,
00079             #ifdef CVD_HAVE_JPEG
00080                 JPEG=4,
00081             #endif
00082             #ifdef CVD_HAVE_PNG
00083                 PNG=5,
00084             #endif
00085             #ifdef CVD_HAVE_TIFF
00086                 TIFF=6,
00087             #endif
00088             TXT=7,
00089             TEXT=7,
00090             FITS=8,
00091             CVD=9,
00092         };
00093     }
00094 
00095     namespace Internal
00096     {
00097         class ImageLoaderIstream{};
00098         template<> struct ImagePromise<ImageLoaderIstream>
00099         {
00100             ImagePromise(std::istream& is)
00101             :i(is){}
00102 
00103             std::istream& i;
00104             template<class C> void execute(Image<C>& im)
00105             {
00106                 img_load(im, i);
00107             }
00108         };
00109 
00110         class ImageLoaderString{};
00111         template<> struct ImagePromise<ImageLoaderString>
00112         {
00113             ImagePromise(const std::string& ss)
00114             :s(ss){}
00115 
00116             const std::string& s;
00117             template<class C> void execute(Image<C>& im)
00118             {
00119                 img_load(im, s);
00120             }
00121         };
00122     };
00123     #endif
00124 
00125     #ifdef DOXYGEN_INCLUDE_ONLY_FOR_DOCS
00126     // This is not the real definition, but this is what it would look like if all
00127     // the macros were expanded. The real definition is above
00129     namespace ImageType
00130     {
00132         enum ImageType
00133         {   
00135             Automatic,
00137             Unknown,
00140             PNM, 
00143             JPEG,
00145             BMP,
00148             PNG,
00152             TIFF,
00160             PS,
00162             EPS,
00166             TXT,
00171             CVD,
00174             FITS,
00175         };
00176     }
00177     #endif
00178 
00179     #ifndef DOXYGEN_IGNORE_INTERNAL
00180 
00181     Internal::ImagePromise<Internal::ImageLoaderIstream> img_load(std::istream& i);
00182     Internal::ImagePromise<Internal::ImageLoaderString> img_load(const std::string &s);
00183     #endif
00184 
00185     #if DOXYGEN_INCLUDE_ONLY_FOR_DOCS
00186     
00195     template<class C> Image<C> img_load(std::istream& i);
00196     
00205     template<class C> Image<C> img_load(std::string& i);
00206 
00207 
00208 
00209     #endif  
00210 
00211 
00219     template<class I> void img_load(Image<I>& im, std::istream& i)
00220     {
00221       if(!i.good())
00222       {
00223         //Check for one of the commonest errors and put in
00224         //a special case
00225         std::ifstream* fs;
00226         if((fs = dynamic_cast<std::ifstream*>(&i)) && !fs->is_open())
00227           throw Exceptions::Image_IO::IfstreamNotOpen();
00228         else
00229           throw Exceptions::Image_IO::EofBeforeImage();
00230       }
00231       unsigned char c = i.peek();
00232       
00233       if(!i.good())
00234         throw Exceptions::Image_IO::EofBeforeImage();
00235 
00236       if(c == 'P')
00237         CVD::Internal::readImage<I, PNM::Reader>(im, i);
00238 #ifdef CVD_HAVE_JPEG
00239       else if(c == 0xff)
00240         CVD::Internal::readImage<I, JPEG::reader>(im, i);
00241 #endif
00242 #ifdef CVD_HAVE_TIFF
00243       else if(c == 'I' || c == 'M') //Little or big endian TIFF
00244         CVD::Internal::readImage<I, TIFF::tiff_reader>(im, i);
00245 #endif
00246 #ifdef CVD_HAVE_PNG
00247       else if(c == 0x89)
00248         CVD::Internal::readImage<I, PNG::png_reader>(im, i);
00249 #endif
00250       else if(c == 'B')
00251         CVD::Internal::readImage<I, BMP::Reader>(im, i);
00252       else if(c == 'S')
00253         CVD::Internal::readImage<I, FITS::reader>(im, i);
00254       else if(c == 'C')
00255         CVD::Internal::readImage<I, CVDimage::reader>(im, i);
00256       else if(c == ' ' || c == '\t' || isdigit(c) || c == '-' || c == '+')
00257         CVD::Internal::readImage<I, TEXT::reader>(im, i);
00258       else
00259         throw Exceptions::Image_IO::UnsupportedImageType();
00260     }
00261         
00262     //  syg21
00263     template<class I> void img_load(Image<I> &im, const std::string &s)
00264     {
00265       std::ifstream i(s.c_str(), std::ios::in|std::ios::binary);
00266 
00267       if(!i.good())
00268         throw Exceptions::Image_IO::OpenError(s, "for reading", errno);
00269       img_load(im, i);
00270     }   
00271 
00272 
00274     //
00275     // Image saving
00276     //
00277 
00278 
00281     ImageType::ImageType string_to_image_type(const std::string& name);
00282 
00283 
00291     template<class PixelType> 
00292     void img_save(const BasicImage<PixelType>& im, std::ostream& o, ImageType::ImageType t, const std::map<std::string, Parameter<> >& p = std::map<std::string, Parameter<> >())
00293     {
00294       switch (t) {
00295       default:
00296       case ImageType::PNM:  
00297       case ImageType::Automatic:
00298       case ImageType::Unknown:
00299         Internal::writeImage<PixelType, PNM::Writer>(im, o, p); break;
00300       #ifdef CVD_HAVE_JPEG
00301           case ImageType::JPEG: Internal::writeImage<PixelType, JPEG::writer>(im,o, p); break;
00302       #endif
00303       #ifdef CVD_HAVE_PNG
00304           case ImageType::PNG: Internal::writeImage<PixelType, PNG::png_writer>(im,o, p); break;
00305       #endif
00306       #ifdef CVD_HAVE_TIFF
00307           case ImageType::TIFF: Internal::writeImage<PixelType, TIFF::tiff_writer>(im,o, p); break;
00308       #endif
00309       case ImageType::FITS: Internal::writeImage<PixelType, FITS::writer>(im,o, p); break;
00310       case ImageType::BMP:  Internal::writeImage<PixelType, BMP::Writer>(im, o, p); break;
00311       case ImageType::TXT:  Internal::writeImage<PixelType, TEXT::writer>(im, o, p); break;
00312       case ImageType::PS:   Internal::writeImage<PixelType, PS::writer>(im, o, p); break;
00313       case ImageType::EPS:  Internal::writeImage<PixelType, PS::eps_writer>(im, o, p); break;
00314       case ImageType::CVD:  Internal::writeImage<PixelType, CVDimage::writer>(im,o, p); break;
00315       }
00316     }
00317 
00318     template<class PixelType> void img_save(const BasicImage<PixelType>& im, const std::string& name, ImageType::ImageType t, ImageType::ImageType d = ImageType::PNM, const std::map<std::string, Parameter<> >& p = std::map<std::string, Parameter<> >())
00319     {
00320       std::ofstream out(name.c_str(), std::ios::out|std::ios::binary);
00321       if(!out.good())
00322         throw Exceptions::Image_IO::OpenError(name, "for writing", errno);
00323 
00324       if(t == ImageType::Automatic)
00325       {
00326         t = string_to_image_type(name);
00327         if(t == ImageType::Unknown)
00328             t = d;
00329       }
00330 
00331       img_save(im, out, t, p);
00332     }
00333 
00334     template<class PixelType> void img_save(const BasicImage<PixelType>& im, const std::string& name, const std::map<std::string, Parameter<> >& p = std::map<std::string, Parameter<> >())
00335     {
00336         img_save(im, name, ImageType::Automatic, ImageType::PNM, p);
00337     }
00338 
00340     //
00341     // Legacy pnm_* functions
00342     //
00343 
00350     template<class PixelType> void pnm_save(const BasicImage<PixelType>& im, std::ostream& o)
00351     {
00352         img_save(im, o, ImageType::PNM);
00353     }
00354 
00371     template<class PixelType> void pnm_load(Image<PixelType>& im, std::istream& i)
00372     {
00373         img_load(im, i);
00374     }
00375 
00377     //
00378     // Postscript helper functions
00379     //
00380 
00384     void output_eps_footer(std::ostream& o);
00385 
00393     void output_eps_header(std::ostream& o, int xs, int ys);
00394 
00395 
00402     void output_eps_header(std::ostream & o, const ImageRef& s);
00403 
00410     template<class PixelType> void output_eps_header(std::ostream& o, const BasicImage<PixelType>& im)
00411     {
00412         output_eps_header(o, im.size());
00413     }
00414 
00415 
00416 
00417 }
00418 
00419 #endif