00001 /*!@file Raster/PfzParser.C Parse pfm image files. */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the // 00005 // 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: T. Nathan Mundhenk <mundhenk@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Raster/PfzParser.C $ 00035 // $Id: PfzParser.C 8027 2007-03-02 00:40:43Z rjpeters $ 00036 // 00037 00038 #include "Raster/PfzParser.H" 00039 00040 #include "Util/Assert.H" 00041 #include "Image/Image.H" 00042 #include "Image/Pixels.H" 00043 #include "Raster/GenericFrame.H" 00044 #include "Util/log.H" 00045 00046 #include <fstream> 00047 #include <limits> 00048 #include <string> 00049 #include <deque> 00050 00051 // ###################################################################### 00052 struct PfzParser::Rep 00053 { 00054 Rep(const char* fname) : 00055 strm(fname), mode('\0'), w(-1), h(-1), maxGrey(1), comments(""), tags(0) 00056 {} 00057 00058 std::ifstream strm; 00059 std::stringstream os; 00060 char mode; 00061 int w, h; 00062 float maxGrey; 00063 std::string comments; 00064 std::deque<std::string> tagName; 00065 std::deque<std::string> tagValue; 00066 uint tags; 00067 }; 00068 00069 // ###################################################################### 00070 PfzParser::PfzParser(const char* fname) : 00071 rep(new Rep(fname)) 00072 { 00073 /* allocate inflate state */ 00074 zstrm.zalloc = Z_NULL; 00075 zstrm.zfree = Z_NULL; 00076 zstrm.opaque = Z_NULL; 00077 zstrm.avail_in = 0; 00078 zstrm.next_in = Z_NULL; 00079 const int retI = inflateInit(&zstrm); 00080 if (retI != Z_OK) 00081 LFATAL("Unable to allocate memory and set up zlib compression in PFZ '%s'", 00082 fname); 00083 00084 if (!rep->strm.is_open()) 00085 LFATAL("Couldn't open file '%s' for reading.", fname); 00086 00087 int c = rep->strm.get(); 00088 if (c != 'P') 00089 LFATAL("Missing magic number in pbm file '%s'.", fname); 00090 00091 rep->tagName.clear(); 00092 rep->tagValue.clear(); 00093 00094 rep->strm >> rep->mode; 00095 00096 rep->strm >> std::ws; 00097 00098 // copy and concatenate optional UNCOMPRESSED 00099 // comment line(s) starting with '#' 00100 // into comments string 00101 00102 std::string temp; 00103 00104 while ( rep->strm.peek() == '#' ) 00105 { 00106 //get the full line 00107 std::getline( rep->strm, temp, '\n'); 00108 rep->comments += temp; 00109 //LINFO("%s",temp.c_str()); 00110 //This is what we did before we were interested in the comments 00111 } 00112 00113 rep->strm >> std::ws; 00114 00115 // read in chunks from zipped PFZ file 00116 while(rep->strm.good()) 00117 { 00118 rep->strm.read(reinterpret_cast<char*>(buff_uin),PFZ_CHUNK); 00119 zstrm.avail_in = rep->strm.gcount(); 00120 zstrm.next_in = buff_uin; 00121 00122 // each input chunk is taken in sizes that zlib can handle 00123 zstrm.avail_out = 0; 00124 while (zstrm.avail_out == 0) 00125 { 00126 zstrm.avail_out = PFZ_CHUNK; 00127 zstrm.next_out = buff_uout; 00128 00129 const int ret = inflate(&zstrm, Z_NO_FLUSH); 00130 if(ret == Z_STREAM_ERROR) 00131 LFATAL("Stream Error in zlib decompression of PFZ image '%s'",fname); 00132 switch (ret) 00133 { 00134 case Z_NEED_DICT: 00135 LINFO("zlib needs dictionary in opening PFZ '%s'",fname); 00136 case Z_DATA_ERROR: 00137 LFATAL("zlib data error in opening PFZ '%s'",fname); 00138 case Z_MEM_ERROR: 00139 LFATAL("zlib memory error in opening PFZ '%s'",fname); 00140 } 00141 const uint have = PFZ_CHUNK - zstrm.avail_out; 00142 rep->os.write(reinterpret_cast<char*>(buff_uout),have); 00143 } 00144 } 00145 00146 rep->os >> rep->w >> rep->h; 00147 00148 if (rep->mode != 1 && rep->mode != 4) 00149 { 00150 rep->os >> rep->maxGrey; 00151 } 00152 00153 // copy and concatenate optional COMPRESSED 00154 // tags starting with '!' 00155 // into comments string 00156 00157 rep->os >> std::ws; 00158 00159 while ( rep->os.peek() == '!' ) 00160 { 00161 // get the full line, remove leading ! 00162 std::getline( rep->os, temp, '\n'); 00163 temp = temp.substr(1,temp.length()); 00164 rep->tagName.push_back(temp); 00165 // the next line contains the data with this tag 00166 std::getline( rep->os, temp, '\n'); 00167 rep->tagValue.push_back(temp); 00168 } 00169 00170 // read one more character of whitespace from the stream after maxGrey 00171 c = rep->os.get(); 00172 if ( !isspace(c) ) 00173 LFATAL("Missing whitespace after maxGrey in PFZ file '%s'.", fname); 00174 LDEBUG("PFM Reading Image: %s", fname); 00175 00176 inflateEnd(&zstrm); 00177 } 00178 00179 // ###################################################################### 00180 PfzParser::~PfzParser() 00181 { 00182 delete rep; 00183 } 00184 00185 // ###################################################################### 00186 GenericFrameSpec PfzParser::getFrameSpec() const 00187 { 00188 GenericFrameSpec result; 00189 00190 result.nativeType = GenericFrame::GRAY_F32; 00191 result.videoFormat = VIDFMT_AUTO; 00192 result.videoByteSwap = false; 00193 result.dims = Dims(rep->w, rep->h); 00194 result.floatFlags = 0; 00195 00196 return result; 00197 } 00198 00199 // ###################################################################### 00200 std::string PfzParser::getComments() const 00201 { return rep->comments; } 00202 00203 // ###################################################################### 00204 uint PfzParser::getTagCount() const 00205 { return rep->tags; } 00206 00207 // ###################################################################### 00208 bool PfzParser::getTag(uint tag, std::string &name, std::string &value) const 00209 { 00210 if(tag < rep->tagName.size()) 00211 { 00212 name = rep->tagName[tag]; 00213 value = rep->tagValue[tag]; 00214 return true; 00215 } 00216 else 00217 return false; 00218 } 00219 00220 // ###################################################################### 00221 GenericFrame PfzParser::getFrame() 00222 { return GenericFrame(parseFloat(), /* flags */ 0); } 00223 00224 // ###################################################################### 00225 void PfzParser::readFloats(float* space, int count) 00226 { 00227 ASSERT(rep->mode == 'Z'); 00228 rep->os.read(reinterpret_cast<char *>(space), count * sizeof(float)); 00229 } 00230 00231 // ###################################################################### 00232 Image<float> PfzParser::parseFloat() 00233 { 00234 ASSERT(rep->mode == 'Z'); 00235 00236 Image<float> img(rep->w, rep->h, NO_INIT); 00237 readFloats(img.getArrayPtr(), img.getSize()); 00238 return img; 00239 } 00240 00241 // ###################################################################### 00242 /* So things look consistent in everyone's emacs... */ 00243 /* Local Variables: */ 00244 /* indent-tabs-mode: nil */ 00245 /* End: */