00001 /*!@file Raster/PnmWriter.C Write pbm/pgm/ppm image files */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005 // 00005 // by the University of Southern California (USC) and the iLab at USC. // 00006 // See http://iLab.usc.edu for information about this project. // 00007 // //////////////////////////////////////////////////////////////////// // 00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00010 // in Visual Environments, and Applications'' by Christof Koch and // 00011 // Laurent Itti, California Institute of Technology, 2001 (patent // 00012 // pending; application number 09/912,225 filed July 23, 2001; see // 00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00014 // //////////////////////////////////////////////////////////////////// // 00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00016 // // 00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00018 // redistribute it and/or modify it under the terms of the GNU General // 00019 // Public License as published by the Free Software Foundation; either // 00020 // version 2 of the License, or (at your option) any later version. // 00021 // // 00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00025 // PURPOSE. See the GNU General Public License for more details. // 00026 // // 00027 // You should have received a copy of the GNU General Public License // 00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00030 // Boston, MA 02111-1307 USA. // 00031 // //////////////////////////////////////////////////////////////////// // 00032 // 00033 // Primary maintainer for this file: Rob Peters <rjpeters at usc dot edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Raster/PnmWriter.C $ 00035 // $Id: PnmWriter.C 14290 2010-12-01 21:44:03Z itti $ 00036 // 00037 00038 #ifndef RASTER_PNMWRITER_C_DEFINED 00039 #define RASTER_PNMWRITER_C_DEFINED 00040 00041 #include "Raster/PnmWriter.H" 00042 00043 #include "Image/Image.H" 00044 #include "Image/Normalize.H" 00045 #include "Image/Pixels.H" 00046 #include "Raster/GenericFrame.H" 00047 #include "Raster/PfmWriter.H" 00048 00049 #include <fstream> 00050 00051 // ###################################################################### 00052 PnmWriter::PnmWriter(const bool forcepbm, const byte pbmthresh) 00053 : 00054 itsForcePBM(forcepbm), 00055 itsPBMThresh(pbmthresh) 00056 {} 00057 00058 // ###################################################################### 00059 PnmWriter::~PnmWriter() {} 00060 00061 // ###################################################################### 00062 std::string PnmWriter::writeFrame(const GenericFrame& image, 00063 const std::string& fnameorig) 00064 { 00065 if (itsForcePBM) 00066 { 00067 PnmWriter::writeRawBW(image.asGray(), itsPBMThresh, fnameorig); 00068 return fnameorig; 00069 } 00070 00071 std::string fname = fnameorig; 00072 00073 switch (image.nativeType()) 00074 { 00075 case GenericFrame::NONE: 00076 LFATAL("can't write an empty image to '%s'", fname.c_str()); 00077 break; 00078 00079 case GenericFrame::RGB_U8: 00080 case GenericFrame::RGBD: 00081 PnmWriter::writeRGB(image.asRgbU8(), fname); 00082 break; 00083 00084 case GenericFrame::RGB_U16: 00085 PnmWriter::writeRGB(image.asRgbU16(), fname); 00086 break; 00087 00088 case GenericFrame::RGB_F32: 00089 PnmWriter::writeRGB(image.asRgbU8(), fname); 00090 break; 00091 00092 case GenericFrame::GRAY_U8: 00093 PnmWriter::writeGray(image.asGrayU8(), fname); 00094 break; 00095 00096 case GenericFrame::GRAY_U16: 00097 PnmWriter::writeGray(image.asGrayU16(), fname); 00098 break; 00099 00100 case GenericFrame::GRAY_F32: 00101 { 00102 if (image.floatFlags() & FLOAT_NORM_PRESERVE) 00103 { 00104 // make a new filename with a ".pfm" extension, either by 00105 // replacing an existing ".pgm" or ".ppm" or ".pnm" 00106 // extension, or by just tacking on a new ".pfm" extension 00107 std::string::size_type len = fname.length(); 00108 if ((len > 4) 00109 && (fname.compare(len-4, 4, ".pgm") == 0 || 00110 fname.compare(len-4, 4, ".ppm") == 0 || 00111 fname.compare(len-4, 4, ".pnm") == 0)) 00112 { 00113 fname[len-2] = 'f'; 00114 } 00115 else 00116 { 00117 fname += ".pfm"; 00118 } 00119 PfmWriter::writeFloat(image.asGrayF32(), fname); 00120 } 00121 else 00122 { 00123 PnmWriter::writeGray(image.asGrayU8(), fname); 00124 } 00125 } 00126 break; 00127 00128 case GenericFrame::VIDEO: 00129 PnmWriter::writeRGB(image.asRgb(), fname); 00130 break; 00131 } 00132 00133 return fname; 00134 } 00135 00136 // ###################################################################### 00137 void PnmWriter::writeRGB(const Image<PixRGB<byte> >& image, 00138 std::ostream& strm) 00139 { 00140 strm << "P6\n" << image.getWidth() << ' ' << image.getHeight() 00141 << "\n255\n"; 00142 strm.write(reinterpret_cast<const char*>(image.getArrayPtr()), 00143 3 * image.getSize()); 00144 } 00145 00146 // ###################################################################### 00147 void PnmWriter::writeGray(const Image<byte>& image, 00148 std::ostream& strm) 00149 { 00150 strm << "P5\n" << image.getWidth() << ' ' << image.getHeight() 00151 << "\n255\n"; 00152 strm.write(reinterpret_cast<const char*>(image.getArrayPtr()), 00153 image.getSize()); 00154 } 00155 00156 // ###################################################################### 00157 void PnmWriter::writeRawBW(const Image<byte>& image, const byte thresh, 00158 std::ostream& strm) 00159 { 00160 strm << "P4\n" << image.getWidth() << ' ' << image.getHeight() << '\n'; 00161 00162 Image<byte>::const_iterator itr = image.begin(), stop = image.end(); 00163 00164 int c = 0; 00165 int pos = 7; 00166 00167 while (itr != stop) 00168 { 00169 if (*itr++ >= thresh) 00170 { /* leave bit at zero */ } // "0" ==> white pixel 00171 else 00172 c |= (1 << pos); // "1" ==> black pixel 00173 00174 if (pos == 0 || (itr == stop)) 00175 { 00176 strm.put(byte(c)); 00177 c = 0; 00178 pos = 7; 00179 } 00180 else 00181 --pos; 00182 } 00183 } 00184 00185 // ###################################################################### 00186 void PnmWriter::writeAsciiBW(const Image<byte>& image, const byte thresh, 00187 std::ostream& strm) 00188 { 00189 strm << "P1\n" << image.getWidth() << ' ' << image.getHeight() << '\n'; 00190 00191 Image<byte>::const_iterator itr = image.begin(); 00192 00193 for (int j = 0; j < image.getHeight(); ++j) 00194 { 00195 for (int i = 0; i < image.getWidth(); ++i) 00196 { 00197 if (*itr++ >= thresh) 00198 strm << "0 "; // "0" ==> white pixel 00199 else 00200 strm << "1 "; // "1" ==> black pixel 00201 } 00202 strm << '\n'; 00203 } 00204 } 00205 00206 // ###################################################################### 00207 void PnmWriter::writeRGB(const Image<PixRGB<byte> >& image, 00208 const std::string& fname) 00209 { 00210 std::ofstream ofs(fname.c_str(), std::ios::binary); 00211 if (!ofs.is_open()) 00212 LFATAL("Couldn't open PNM file '%s' for writing.", fname.c_str()); 00213 00214 PnmWriter::writeRGB(image, ofs); 00215 00216 ofs.close(); 00217 if (ofs.fail()) 00218 LFATAL("Output stream failure while writing '%s'.", fname.c_str()); 00219 } 00220 00221 // ###################################################################### 00222 void PnmWriter::writeGray(const Image<byte>& image, 00223 const std::string& fname) 00224 { 00225 std::ofstream ofs(fname.c_str(), std::ios::binary); 00226 if (!ofs.is_open()) 00227 LFATAL("Couldn't open PNM file '%s' for writing.", fname.c_str()); 00228 00229 PnmWriter::writeGray(image, ofs); 00230 00231 if (ofs.fail()) 00232 LFATAL("Output stream failure while writing '%s'.", fname.c_str()); 00233 } 00234 00235 // ###################################################################### 00236 void PnmWriter::writeRawBW(const Image<byte>& image, const byte thresh, 00237 const std::string& fname) 00238 { 00239 std::ofstream ofs(fname.c_str(), std::ios::binary); 00240 if (!ofs.is_open()) 00241 LFATAL("Couldn't open PNM file '%s' for writing.", fname.c_str()); 00242 00243 PnmWriter::writeRawBW(image, thresh, ofs); 00244 00245 if (ofs.fail()) 00246 LFATAL("Output stream failure while writing '%s'.", fname.c_str()); 00247 } 00248 00249 // ###################################################################### 00250 void PnmWriter::writeAsciiBW(const Image<byte>& image, const byte thresh, 00251 const std::string& fname) 00252 { 00253 std::ofstream ofs(fname.c_str(), std::ios::binary); 00254 if (!ofs.is_open()) 00255 LFATAL("Couldn't open PNM file '%s' for writing.", fname.c_str()); 00256 00257 PnmWriter::writeAsciiBW(image, thresh, ofs); 00258 00259 if (ofs.fail()) 00260 LFATAL("Output stream failure while writing '%s'.", fname.c_str()); 00261 } 00262 00263 // ###################################################################### 00264 /* So things look consistent in everyone's emacs... */ 00265 /* Local Variables: */ 00266 /* mode: c++ */ 00267 /* indent-tabs-mode: nil */ 00268 /* End: */ 00269 00270 #endif // RASTER_PNMWRITER_C_DEFINED