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
Generated on Sat Feb 26 2011 16:06:34 for IT++ by Doxygen 1.7.3