CVD 0.8
|
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