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 
00043 
00044 #ifdef CVD_HAVE_JPEG
00045     #include <cvd/internal/io/jpeg.h>
00046 #endif
00047 
00048 #ifdef CVD_HAVE_TIFF
00049     #include <cvd/internal/io/tiff.h>
00050 #endif
00051 
00052 
00053 #ifdef CVD_HAVE_PNG
00054     #include <cvd/internal/io/png.h>
00055 #endif
00056 
00057 namespace CVD
00058 {
00059     
00060 
00061 
00063     //
00064     // Image loading
00065     //
00066 
00067     #ifndef DOXYGEN_IGNORE_INTERNAL
00068     namespace ImageType
00069     {
00070         enum ImageType
00071         {
00072             Automatic= -2,
00073             Unknown = -1,
00074             PNM=0,
00075             PS=1,
00076             EPS=2,
00077             BMP=3,
00078             #ifdef CVD_HAVE_JPEG
00079                 JPEG=4,
00080             #endif
00081             #ifdef CVD_HAVE_PNG
00082                 PNG=5,
00083             #endif
00084             #ifdef CVD_HAVE_TIFF
00085                 TIFF=6,
00086             #endif
00087             TXT=7,
00088             TEXT=7,
00089         };
00090     }
00091 
00092     namespace Internal
00093     {
00094         class ImageLoaderIstream{};
00095         template<> struct ImagePromise<ImageLoaderIstream>
00096         {
00097             ImagePromise(std::istream& is)
00098             :i(is){}
00099 
00100             std::istream& i;
00101             template<class C> void execute(Image<C>& im)
00102             {
00103                 img_load(im, i);
00104             }
00105         };
00106 
00107         class ImageLoaderString{};
00108         template<> struct ImagePromise<ImageLoaderString>
00109         {
00110             ImagePromise(const std::string& ss)
00111             :s(ss){}
00112 
00113             const std::string& s;
00114             template<class C> void execute(Image<C>& im)
00115             {
00116                 img_load(im, s);
00117             }
00118         };
00119     };
00120     #endif
00121 
00122     #ifdef DOXYGEN_INCLUDE_ONLY_FOR_DOCS
00123     // This is not the real definition, but this is what it would look like if all
00124     // the macros were expanded. The real definition is above
00126     namespace ImageType
00127     {
00129         enum ImageType
00130         {   
00132             Automatic,
00134             Unknown,
00137             PNM, 
00140             JPEG,
00142             BMP,
00145             PNG,
00149             TIFF,
00157             PS,
00159             EPS,
00163             TXT,
00164         };
00165     }
00166     #endif
00167 
00168     #ifndef DOXYGEN_IGNORE_INTERNAL
00169 
00170     Internal::ImagePromise<Internal::ImageLoaderIstream> img_load(std::istream& i);
00171     Internal::ImagePromise<Internal::ImageLoaderString> img_load(const std::string &s);
00172     #endif
00173 
00174     #if DOXYGEN_INCLUDE_ONLY_FOR_DOCS
00175     
00184     template<class C> Image<C> img_load(std::istream& i);
00185     
00194     template<class C> Image<C> img_load(std::string& i);
00195 
00196 
00197 
00198     #endif  
00199 
00200 
00208     template<class I> void img_load(Image<I>& im, std::istream& i)
00209     {
00210       if(!i.good())
00211       {
00212         //Check for one of the commonest errors and put in
00213         //a special case
00214         std::ifstream* fs;
00215         if((fs = dynamic_cast<std::ifstream*>(&i)) && !fs->is_open())
00216           throw Exceptions::Image_IO::IfstreamNotOpen();
00217         else
00218           throw Exceptions::Image_IO::EofBeforeImage();
00219       }
00220       unsigned char c = i.peek();
00221       
00222       if(!i.good())
00223         throw Exceptions::Image_IO::EofBeforeImage();
00224 
00225       if(c == 'P')
00226         PNM::readPNM(im, i);
00227 #ifdef CVD_HAVE_JPEG
00228       else if(c == 0xff)
00229         CVD::Internal::readImage<I, JPEG::reader>(im, i);
00230 #endif
00231 #ifdef CVD_HAVE_TIFF
00232       else if(c == 'I' || c == 'M') //Little or big endian TIFF
00233         CVD::Internal::readImage<I, TIFF::tiff_reader>(im, i);
00234 #endif
00235 #ifdef CVD_HAVE_PNG
00236       else if(c == 0x89)
00237         CVD::Internal::readImage<I, PNG::png_reader>(im, i);
00238 #endif
00239       else if(c == 'B')
00240         BMP::readBMP(im, i);
00241       else if(c == 'S')
00242         CVD::Internal::readImage<I, FITS::reader>(im, i);
00243       else if(c == ' ' || c == '\t' || isdigit(c) || c == '-' || c == '+')
00244         CVD::Internal::readImage<I, TEXT::reader>(im, i);
00245       else
00246         throw Exceptions::Image_IO::UnsupportedImageType();
00247     }
00248     
00249     //  syg21
00250     template<class I> void img_load(Image<I> &im, const std::string &s)
00251     {
00252       std::ifstream i(s.c_str(), std::ios::in|std::ios::binary);
00253 
00254       if(!i.good())
00255         throw Exceptions::Image_IO::OpenError(s, "for reading", errno);
00256       img_load(im, i);
00257     }   
00258 
00259 
00261     //
00262     // Image saving
00263     //
00264 
00265 
00268     ImageType::ImageType string_to_image_type(const std::string& name);
00269     
00270 
00278     template<class PixelType> 
00279     void img_save(const BasicImage<PixelType>& im, std::ostream& o, ImageType::ImageType t)
00280     {
00281       switch (t) {
00282       default:
00283       case ImageType::PNM:  
00284       case ImageType::Automatic:
00285       case ImageType::Unknown:
00286         Internal::writeImage<PixelType, PNM::pnm_writer>(im, o); break;
00287       #ifdef CVD_HAVE_JPEG
00288           case ImageType::JPEG: Internal::writeImage<PixelType, JPEG::writer>(im,o); break;
00289       #endif
00290       #ifdef CVD_HAVE_PNG
00291           case ImageType::PNG: Internal::writeImage<PixelType, PNG::png_writer>(im,o); break;
00292       #endif
00293       #ifdef CVD_HAVE_TIFF
00294           case ImageType::TIFF: Internal::writeImage<PixelType, TIFF::tiff_writer>(im,o); break;
00295       #endif
00296       case ImageType::BMP: BMP::writeBMP(im, o); break;
00297       case ImageType::TXT: Internal::writeImage<PixelType, TEXT::writer>(im, o); break;
00298       case ImageType::PS:   Internal::writeImage<PixelType, PS::writer>(im, o); break;
00299       case ImageType::EPS:   Internal::writeImage<PixelType, PS::eps_writer>(im, o); break;
00300       }
00301     }
00302 
00303     template<class PixelType> void img_save(const BasicImage<PixelType>& im, const std::string& name, ImageType::ImageType t, ImageType::ImageType d = ImageType::PNM)
00304     {
00305       std::ofstream out(name.c_str(), std::ios::out|std::ios::binary);
00306       if(!out.good())
00307         throw Exceptions::Image_IO::OpenError(name, "for writing", errno);
00308 
00309       if(t == ImageType::Automatic)
00310       {
00311         t = string_to_image_type(name);
00312         if(t == ImageType::Unknown)
00313             t = d;
00314       }
00315 
00316       img_save(im, out, t);
00317     }
00318 
00319     template<class PixelType> void img_save(const BasicImage<PixelType>& im, const std::string& name)
00320     {
00321         img_save(im, name, ImageType::Automatic);
00322     }
00323 
00325     //
00326     // Legacy pnm_* functions
00327     //
00328 
00335     template<class PixelType> void pnm_save(const BasicImage<PixelType>& im, std::ostream& o)
00336     {
00337         img_save(im, o, ImageType::PNM);
00338     }
00339 
00356     template<class PixelType> void pnm_load(Image<PixelType>& im, std::istream& i)
00357     {
00358         img_load(im, i);
00359     }
00360 
00362     //
00363     // Postscript helper functions
00364     //
00365 
00369     void output_eps_footer(std::ostream& o);
00370 
00378     void output_eps_header(std::ostream& o, int xs, int ys);
00379 
00380 
00387     void output_eps_header(std::ostream & o, const ImageRef& s);
00388 
00395     template<class PixelType> void output_eps_header(std::ostream& o, const BasicImage<PixelType>& im)
00396     {
00397         output_eps_header(o, im.size());
00398     }
00399 
00400 
00401 
00402 }
00403 
00404 #endif

Generated on Wed Feb 18 10:23:01 2009 for CVD by  doxygen 1.5.3