00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00039 #include "pgm.h"
00040
00041 #include <stdio.h>
00042 #include <stdlib.h>
00043 #include <string.h>
00044
00051 static int
00052 remove_line(FILE* f)
00053 {
00054 int count = 0 ;
00055 int c ;
00056
00057 while (1) {
00058 c = fgetc(f) ;
00059 ++ count ;
00060
00061 switch(c) {
00062 case '\n' :
00063 goto quit_remove_line ;
00064
00065 case EOF :
00066 -- count ;
00067 goto quit_remove_line ;
00068 }
00069 }
00070 quit_remove_line :
00071 return count ;
00072 }
00073
00080 static int
00081 remove_blanks(FILE* f)
00082 {
00083 int count = 0 ;
00084 int c ;
00085
00086 while (1) {
00087 c = fgetc(f) ;
00088
00089 switch(c) {
00090
00091 case '\t' : case '\n' :
00092 case '\r' : case ' ' :
00093 ++ count ;
00094 break ;
00095
00096 case '#' :
00097 count += 1 + remove_line(f) ;
00098 break ;
00099
00100 case EOF :
00101 goto quit_remove_blanks ;
00102
00103 default:
00104 ungetc(c, f) ;
00105 goto quit_remove_blanks ;
00106 }
00107 }
00108 quit_remove_blanks:
00109 return count ;
00110 }
00111
00124 VL_EXPORT vl_size
00125 vl_pgm_get_npixels (VlPgmImage const *im)
00126 {
00127 return im->width * im->height ;
00128 }
00129
00139 VL_EXPORT vl_size
00140 vl_pgm_get_bpp (VlPgmImage const *im)
00141 {
00142 return (im->max_value >= 256) + 1 ;
00143 }
00144
00160 VL_EXPORT int
00161 vl_pgm_extract_head (FILE* f, VlPgmImage *im)
00162 {
00163 char magic [2] ;
00164 int c ;
00165 int is_raw ;
00166 int width ;
00167 int height ;
00168 int max_value ;
00169 size_t sz ;
00170 vl_bool good ;
00171
00172
00173
00174
00175 sz = fread(magic, 1, 2, f) ;
00176
00177 if (sz < 2) {
00178 return vl_set_last_error(VL_ERR_PGM_INV_HEAD, "Invalid PGM header") ;
00179 }
00180
00181 good = magic [0] == 'P' ;
00182
00183 switch (magic [1]) {
00184 case '2' :
00185 is_raw = 0 ;
00186 break ;
00187
00188 case '5' :
00189 is_raw = 1 ;
00190 break ;
00191
00192 default :
00193 good = 0 ;
00194 break ;
00195 }
00196
00197 if( ! good ) {
00198 return vl_set_last_error(VL_ERR_PGM_INV_HEAD, "Invalid PGM header") ;
00199 }
00200
00201
00202
00203
00204 good = 1 ;
00205
00206 c = remove_blanks(f) ;
00207 good &= c > 0 ;
00208
00209 c = fscanf(f, "%d", &width) ;
00210 good &= c == 1 ;
00211
00212 c = remove_blanks(f) ;
00213 good &= c > 0 ;
00214
00215 c = fscanf(f, "%d", &height) ;
00216 good &= c == 1 ;
00217
00218 c = remove_blanks(f) ;
00219 good &= c > 0 ;
00220
00221 c = fscanf(f, "%d", &max_value) ;
00222 good &= c == 1 ;
00223
00224
00225 c = fgetc(f) ;
00226 good &=
00227 c == '\n' ||
00228 c == '\t' ||
00229 c == ' ' ||
00230 c == '\r' ;
00231
00232 if(! good) {
00233 return vl_set_last_error(VL_ERR_PGM_INV_META, "Invalid PGM meta information");
00234 }
00235
00236 if(! max_value >= 65536) {
00237 return vl_set_last_error(VL_ERR_PGM_INV_META, "Invalid PGM meta information");
00238 }
00239
00240
00241 im-> width = width ;
00242 im-> height = height ;
00243 im-> max_value = max_value ;
00244 im-> is_raw = is_raw ;
00245 return 0 ;
00246 }
00247
00261 VL_EXPORT
00262 int
00263 vl_pgm_extract_data (FILE* f, VlPgmImage const *im, void *data)
00264 {
00265 vl_size bpp = vl_pgm_get_bpp(im) ;
00266 vl_size data_size = vl_pgm_get_npixels(im) ;
00267 vl_bool good = 1 ;
00268 size_t c ;
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280 if (im->is_raw) {
00281
00282 c = fread( data,
00283 bpp,
00284 data_size,
00285 f ) ;
00286 good = (c == data_size) ;
00287
00288
00289 #if defined(VL_ARCH_LITTLE_ENDIAN)
00290 if (bpp == 2) {
00291 vl_uindex i ;
00292 vl_uint8 *pt = (vl_uint8*) data ;
00293 for(i = 0 ; i < 2 * data_size ; i += 2) {
00294 vl_uint8 tmp = pt [i] ;
00295 pt [i] = pt [i+1] ;
00296 pt [i+1] = tmp ;
00297 }
00298 }
00299 #endif
00300 }
00301
00302
00303
00304
00305 else {
00306 vl_uindex i ;
00307 int unsigned v ;
00308 for(good = 1, i = 0 ;
00309 i < data_size && good ;
00310 ++i) {
00311 c = fscanf(f, " %ud", &v) ;
00312 if (bpp == 1) {
00313 * ((vl_uint8* ) data + i) = (vl_uint8) v ;
00314 } else {
00315 * ((vl_uint16*) data + i) = (vl_uint16) v ;
00316 }
00317 good &= c == 1 ;
00318 }
00319 }
00320
00321 if(! good ) {
00322 return vl_set_last_error(VL_ERR_PGM_INV_DATA, "Invalid PGM data") ;
00323 }
00324 return 0 ;
00325 }
00326
00335 VL_EXPORT
00336 int
00337 vl_pgm_insert(FILE* f, VlPgmImage const *im, void const *data)
00338 {
00339 vl_size bpp = vl_pgm_get_bpp (im) ;
00340 vl_size data_size = vl_pgm_get_npixels (im) ;
00341 size_t c ;
00342
00343
00344 fprintf(f,
00345 "P5\n%d\n%d\n%d\n",
00346 (signed)im->width,
00347 (signed)im->height,
00348 (signed)im->max_value) ;
00349
00350
00351 #if defined(VL_ARCH_LITTLE_ENDIAN)
00352 if (bpp == 2) {
00353 vl_uindex i ;
00354 vl_uint8* temp = vl_malloc (2 * data_size) ;
00355 memcpy(temp, data, 2 * data_size) ;
00356 for(i = 0 ; i < 2 * data_size ; i += 2) {
00357 vl_uint8 tmp = temp [i] ;
00358 temp [i] = temp [i+1] ;
00359 temp [i+1] = tmp ;
00360 }
00361 c = fwrite(temp, 2, data_size, f) ;
00362 vl_free (temp) ;
00363 }
00364 else {
00365 #endif
00366 c = fwrite(data, bpp, data_size, f) ;
00367 #if defined(VL_ARCH_LITTLE_ENDIAN)
00368 }
00369 #endif
00370
00371 if(c != data_size) {
00372 return vl_set_last_error(VL_ERR_PGM_IO, "Error writing PGM data") ;
00373 }
00374 return 0 ;
00375 }
00376
00393 VL_EXPORT
00394 int vl_pgm_read_new (char const *name, VlPgmImage *im, vl_uint8** data)
00395 {
00396 int err = 0 ;
00397 FILE *f = fopen (name, "rb") ;
00398
00399 if (! f) {
00400 return vl_set_last_error(VL_ERR_PGM_IO, "Error opening PGM file `%s' for reading", name) ;
00401 }
00402
00403 err = vl_pgm_extract_head(f, im) ;
00404 if (err) {
00405 fclose (f) ;
00406 return err ;
00407 }
00408
00409 if (vl_pgm_get_bpp(im) > 1) {
00410 return vl_set_last_error(VL_ERR_BAD_ARG, "PGM with BPP > 1 not supported") ;
00411 }
00412
00413 *data = vl_malloc (vl_pgm_get_npixels(im) * sizeof(vl_uint8)) ;
00414 err = vl_pgm_extract_data(f, im, *data) ;
00415
00416 if (err) {
00417 vl_free (data) ;
00418 fclose (f) ;
00419 }
00420
00421 fclose (f) ;
00422 return err ;
00423 }
00424
00442 VL_EXPORT
00443 int vl_pgm_read_new_f (char const *name, VlPgmImage *im, float** data)
00444 {
00445 int err = 0 ;
00446 size_t npixels ;
00447 vl_uint8 *idata ;
00448
00449 err = vl_pgm_read_new (name, im, &idata) ;
00450 if (err) {
00451 return err ;
00452 }
00453
00454 npixels = vl_pgm_get_npixels(im) ;
00455 *data = vl_malloc (sizeof(float) * npixels) ;
00456 {
00457 size_t k ;
00458 float scale = 1.0f / (float)im->max_value ;
00459 for (k = 0 ; k < npixels ; ++ k) (*data)[k] = scale * idata[k] ;
00460 }
00461
00462 vl_free (idata) ;
00463 return 0 ;
00464 }
00465
00479 VL_EXPORT
00480 int vl_pgm_write (char const *name, vl_uint8 const* data, int width, int height)
00481 {
00482 int err = 0 ;
00483 VlPgmImage pgm ;
00484 FILE *f = fopen (name, "wb") ;
00485
00486 if (! f) {
00487 return vl_set_last_error(VL_ERR_PGM_IO,
00488 "Error opening PGM file '%s' for writing", name) ;
00489 }
00490
00491 pgm.width = width ;
00492 pgm.height = height ;
00493 pgm.is_raw = 1 ;
00494 pgm.max_value = 255 ;
00495
00496 err = vl_pgm_insert (f, &pgm, data) ;
00497 fclose (f) ;
00498
00499 return err ;
00500 }
00501
00516 VL_EXPORT
00517 int vl_pgm_write_f (char const *name, float const* data, int width, int height)
00518 {
00519 int err = 0 ;
00520 int k ;
00521 float min = + VL_INFINITY_F ;
00522 float max = - VL_INFINITY_F ;
00523 float scale ;
00524
00525 vl_uint8 * buffer = vl_malloc (sizeof(float) * width * height) ;
00526
00527 for (k = 0 ; k < width * height ; ++k) {
00528 min = VL_MIN(min, data [k]) ;
00529 max = VL_MAX(max, data [k]) ;
00530 }
00531
00532 scale = 255 / (max - min + VL_EPSILON_F) ;
00533
00534 for (k = 0 ; k < width * height ; ++k) {
00535 buffer [k] = (vl_uint8) ((data [k] - min) * scale) ;
00536 }
00537
00538 err = vl_pgm_write (name, buffer, width, height) ;
00539
00540 vl_free (buffer) ;
00541 return err ;
00542 }