IT++ Logo Newcom Logo

pnm.cpp

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

Generated on Thu Apr 19 14:18:32 2007 for IT++ by Doxygen 1.5.1