IT++ Logo

pnm.cpp

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

Generated on Fri Aug 14 15:28:28 2009 for IT++ by Doxygen 1.5.9