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
Generated on Wed Jul 27 2011 16:27:05 for IT++ by Doxygen 1.7.4