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 // 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 { 00163 int rtmp = r2; 00164 r2 = r1; 00165 r1 = rtmp; 00166 } 00167 00168 if( c1 > c2 ) 00169 { 00170 int ctmp = c2; 00171 c2 = c1; 00172 c1 = ctmp; 00173 } 00174 00175 if( r1 < 0 ) 00176 it_error( "Bad parameter value : row number must be >=0" ); 00177 00178 if( c1 < 0 ) 00179 it_error( "Bad parameter value : column number must be >=0" ); 00180 00181 if (r2 >= height ) 00182 it_error( "Bad parameter value : row number exceeds the image heigth" ); 00183 00184 if( c1 >= width ) 00185 it_error( "Bad parameter value : column number exceeds the image width" ); 00186 00187 m.set_size( r2-r1+1, c2-c1+1, false ); 00188 file.seekg( r1 * width + c1, ios::cur ); 00189 00190 for( i = 0 ; i < m.rows() ; i++ ) 00191 { 00192 for( j = 0 ; j < m.cols() ; j++ ) 00193 m( i, j ) = file.get(); 00194 file.seekg( width - ( c2-c1+1 ), ios::cur ); 00195 } 00196 00197 return true; 00198 } 00199 00200 00201 //-------------------------------------------------------------- 00202 bool pgm_write( const string & filename, 00203 const imat &m, const string & comments ) 00204 { 00205 00206 ofstream file; 00207 int i, j; 00208 00209 file.open( filename.c_str(), ofstream::out | ofstream::binary ); 00210 00211 if (!pnm_write_header(file, '5', m.cols(), m.rows(), 255, comments )) 00212 return false; 00213 00214 for (i=0; i<m.rows(); i++) 00215 for (j=0; j<m.cols(); j++) 00216 file.put( m(i,j) ); 00217 00218 if (!file) 00219 return false; 00220 00221 return true; 00222 } 00223 00224 00225 //-------------------------------------------------------------- 00226 // PPM related functions (color images) 00227 //-------------------------------------------------------------- 00228 00229 bool ppm_read( const string & filename, 00230 imat &r, imat &g, imat &b, 00231 string & comments ) 00232 { 00233 ifstream file; 00234 int width, height, max_val, i, j; 00235 00236 file.open(filename.c_str(), ifstream::in | ifstream::binary); 00237 00238 char pnm_type; 00239 if(!pnm_read_header(file, pnm_type, width, height, max_val, comments, '6' ) ) 00240 return false; 00241 00242 r.set_size(height, width, false); 00243 g.set_size(height, width, false); 00244 b.set_size(height, width, false); 00245 for (i=0; i<height; i++) 00246 for (j=0; j<width; j++) { 00247 r(i,j) = file.get(); 00248 g(i,j) = file.get(); 00249 b(i,j) = file.get(); 00250 } 00251 00252 return true; 00253 } 00254 00255 00256 //-------------------------------------------------------------- 00257 // Same function but suppress the comments 00258 bool ppm_read( const string & filename, 00259 imat &r, imat &g, imat &b ) 00260 { 00261 string comments; // This is a dummy variable 00262 00263 return ppm_read( filename, r, g, b, comments ); 00264 } 00265 00266 //-------------------------------------------------------------- 00267 bool ppm_read( const string & filename, 00268 imat &r, imat &g, imat &b, 00269 int r1, int r2, int c1, int c2) 00270 { 00271 ifstream file; 00272 int width, height, max_val, i, j; 00273 00274 // This is a dummy variable. Its purpose is the call of function pnm_read_header. 00275 string comments; 00276 00277 file.open(filename.c_str(), ifstream::in | ifstream::binary); 00278 00279 char pnm_type; 00280 if (!pnm_read_header(file, pnm_type, width, height, max_val, comments, '6' ) ) 00281 return false; 00282 00283 // Inversion of the column/row numbers may be required 00284 if( r1 > r2 ) 00285 { 00286 // Funny way to do it... (without using any temporary variable) 00287 r1 += r2; 00288 r2 = r1 - r2; 00289 r1 -= r2; 00290 } 00291 00292 if( c1 > c2 ) 00293 { 00294 // Conventionnal way to do it 00295 int ctmp = c2; 00296 c2 = c1; 00297 c1 = ctmp; 00298 } 00299 00300 if( r1 < 0 ) 00301 it_error( "Bad parameter value : row number must be >=0" ); 00302 00303 if( c1 < 0 ) 00304 it_error( "Bad parameter value : column number must be >=0" ); 00305 00306 if (r2 >= height ) 00307 it_error( "Bad parameter value : row number exceeds the image heigth" ); 00308 00309 if( c1 >= width) 00310 it_error( "Bad parameter value : column number exceeds the image width" ); 00311 00312 r.set_size( r2-r1+1, c2-c1+1, false); 00313 g.set_size( r2-r1+1, c2-c1+1, false); 00314 b.set_size( r2-r1+1, c2-c1+1, false); 00315 file.seekg( 3 *( r1 * width + c1 ), ios::cur); 00316 00317 for (i=0; i<r.rows(); i++) { 00318 for (j=0; j<r.cols(); j++) { 00319 r(i,j) = file.get(); 00320 g(i,j) = file.get(); 00321 b(i,j) = file.get(); 00322 } 00323 file.seekg( 3 * ( width - (c2-c1+1) ), ios::cur); 00324 } 00325 00326 return true; 00327 } 00328 00329 00330 //-------------------------------------------------------------- 00331 bool ppm_write( const string & filename, 00332 const imat &r, const imat &g, const imat &b, 00333 const string & comments, 00334 int max_val ) 00335 { 00336 ofstream file; 00337 int i, j; 00338 00339 it_assert_debug(r.cols() == g.cols() && g.cols() == b.cols() && 00340 r.rows() == g.rows() && g.rows() == b.rows(), 00341 "Matrices r, g and b must have the same size in ppm_write()"); 00342 00343 file.open( filename.c_str(), ofstream::out | ofstream::binary ); 00344 00345 if( max_val < 0 || max_val > 65535 ) 00346 { 00347 it_warning( "Proposed maximal value is incorrect" ); 00348 return false; 00349 } 00350 00351 if (!pnm_write_header(file, '6', r.cols(), r.rows(), max_val, comments )) 00352 return false; 00353 00354 for (i=0; i<r.rows(); i++) 00355 for (j=0; j<r.cols(); j++) { 00356 file.put( r(i,j) ); 00357 file.put( g(i,j) ); 00358 file.put( b(i,j) ); 00359 } 00360 00361 if (!file) 00362 return false; 00363 00364 return true; 00365 } 00366 00367 00368 //-------------------------------------------------------------- 00369 imat img_double2int( const mat & m, 00370 int max_val, 00371 double double_min, 00372 double double_max ) 00373 { 00374 int i, j; 00375 imat M( m.rows(), m.cols() ); 00376 00377 for( i = 0 ; i < m.rows() ; i++ ) 00378 for( j = 0 ; j < m.cols() ; j++ ) 00379 if( m( i, j ) <= double_min ) 00380 M( i, j ) = 0; 00381 00382 else if( m( i, j ) >= double_max ) 00383 M( i, j ) = max_val; 00384 00385 else 00386 M( i, j ) = (int) ( max_val * ( m( i, j ) - double_min ) 00387 / ( double_max - double_min ) + 0.5 ); 00388 00389 return M; 00390 } 00391 00392 //-------------------------------------------------------------- 00393 mat img_int2double( const imat & m, 00394 int max_val, 00395 double double_min, 00396 double double_max ) 00397 { 00398 int i, j; 00399 mat M( m.rows(), m.cols() ); 00400 00401 for( i = 0 ; i < m.rows() ; i++ ) 00402 for( j = 0 ; j < m.cols() ; j++ ) 00403 if( m( i, j ) <= 0 ) 00404 M( i, j ) = double_min; 00405 00406 else if( m( i, j ) >= max_val ) 00407 M( i, j ) = double_max; 00408 00409 else 00410 // This rounding works well when m(i,j) is positive 00411 M( i, j ) = double_min + ( double_max - double_min ) 00412 * m( i, j ) / (double) max_val; 00413 00414 return M; 00415 } 00416 00417 00418 //-------------------------------------------------------------- 00419 // Static functions: Used in this file only 00420 //-------------------------------------------------------------- 00421 00422 //-------------------------------------------------------------- 00423 static void pnm_read_comments( istream & i, string & comments ) 00424 { 00425 while (isspace(i.peek())) 00426 { 00427 while (isspace(i.peek())) 00428 i.get(); 00429 00430 if (i.peek() == '#') 00431 while (i.peek()!='\r' && i.peek()!='\n') 00432 comments += i.get(); 00433 } 00434 } 00435 00436 00437 //-------------------------------------------------------------- 00438 static void pnm_write_comments( ostream & o, const string & comments ) 00439 { 00440 istringstream comments_stream( comments ); 00441 char comment_line[ 256 ]; 00442 00443 // Put header and comment 00444 while( !comments_stream.eof() ) 00445 { 00446 o << "#"; 00447 comments_stream.get( comment_line, 256 ); 00448 o << comment_line << endl; 00449 } 00450 } 00451 00452 00453 //-------------------------------------------------------------- 00454 // Read the header of a pnm file 00455 static bool pnm_read_header( ifstream & file, char & pnm_type, 00456 int & width, int & height, int & max_val, 00457 string & comments, char pnm_type_required ) 00458 { 00459 bool return_code = true; 00460 00461 if (file.get() != 'P') 00462 return_code = false; 00463 00464 if( !return_code ) 00465 it_error("Invalid format file: code of file format has not been found"); 00466 00467 // Read the type of the pnm file 00468 pnm_type = file.get(); 00469 00470 if( pnm_type < '1' || pnm_type > '6' ) 00471 it_error("Bad file code P" << pnm_type); 00472 00473 // If a type has been specified 00474 if( pnm_type_required != '0' ) 00475 if( pnm_type_required != pnm_type ) 00476 { 00477 string err_msg( "Found file code P" ); 00478 err_msg += pnm_type + " instead of P" + pnm_type_required; 00479 it_error( err_msg ); 00480 } 00481 00482 // Retrieve the image format and the comments 00483 pnm_read_comments(file, comments ); 00484 file >> width; 00485 pnm_read_comments(file, comments ); 00486 file >> height; 00487 pnm_read_comments(file, comments ); 00488 00489 if( height < 0 || width < 0 ) 00490 it_error( "Bad image size" ); 00491 00492 // Maximal values is not present in PBM files 00493 if( pnm_type == '2' || pnm_type == '3' || pnm_type == '5' || pnm_type == '6' ) 00494 file >> max_val; 00495 00496 file.get(); // Eat the last whitespace 00497 00498 // According to the pnm specification, the maximal value should not 00499 // be greater than 65536 and lower than 0 00500 if( max_val >= 65536 || max_val < 0 ) 00501 it_error( "Invalid maximum number in pnm header" ); 00502 00503 // For type P5 and P6, the value have to be lower than 255 00504 if( ( pnm_type == '5' || pnm_type == '6' ) && max_val > 255 ) 00505 it_error( "Invalid maximum number in pnm header" ); 00506 00507 return file.good(); 00508 } 00509 00510 00511 //-------------------------------------------------------------- 00512 static bool pnm_write_header( ofstream &file, char pnm_type, 00513 int width, int height, int max_val, 00514 const string & comments ) 00515 { 00516 file << 'P' << pnm_type << endl; 00517 pnm_write_comments( file, comments ); 00518 file << width << ' ' << height << endl; 00519 00520 // Maximal values is not present in PBM files 00521 if( pnm_type == '2' || pnm_type == '3' || pnm_type == '5' || pnm_type == '6' ) 00522 file << max_val << endl; 00523 00524 return file.good(); 00525 } 00526 00527 } // namespace itpp 00528
Generated on Mon Jan 7 22:28:59 2008 for IT++ by Doxygen 1.5.4