00001
00002
00003
00004 #include <fstream>
00005 #include "ppm_image.h"
00006
00008 image::image_t*
00009 image::ppm::load( const std::string& filename )
00010 {
00011
00012 std::ifstream stream( filename.c_str( ) );
00013 if( !stream ) {
00014
00015 return NULL;
00016 }
00017
00018
00019 image_t* img = load( stream );
00020
00021
00022 stream.close( );
00023
00024
00025 return img;
00026 }
00027
00029 image::image_t*
00030 image::ppm::load( std::istream& stream )
00031 {
00032
00033 char c;
00034
00035
00036 stream.read( &c, 1 );
00037 if( c != 'P' ) return NULL;
00038
00039
00040 stream.read( &c, 1 );
00041 if( c == '2' ) {
00042 return load_ascii_pgm( stream );
00043 } else if( c == '3' ) {
00044 return load_ascii_ppm( stream );
00045 } else if( c == '5' ) {
00046 return load_binary_pgm( stream );
00047 } else if( c == '6' ) {
00048 return load_binary_ppm( stream );
00049 } else {
00050 return NULL;
00051 }
00052 }
00053
00055 bool
00056 image::ppm::can_load( const std::string& filename )
00057 {
00058
00059 std::ifstream stream( filename.c_str( ) );
00060 if( !stream ) {
00061
00062 return false;
00063 }
00064
00065
00066 bool loadable = can_load( stream );
00067
00068
00069 stream.close( );
00070
00071
00072 return loadable;
00073 }
00074
00076 bool
00077 image::ppm::can_load( std::istream& stream )
00078 {
00079
00080 char c;
00081
00082
00083 std::streampos save = stream.tellg( );
00084
00085
00086 stream.read( &c, 1 );
00087 if( c != 'P' ) return false;
00088
00089
00090 stream.read( &c, 1 );
00091
00092
00093 stream.seekg( save );
00094
00095 if( (c == '2') || (c == '3') || (c == '5') || (c == '6') ) {
00096 return true;
00097 }
00098
00099
00100 return false;
00101 }
00102
00104 image::image_t*
00105 image::ppm::load_ascii_pgm( std::istream& stream )
00106 {
00107
00108 std::string line;
00109 unsigned int rows, cols, pixels;
00110 float max, g;
00111 unsigned int gn;
00112
00113
00114 getline( stream, line );
00115
00116
00117 while( stream.peek( ) == '#' ) {
00118
00119 getline( stream, line );
00120 }
00121
00122
00123 if( !(stream >> cols) ) return NULL;
00124
00125
00126 if( !(stream >> rows) ) return NULL;
00127
00128
00129 if( !(stream >> max) ) return NULL;
00130 if( max == 0.0 ) return NULL;
00131
00132
00133 image_t *img = new image_t( cols, rows, image_t::GREYSCALE, image_t::BYTE );
00134 img->seek( 0, 0 );
00135
00136
00137 pixels = rows * cols;
00138 for( unsigned int i = 0; i < pixels; ++i ) {
00139 if( !(stream >> g) ) {
00140
00141 delete img;
00142 return NULL;
00143 }
00144
00145
00146 gn = static_cast<unsigned int>(g / max * 255.0);
00147
00148
00149 img->write( gn );
00150 }
00151
00152
00153 return img;
00154 }
00155
00157 image::image_t*
00158 image::ppm::load_ascii_ppm( std::istream& stream )
00159 {
00160
00161 std::string line;
00162 unsigned int rows, cols, pixels;
00163 float max, r, g, b;
00164 unsigned int rn, gn, bn;
00165
00166
00167 getline( stream, line );
00168
00169
00170 while( stream.peek( ) == '#' ) {
00171
00172 getline( stream, line );
00173 }
00174
00175
00176 if( !(stream >> cols) ) return NULL;
00177
00178
00179 if( !(stream >> rows) ) return NULL;
00180
00181
00182 if( !(stream >> max) ) return NULL;
00183 if( max == 0.0 ) return NULL;
00184
00185
00186 image_t *img = new image_t( cols, rows, image_t::RGB, image_t::BYTE );
00187 img->seek( 0, 0 );
00188
00189
00190 pixels = rows * cols;
00191 for( unsigned int i = 0; i < pixels; ++i ) {
00192 if( !(stream >> r >> g >> b) ) {
00193
00194 delete img;
00195 return NULL;
00196 }
00197
00198
00199 rn = static_cast<unsigned int>(r / max * 255.0);
00200 gn = static_cast<unsigned int>(g / max * 255.0);
00201 bn = static_cast<unsigned int>(b / max * 255.0);
00202
00203
00204 img->write( rn, gn, bn );
00205 }
00206
00207
00208 return img;
00209 }
00210
00212 image::image_t*
00213 image::ppm::load_binary_pgm( std::istream& stream )
00214 {
00215
00216 std::string line;
00217 unsigned int rows, cols, pixels;
00218 float max;
00219 char g;
00220 unsigned int gn;
00221
00222
00223 getline( stream, line );
00224
00225
00226 while( stream.peek( ) == '#' ) {
00227
00228 getline( stream, line );
00229 }
00230
00231
00232 if( !(stream >> cols) ) return NULL;
00233
00234
00235 if( !(stream >> rows) ) return NULL;
00236
00237
00238 if( !(stream >> max) ) return NULL;
00239 if( max == 0.0 ) return NULL;
00240
00241
00242 getline( stream, line );
00243
00244
00245 image_t *img = new image_t( cols, rows, image_t::GREYSCALE, image_t::BYTE );
00246 img->seek( 0, 0 );
00247
00248
00249 pixels = rows * cols;
00250 for( unsigned int i = 0; i < pixels; ++i ) {
00251 if( !stream.read( &g, 1 ) ) {
00252
00253 delete img;
00254 return NULL;
00255 }
00256
00257
00258 gn = static_cast<unsigned int>(static_cast<unsigned char>( g ) / max * 255.0);
00259
00260
00261 img->write( gn );
00262 }
00263
00264
00265 return img;
00266 }
00267
00269 image::image_t*
00270 image::ppm::load_binary_ppm( std::istream& stream )
00271 {
00272
00273 std::string line;
00274 unsigned int rows, cols, pixels;
00275 float max;
00276 char r, g, b;
00277 unsigned int rn, gn, bn;
00278
00279
00280 getline( stream, line );
00281
00282
00283 while( stream.peek( ) == '#' ) {
00284
00285 getline( stream, line );
00286 }
00287
00288
00289 if( !(stream >> cols) ) return NULL;
00290
00291
00292 if( !(stream >> rows) ) return NULL;
00293
00294
00295 if( !(stream >> max) ) return NULL;
00296 if( max == 0.0 ) return NULL;
00297
00298
00299 getline( stream, line );
00300
00301
00302 image_t *img = new image_t( cols, rows, image_t::RGB, image_t::BYTE );
00303 img->seek( 0, 0 );
00304
00305
00306 pixels = rows * cols;
00307 for( unsigned int i = 0; i < pixels; ++i ) {
00308 if( !(stream.read( &r, 1 ) &&
00309 stream.read( &g, 1 ) &&
00310 stream.read( &b, 1 )) ) {
00311
00312 delete img;
00313 return NULL;
00314 }
00315
00316
00317 rn = static_cast<unsigned int>(static_cast<unsigned char>( r ) / max * 255.0);
00318 gn = static_cast<unsigned int>(static_cast<unsigned char>( g ) / max * 255.0);
00319 bn = static_cast<unsigned int>(static_cast<unsigned char>( b ) / max * 255.0);
00320
00321
00322 img->write( rn, gn, bn );
00323 }
00324
00325
00326 return img;
00327 }