IT++ Logo
pnm.cpp
Go to the documentation of this file.
00001 
00029 #include <itpp/srccode/pnm.h>
00030 #include <itpp/base/itassert.h>
00031 #include <fstream>
00032 
00034 
00035 using std::istream;
00036 using std::ostream;
00037 using std::endl;
00038 using std::string;
00039 using std::ifstream;
00040 using std::ofstream;
00041 using std::istringstream;
00042 using std::ios;
00043 using std::ios_base;
00044 using std::streampos;
00045 
00046 
00047 namespace itpp
00048 {
00049 
00050 
00051 // Suppress the additional white characters and return the comments
00052 static void pnm_read_comments(istream & i, string & comments);
00053 
00054 // Write comment in the image file
00055 static void pnm_write_comments(ostream & o, const string & comments);
00056 
00057 // Read/Write the header for the pnm file format
00058 static bool pnm_read_header(ifstream & file, char & pnm_type,
00059                             int & width, int & height, int & max_val,
00060                             string & comments, char pnm_type_required = '0');
00061 
00062 static bool pnm_write_header(ofstream & file, char type,
00063                              int width, int height, int max_val,
00064                              const string & comments);
00065 
00066 
00067 //--------------------------------------------------------------
00068 // General PNM functions
00069 //--------------------------------------------------------------
00070 char pnm_type(const string & filename)
00071 {
00072   ifstream file;
00073   char pnm_type;
00074 
00075   file.open(filename.c_str(), ifstream::in | ifstream::binary);
00076 
00077   string comments;
00078   int width, height, max_val;
00079   pnm_read_header(file, pnm_type, width, height, max_val, comments);
00080 
00081   return pnm_type;
00082 }
00083 
00084 
00085 //--------------------------------------------------------------
00086 bool pnm_info(const string & filename, char & pnm_type,
00087               int & width, int & height, int & max_val,
00088               string & comments)
00089 {
00090   ifstream file;
00091 
00092   file.open(filename.c_str(), ifstream::in | ifstream::binary);
00093 
00094   pnm_read_header(file, pnm_type, width, height, max_val, comments);
00095 
00096   return true;
00097 }
00098 
00099 
00100 //--------------------------------------------------------------
00101 // PGM related functions (gray images)
00102 //--------------------------------------------------------------
00103 
00104 bool pgm_read(const string & filename,
00105               imat & m, string & comments)
00106 {
00107   ifstream file;
00108   int width, height, max_val, i, j;
00109   comments = "";
00110 
00111   file.open(filename.c_str(), ifstream::in | ifstream::binary);
00112 
00113   // The format code is 'P5' for pgm files
00114   char pnm_type;
00115   if (!pnm_read_header(file, pnm_type, width, height, max_val, comments, '5'))
00116     return false;
00117 
00118   // Format the returned matrix
00119   m.set_size(height, width, false);
00120 
00121   // Retrieve the integer value from the file
00122   for (i = 0 ; i < height; i++)
00123     for (j = 0; j < width; j++)
00124       m(i, j) = file.get();
00125 
00126   return true;
00127 }
00128 
00129 
00130 //--------------------------------------------------------------
00131 // Simplified version of read_pgm
00132 imat pgm_read(const string & filename)
00133 {
00134   imat I;
00135   string comments;
00136   if (!pgm_read(filename, I, comments)) {
00137     it_warning("pgm_read (PGM file->imat) failed ");
00138   }
00139   return I;
00140 }
00141 
00142 
00143 //--------------------------------------------------------------
00144 bool pgm_read(const string & filename, imat &m,
00145               int r1, int r2, int c1, int c2)
00146 {
00147   ifstream file;
00148   int width, height, max_val, i, j;
00149 
00150   // This is a dummy variable.
00151   // Its purpose is the call of function pnm_read_header.
00152   string comments;
00153 
00154   file.open(filename.c_str(), ifstream::in | ifstream::binary);
00155 
00156   char pnm_type;
00157   if (!pnm_read_header(file, pnm_type, width, height, max_val, comments, '5'))
00158     return false;
00159 
00160   // Inversion of the column/row numbers may be required
00161   if (r1 > r2) {
00162     int rtmp = r2;
00163     r2 = r1;
00164     r1 = rtmp;
00165   }
00166 
00167   if (c1 > c2) {
00168     int ctmp = c2;
00169     c2 = c1;
00170     c1 = ctmp;
00171   }
00172 
00173   it_error_if((r1 < 0) || (c1 < 0),
00174               "Bad parameter value: row and column number must be >=0");
00175   it_error_if((r2 >= height) || (c1 >= width), "Bad parameter value: "
00176               "row or column number exceeds the image heigth");
00177 
00178   m.set_size(r2 - r1 + 1, c2 - c1 + 1, false);
00179   file.seekg(r1 * width + c1, ios::cur);
00180 
00181   for (i = 0 ; i < m.rows() ; i++) {
00182     for (j = 0 ; j < m.cols() ; j++)
00183       m(i, j) = file.get();
00184     file.seekg(width - (c2 - c1 + 1), ios::cur);
00185   }
00186 
00187   return true;
00188 }
00189 
00190 
00191 //--------------------------------------------------------------
00192 bool pgm_write(const string & filename,
00193                const imat &m, const string & comments)
00194 {
00195 
00196   ofstream file;
00197   int i, j;
00198 
00199   file.open(filename.c_str(), ofstream::out | ofstream::binary);
00200 
00201   if (!pnm_write_header(file, '5', m.cols(), m.rows(), 255, comments))
00202     return false;
00203 
00204   for (i = 0; i < m.rows(); i++)
00205     for (j = 0; j < m.cols(); j++)
00206       file.put(static_cast<char>(m(i, j)));
00207 
00208   if (!file)
00209     return false;
00210 
00211   return true;
00212 }
00213 
00214 
00215 //--------------------------------------------------------------
00216 // PPM related functions (color images)
00217 //--------------------------------------------------------------
00218 
00219 bool ppm_read(const string & filename,
00220               imat &r, imat &g, imat &b,
00221               string & comments)
00222 {
00223   ifstream file;
00224   int width, height, max_val, i, j;
00225 
00226   file.open(filename.c_str(), ifstream::in | ifstream::binary);
00227 
00228   char pnm_type;
00229   if (!pnm_read_header(file, pnm_type, width, height, max_val, comments, '6'))
00230     return false;
00231 
00232   r.set_size(height, width, false);
00233   g.set_size(height, width, false);
00234   b.set_size(height, width, false);
00235   for (i = 0; i < height; i++)
00236     for (j = 0; j < width; j++) {
00237       r(i, j) = file.get();
00238       g(i, j) = file.get();
00239       b(i, j) = file.get();
00240     }
00241 
00242   return true;
00243 }
00244 
00245 
00246 //--------------------------------------------------------------
00247 // Same function but suppress the comments
00248 bool ppm_read(const string & filename,
00249               imat &r, imat &g, imat &b)
00250 {
00251   string comments; // This is a dummy variable
00252 
00253   return ppm_read(filename, r, g, b, comments);
00254 }
00255 
00256 //--------------------------------------------------------------
00257 bool ppm_read(const string & filename,
00258               imat &r, imat &g, imat &b,
00259               int r1, int r2, int c1, int c2)
00260 {
00261   ifstream file;
00262   int width, height, max_val, i, j;
00263 
00264   // This is a dummy variable. Its purpose is the call of function pnm_read_header.
00265   string comments;
00266 
00267   file.open(filename.c_str(), ifstream::in | ifstream::binary);
00268 
00269   char pnm_type;
00270   if (!pnm_read_header(file, pnm_type, width, height, max_val, comments, '6'))
00271     return false;
00272 
00273   // Inversion of the column/row numbers may be required
00274   if (r1 > r2) {
00275     // Funny way to do it... (without using any temporary variable)
00276     r1 += r2;
00277     r2 = r1 - r2;
00278     r1 -= r2;
00279   }
00280 
00281   if (c1 > c2) {
00282     // Conventionnal way to do it
00283     int ctmp = c2;
00284     c2 = c1;
00285     c1 = ctmp;
00286   }
00287 
00288   it_error_if((r1 < 0) || (c1 < 0),
00289               "Bad parameter value: row and column number must be >=0");
00290   it_error_if((r2 >= height) || (c1 >= width), "Bad parameter value: "
00291               "row or column number exceeds the image heigth");
00292 
00293   r.set_size(r2 - r1 + 1, c2 - c1 + 1, false);
00294   g.set_size(r2 - r1 + 1, c2 - c1 + 1, false);
00295   b.set_size(r2 - r1 + 1, c2 - c1 + 1, false);
00296   file.seekg(3 *(r1 * width + c1), ios::cur);
00297 
00298   for (i = 0; i < r.rows(); i++) {
00299     for (j = 0; j < r.cols(); j++) {
00300       r(i, j) = file.get();
00301       g(i, j) = file.get();
00302       b(i, j) = file.get();
00303     }
00304     file.seekg(3 * (width - (c2 - c1 + 1)), ios::cur);
00305   }
00306 
00307   return true;
00308 }
00309 
00310 
00311 //--------------------------------------------------------------
00312 bool ppm_write(const string & filename,
00313                const imat &r, const imat &g, const imat &b,
00314                const string & comments,
00315                int max_val)
00316 {
00317   ofstream file;
00318   int i, j;
00319 
00320   it_assert_debug(r.cols() == g.cols() && g.cols() == b.cols() &&
00321                   r.rows() == g.rows() && g.rows() == b.rows(),
00322                   "Matrices r, g and b must have the same size in ppm_write()");
00323 
00324   file.open(filename.c_str(), ofstream::out | ofstream::binary);
00325 
00326   if (max_val < 0 || max_val > 65535) {
00327     it_warning("Proposed maximal value is incorrect");
00328     return false;
00329   }
00330 
00331   if (!pnm_write_header(file, '6', r.cols(), r.rows(), max_val, comments))
00332     return false;
00333 
00334   for (i = 0; i < r.rows(); i++)
00335     for (j = 0; j < r.cols(); j++) {
00336       file.put(static_cast<char>(r(i, j)));
00337       file.put(static_cast<char>(g(i, j)));
00338       file.put(static_cast<char>(b(i, j)));
00339     }
00340 
00341   if (!file)
00342     return false;
00343 
00344   return true;
00345 }
00346 
00347 
00348 //--------------------------------------------------------------
00349 imat img_double2int(const mat & m,
00350                     int max_val,
00351                     double double_min,
00352                     double double_max)
00353 {
00354   int i, j;
00355   imat M(m.rows(), m.cols());
00356 
00357   for (i = 0 ; i < m.rows() ; i++)
00358     for (j = 0 ; j < m.cols() ; j++)
00359       if (m(i, j) <= double_min)
00360         M(i, j) = 0;
00361 
00362       else if (m(i, j) >= double_max)
00363         M(i, j) = max_val;
00364 
00365       else
00366         M(i, j) = (int)(max_val * (m(i, j) - double_min)
00367                         / (double_max - double_min) + 0.5);
00368 
00369   return M;
00370 }
00371 
00372 //--------------------------------------------------------------
00373 mat img_int2double(const imat & m,
00374                    int max_val,
00375                    double double_min,
00376                    double double_max)
00377 {
00378   int i, j;
00379   mat M(m.rows(), m.cols());
00380 
00381   for (i = 0 ; i < m.rows() ; i++)
00382     for (j = 0 ; j < m.cols() ; j++)
00383       if (m(i, j) <= 0)
00384         M(i, j) = double_min;
00385 
00386       else if (m(i, j) >= max_val)
00387         M(i, j) = double_max;
00388 
00389       else
00390         // This rounding works well when m(i,j) is positive
00391         M(i, j) = double_min + (double_max - double_min)
00392                   * m(i, j) / (double) max_val;
00393 
00394   return M;
00395 }
00396 
00397 
00398 //--------------------------------------------------------------
00399 // Static functions: Used in this file only
00400 //--------------------------------------------------------------
00401 
00402 //--------------------------------------------------------------
00403 static void pnm_read_comments(istream & i, string & comments)
00404 {
00405   while (isspace(i.peek())) {
00406     while (isspace(i.peek()))
00407       i.get();
00408 
00409     if (i.peek() == '#')
00410       while (i.peek() != '\r' && i.peek() != '\n')
00411         comments += static_cast<char>(i.get());
00412   }
00413 }
00414 
00415 
00416 //--------------------------------------------------------------
00417 static void pnm_write_comments(ostream & o, const string & comments)
00418 {
00419   istringstream comments_stream(comments);
00420   char comment_line[ 256 ];
00421 
00422   // Put header and comment
00423   while (!comments_stream.eof()) {
00424     o << "#";
00425     comments_stream.get(comment_line, 256);
00426     o << comment_line << endl;
00427   }
00428 }
00429 
00430 
00431 //--------------------------------------------------------------
00432 // Read the header of a pnm file
00433 static bool pnm_read_header(ifstream & file, char & pnm_type,
00434                             int & width, int & height, int & max_val,
00435                             string & comments, char pnm_type_required)
00436 {
00437   bool return_code = true;
00438 
00439   if (file.get() != 'P')
00440     return_code = false;
00441   it_error_if(!return_code, "Invalid format file: code of file format has "
00442               "not been found");
00443 
00444   // Read the type of the pnm file
00445   file.get(pnm_type);
00446   it_error_if((pnm_type < '1') || (pnm_type > '6'),
00447               "Bad file code P" << pnm_type);
00448 
00449   // If a type has been specified
00450   if (pnm_type_required != '0')
00451     if (pnm_type_required != pnm_type) {
00452       string err_msg("Found file code P");
00453       err_msg += pnm_type + " instead of P" + pnm_type_required;
00454       it_error(err_msg);
00455     }
00456 
00457   // Retrieve the image format and the comments
00458   pnm_read_comments(file, comments);
00459   file >> width;
00460   pnm_read_comments(file, comments);
00461   file >> height;
00462   pnm_read_comments(file, comments);
00463 
00464   it_error_if((height < 0) || (width < 0), "Bad image size");
00465 
00466   // Maximal values is not present in PBM files
00467   if (pnm_type == '2' || pnm_type == '3' || pnm_type == '5' || pnm_type == '6')
00468     file >> max_val;
00469 
00470   file.get(); // Eat the last whitespace
00471 
00472   // According to the pnm specification, the maximal value should not
00473   // be greater than 65536 and lower than 0
00474   it_error_if((max_val >= 65536) || (max_val < 0),
00475               "Invalid maximum number in pnm header");
00476 
00477   // For type P5 and P6, the value have to be lower than 255
00478   it_error_if((pnm_type == '5' || pnm_type == '6') && (max_val > 255),
00479               "Invalid maximum number in pnm header");
00480 
00481   return file.good();
00482 }
00483 
00484 
00485 //--------------------------------------------------------------
00486 static bool pnm_write_header(ofstream &file, char pnm_type,
00487                              int width, int height, int max_val,
00488                              const string & comments)
00489 {
00490   file << 'P' << pnm_type << endl;
00491   pnm_write_comments(file, comments);
00492   file << width << ' ' << height << endl;
00493 
00494   // Maximal values is not present in PBM files
00495   if (pnm_type == '2' || pnm_type == '3' || pnm_type == '5' || pnm_type == '6')
00496     file << max_val << endl;
00497 
00498   return file.good();
00499 }
00500 
00501 } // namespace itpp
00502 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
SourceForge Logo

Generated on Sat Jul 9 2011 15:21:33 for IT++ by Doxygen 1.7.4