00001 /*!@file Raster/PfzWriter.C Write pfm 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: T. Nathan Mundenk <mundhenk@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Raster/PfzWriter.C $ 00035 // $Id: PfzWriter.C 14290 2010-12-01 21:44:03Z itti $ 00036 // 00037 00038 #ifndef RASTER_PFMWRITER_C_DEFINED 00039 #define RASTER_PFMWRITER_C_DEFINED 00040 00041 #include "Raster/PfzWriter.H" 00042 00043 #include "Image/Image.H" 00044 #include "Image/Pixels.H" 00045 #include "Raster/GenericFrame.H" 00046 00047 #include <fstream> 00048 #include <iostream> // for std::cerr 00049 #include <sstream> 00050 00051 PfzWriter::PfzWriter() {} 00052 00053 PfzWriter::~PfzWriter() {} 00054 00055 std::deque<std::string> PfzWriter::itsTagName(0); 00056 std::deque<std::string> PfzWriter::itsTagValue(0); 00057 z_stream PfzWriter::zstrm; 00058 unsigned char PfzWriter::buff_uin[PFZ_CHUNK]; 00059 unsigned char PfzWriter::buff_uout[PFZ_CHUNK]; 00060 int PfzWriter::itsCompressionLevel(PFZ_LEVEL); 00061 00062 std::string PfzWriter::writeFrame(const GenericFrame& image, 00063 const std::string& fname) 00064 { 00065 switch (image.nativeType()) 00066 { 00067 case GenericFrame::NONE: 00068 LFATAL("cannot write an empty image to '%s'", fname.c_str()); 00069 break; 00070 00071 case GenericFrame::RGB_U8: 00072 case GenericFrame::RGBD: 00073 LFATAL("cannot write an RGB byte image '%s' in PFZ format", fname.c_str()); 00074 break; 00075 00076 case GenericFrame::RGB_U16: 00077 LFATAL("cannot write an RGB byte image '%s' in PFZ format", fname.c_str()); 00078 break; 00079 00080 case GenericFrame::RGB_F32: 00081 LFATAL("cannot write an RGB float image '%s' in PFZ format", fname.c_str()); 00082 break; 00083 00084 case GenericFrame::GRAY_U8: 00085 PfzWriter::writeFloat(image.asFloat(), fname); 00086 break; 00087 00088 case GenericFrame::GRAY_U16: 00089 LFATAL("cannot write an 16 bit gray image '%s' in PFZ format", fname.c_str()); 00090 break; 00091 00092 case GenericFrame::GRAY_F32: 00093 PfzWriter::writeFloat(image.asFloat(), fname); 00094 break; 00095 00096 case GenericFrame::VIDEO: 00097 LFATAL("cannot write a video frame '%s' in PFZ format", fname.c_str()); 00098 break; 00099 } 00100 00101 return fname; 00102 } 00103 00104 void PfzWriter::writeFloat(const Image<float>& image, 00105 const std::string& fname, 00106 const std::deque<std::string> tagName, 00107 const std::deque<std::string> tagValue) 00108 { 00109 itsTagName = tagName; 00110 itsTagValue = tagValue; 00111 writeFloat(image,fname,true); 00112 } 00113 00114 void PfzWriter::writeFloat(const Image<float>& image, 00115 const std::string& fname, 00116 const bool useTag) 00117 { 00118 int flush = 0; 00119 00120 /* allocate deflate state */ 00121 zstrm.zalloc = Z_NULL; 00122 zstrm.zfree = Z_NULL; 00123 zstrm.opaque = Z_NULL; 00124 00125 // 00126 if((itsCompressionLevel < -1) || (itsCompressionLevel > 9)) 00127 LFATAL("Invalid compression level '%d' given for pfz image '%s'", 00128 itsCompressionLevel,fname.c_str()); 00129 00130 const int retI = deflateInit(&zstrm, itsCompressionLevel); 00131 00132 if (retI != Z_OK) 00133 LFATAL("Unable to allocate memory and set up zlib compression in PFZ '%s'", 00134 fname.c_str()); 00135 00136 // first we take the image into a standard stream for formating 00137 00138 std::stringstream os; 00139 std::ofstream ofs(fname.c_str(), std::ios::binary); 00140 if (!ofs.is_open()) 00141 LFATAL("Couldn't open PFZ file '%s' for writing.", fname.c_str()); 00142 00143 ofs << "PZ\n" 00144 << "# PFZ image - Mundhenk, Itti (C) 2006\n"; 00145 os << image.getWidth() << ' ' << image.getHeight() 00146 << "\n1.0\n" 00147 << "!Image Info\n" 00148 << "PFZ Image compressed floating point image for INVT\n" 00149 << "!URL\n" 00150 << "http://www.nerd-cam.com\n" 00151 << "!Compression Level\n" 00152 << itsCompressionLevel << "\n"; 00153 00154 // write extra tags if supplied, these will be compressed 00155 if(useTag) 00156 { 00157 std::deque<std::string>::iterator tagNameItr = itsTagName.begin(); 00158 std::deque<std::string>::iterator tagValueItr = itsTagValue.begin(); 00159 while(tagNameItr != itsTagName.end()) 00160 { 00161 os << "!" << *tagNameItr << "\n" << *tagValueItr << "\n"; 00162 ++tagNameItr; ++tagValueItr; 00163 } 00164 } 00165 00166 os << " "; 00167 00168 // push the image into the sstream 00169 os.write(reinterpret_cast<const char*>(image.getArrayPtr()), 00170 image.getSize() * sizeof(float)); 00171 00172 // sync the string stream buffers 00173 os.flush(); 00174 00175 // buffer each PFZ_CHUNK of the image stream into zlibs stream 00176 while(os.good()) 00177 { 00178 os.read(reinterpret_cast<char*>(buff_uin),PFZ_CHUNK); 00179 zstrm.avail_in = os.gcount(); 00180 /* 00181 unsigned char *uin = &buff_uin[0]; 00182 char *in = &buff_in[0]; 00183 for(uint i = 0; i < PFZ_CHUNK; i++) 00184 { 00185 *uin = clamped_convert<byte>(*in); 00186 ++uin; ++in; 00187 } 00188 */ 00189 zstrm.next_in = buff_uin; 00190 // for each in chunk, compress them, we use this inner loop 00191 // because zlib may not compress the entire chunk in one go and may 00192 // need to take it in several pieces 00193 // avail_out is set via pointer to 0 when we are done 00194 zstrm.avail_out = 0; 00195 00196 if(os.good()) 00197 flush = Z_NO_FLUSH; 00198 else 00199 flush = Z_FINISH; 00200 00201 while(zstrm.avail_out == 0) 00202 { 00203 zstrm.avail_out = PFZ_CHUNK; 00204 zstrm.next_out = buff_uout; 00205 const int ret = deflate(&zstrm, flush); 00206 00207 if(ret == Z_STREAM_ERROR) 00208 LFATAL("Error in PFZ zlib compression stream of image '%s'", 00209 fname.c_str()); 00210 00211 const uint have = PFZ_CHUNK - zstrm.avail_out; 00212 /* 00213 unsigned char *uout = &buff_uout[0]; 00214 char *out = &buff_out[0]; 00215 for(uint i = 0; i < have; i++) 00216 { 00217 *out = clamped_convert<char>(*uout); 00218 ++uout; ++out; 00219 } 00220 */ 00221 ofs.write(reinterpret_cast<char*>(buff_uout),have); 00222 if (ofs.fail()) 00223 LFATAL("Output stream failure while writing '%s'.", fname.c_str()); 00224 } 00225 } 00226 ofs.close(); 00227 deflateEnd(&zstrm); 00228 } 00229 00230 // ###################################################################### 00231 /* So things look consistent in everyone's emacs... */ 00232 /* Local Variables: */ 00233 /* mode: c++ */ 00234 /* indent-tabs-mode: nil */ 00235 /* End: */ 00236 00237 #endif // RASTER_PFMWRITER_C_DEFINED