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   // 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 
SourceForge Logo

Generated on Sun Sep 14 18:52:28 2008 for IT++ by Doxygen 1.5.6