00001
00006
00007
00008
00009
00010
00011
00012
00034 #include "pgm.h"
00035
00036 #include <stdio.h>
00037 #include <stdlib.h>
00038 #include <string.h>
00039
00047 static int
00048 remove_line(FILE* f)
00049 {
00050 int count = 0 ;
00051 int c ;
00052
00053 while (1) {
00054 c = fgetc(f) ;
00055 ++ count ;
00056
00057 switch(c) {
00058 case '\n' :
00059 goto quit_remove_line ;
00060
00061 case EOF :
00062 -- count ;
00063 goto quit_remove_line ;
00064 }
00065 }
00066 quit_remove_line :
00067 return count ;
00068 }
00069
00077 static int
00078 remove_blanks(FILE* f)
00079 {
00080 int count = 0 ;
00081 int c ;
00082
00083 while (1) {
00084 c = fgetc(f) ;
00085
00086 switch(c) {
00087
00088 case '\t' : case '\n' :
00089 case '\r' : case ' ' :
00090 ++ count ;
00091 break ;
00092
00093 case '#' :
00094 count += 1 + remove_line(f) ;
00095 break ;
00096
00097 case EOF :
00098 goto quit_remove_blanks ;
00099
00100 default:
00101 ungetc(c, f) ;
00102 goto quit_remove_blanks ;
00103 }
00104 }
00105 quit_remove_blanks:
00106 return count ;
00107 }
00108
00123 VL_EXPORT
00124 int
00125 vl_pgm_get_npixels (VlPgmImage const *im)
00126 {
00127 return im->width * im->height ;
00128 }
00129
00141 VL_EXPORT
00142 int
00143 vl_pgm_get_bpp (VlPgmImage const *im)
00144 {
00145 return (im->max_value >= 256) + 1 ;
00146 }
00147
00163 VL_EXPORT
00164 int
00165 vl_pgm_extract_head (FILE* f, VlPgmImage *im)
00166 {
00167 char magic [2] ;
00168 int c ;
00169 int is_raw ;
00170 int width ;
00171 int height ;
00172 int max_value ;
00173 int sz ;
00174 vl_bool good ;
00175
00176
00177
00178
00179
00180 sz = fread(magic, 1, 2, f) ;
00181
00182 if (sz < 2) {
00183 vl_err_no = VL_ERR_PGM_INV_HEAD ;
00184 return -1 ;
00185 }
00186
00187 good = magic [0] == 'P' ;
00188
00189 switch (magic [1]) {
00190 case '2' :
00191 is_raw = 0 ;
00192 break ;
00193
00194 case '5' :
00195 is_raw = 1 ;
00196 break ;
00197
00198 default :
00199 good = 0 ;
00200 break ;
00201 }
00202
00203 if( ! good ) {
00204 vl_err_no = VL_ERR_PGM_INV_HEAD ;
00205 return -1 ;
00206 }
00207
00208
00209
00210
00211 good = 1 ;
00212
00213 c = remove_blanks(f) ;
00214 good &= c > 0 ;
00215
00216 c = fscanf(f, "%d", &width) ;
00217 good &= c == 1 ;
00218
00219 c = remove_blanks(f) ;
00220 good &= c > 0 ;
00221
00222 c = fscanf(f, "%d", &height) ;
00223 good &= c == 1 ;
00224
00225 c = remove_blanks(f) ;
00226 good &= c > 0 ;
00227
00228 c = fscanf(f, "%d", &max_value) ;
00229 good &= c == 1 ;
00230
00231
00232 c = fgetc(f) ;
00233 good &=
00234 c == '\n' ||
00235 c == '\t' ||
00236 c == ' ' ||
00237 c == '\r' ;
00238
00239 if(! good) {
00240 vl_err_no = VL_ERR_PGM_INV_META ;
00241 return vl_err_no ;
00242 }
00243
00244 if(! max_value >= 65536) {
00245 vl_err_no = VL_ERR_PGM_INV_META ;
00246 return vl_err_no ;
00247 }
00248
00249
00250 im-> width = width ;
00251 im-> height = height ;
00252 im-> max_value = max_value ;
00253 im-> is_raw = is_raw ;
00254 return 0 ;
00255 }
00256
00272 VL_EXPORT
00273 int
00274 vl_pgm_extract_data (FILE* f, VlPgmImage const *im, void *data)
00275 {
00276 int bpp = vl_pgm_get_bpp (im) ;
00277 int data_size = vl_pgm_get_npixels (im) ;
00278 int c ;
00279 vl_bool good = 1 ;
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291 if (im->is_raw) {
00292
00293 c = fread( data,
00294 bpp,
00295 data_size,
00296 f ) ;
00297 good = (c == data_size) ;
00298
00299
00300 #if defined(VL_ARCH_LITTLE_ENDIAN)
00301 if (bpp == 2) {
00302 int i ;
00303 vl_uint8 *pt = (vl_uint8*) data ;
00304 for(i = 0 ; i < 2 * data_size ; i += 2) {
00305 vl_uint8 tmp = pt [i] ;
00306 pt [i] = pt [i+1] ;
00307 pt [i+1] = tmp ;
00308 }
00309 }
00310 #endif
00311 }
00312
00313
00314
00315
00316 else {
00317 int i ;
00318 int unsigned v ;
00319 for(good = 1, i = 0 ;
00320 i < data_size && good ;
00321 ++i) {
00322 c = fscanf(f, " %ud", &v) ;
00323 if (bpp == 1) {
00324 * ((vl_uint8* ) data + i) = (vl_uint8) v ;
00325 } else {
00326 * ((vl_uint16*) data + i) = (vl_uint16) v ;
00327 }
00328 good &= c == 1 ;
00329 }
00330 }
00331
00332 if(! good ) {
00333 vl_err_no = VL_ERR_PGM_INV_DATA ;
00334 snprintf(vl_err_msg, VL_ERR_MSG_LEN,
00335 "Invalid PGM data") ;
00336 return vl_err_no ;
00337 }
00338 return 0 ;
00339 }
00340
00350 VL_EXPORT
00351 int
00352 vl_pgm_insert(FILE* f, VlPgmImage const *im, void const *data)
00353 {
00354 int bpp = vl_pgm_get_bpp (im) ;
00355 int data_size = vl_pgm_get_npixels (im) ;
00356 int c ;
00357
00358
00359 fprintf(f,
00360 "P5\n%d\n%d\n%d\n",
00361 im->width,
00362 im->height,
00363 im->max_value) ;
00364
00365
00366 #if defined(VL_ARCH_LITTLE_ENDIAN)
00367 if (bpp == 2) {
00368 int i ;
00369 vl_uint8* temp = vl_malloc (2 * data_size) ;
00370 memcpy(temp, data, 2 * data_size) ;
00371 for(i = 0 ; i < 2 * data_size ; i += 2) {
00372 vl_uint8 tmp = temp [i] ;
00373 temp [i] = temp [i+1] ;
00374 temp [i+1] = tmp ;
00375 }
00376 c = fwrite(temp, 2, data_size, f) ;
00377 vl_free (temp) ;
00378 }
00379 else {
00380 #endif
00381 c = fwrite(data, bpp, data_size, f) ;
00382 #if defined(VL_ARCH_LITTLE_ENDIAN)
00383 }
00384 #endif
00385
00386 if(c != data_size) {
00387 vl_err_no = VL_ERR_PGM_IO ;
00388 snprintf(vl_err_msg, VL_ERR_MSG_LEN,
00389 "Error writing PGM data") ;
00390 return vl_err_no ;
00391 }
00392 return 0 ;
00393 }
00394
00413 VL_EXPORT
00414 int vl_pgm_read_new (char const *name, VlPgmImage *im, vl_uint8** data)
00415 {
00416 int err = 0 ;
00417
00418 FILE *f = fopen (name, "rb") ;
00419
00420 if (! f) {
00421 vl_err_no = VL_ERR_PGM_IO ;
00422 snprintf(vl_err_msg, VL_ERR_MSG_LEN,
00423 "Error opening PGM file `%s' for reading", name) ;
00424 return vl_err_no ;
00425 }
00426
00427 err = vl_pgm_extract_head(f, im) ;
00428 if (err) {
00429 fclose (f) ;
00430 return err ;
00431 }
00432
00433 if (vl_pgm_get_bpp(im) > 1) {
00434 vl_err_no = VL_ERR_BAD_ARG ;
00435 snprintf(vl_err_msg, VL_ERR_MSG_LEN,
00436 "vl_pgm_read(): PGM with BPP > 1 not supported") ;
00437 return vl_err_no ;
00438 }
00439
00440 *data = vl_malloc (vl_pgm_get_npixels(im) * sizeof(vl_uint8)) ;
00441 err = vl_pgm_extract_data(f, im, *data) ;
00442
00443 if (err) {
00444 vl_free (data) ;
00445 fclose (f) ;
00446 }
00447
00448 fclose (f) ;
00449 return err ;
00450 }
00451
00471 VL_EXPORT
00472 int vl_pgm_read_new_f (char const *name, VlPgmImage *im, float** data)
00473 {
00474 int err = 0 ;
00475 size_t npixels ;
00476 vl_uint8 *idata ;
00477
00478 err = vl_pgm_read_new (name, im, &idata) ;
00479 if (err) {
00480 return err ;
00481 }
00482
00483 npixels = vl_pgm_get_npixels(im) ;
00484 *data = vl_malloc (sizeof(float) * npixels) ;
00485 {
00486 size_t k ;
00487 float scale = 1.0f / im->max_value ;
00488 for (k = 0 ; k < npixels ; ++ k) (*data)[k] = scale * idata[k] ;
00489 }
00490
00491 vl_free (idata) ;
00492 return err ;
00493 }
00494
00510 VL_EXPORT
00511 int vl_pgm_write (char const *name, vl_uint8 const* data, int width, int height)
00512 {
00513 int err = 0 ;
00514 VlPgmImage pgm ;
00515
00516 FILE *f = fopen (name, "wb") ;
00517
00518 if (! f) {
00519 vl_err_no = VL_ERR_PGM_IO ;
00520 snprintf(vl_err_msg, VL_ERR_MSG_LEN,
00521 "Error opening PGM file for writing") ;
00522 return vl_err_no ;
00523 }
00524
00525 pgm.width = width ;
00526 pgm.height = height ;
00527 pgm.is_raw = 1 ;
00528 pgm.max_value = 255 ;
00529
00530 err = vl_pgm_insert (f, &pgm, data) ;
00531 fclose (f) ;
00532
00533 return err ;
00534 }
00535
00552 VL_EXPORT
00553 int vl_pgm_write_f (char const *name, float const* data, int width, int height)
00554 {
00555 int err = 0 ;
00556 int k ;
00557 float min = + VL_INFINITY_F ;
00558 float max = - VL_INFINITY_F ;
00559 float scale ;
00560
00561 vl_uint8 * buffer = vl_malloc (sizeof(float) * width * height) ;
00562
00563 for (k = 0 ; k < width * height ; ++k) {
00564 min = VL_MIN(min, data [k]) ;
00565 max = VL_MAX(max, data [k]) ;
00566 }
00567
00568 scale = 255 / (max - min + VL_EPSILON_F) ;
00569
00570 for (k = 0 ; k < width * height ; ++k) {
00571 buffer [k] = (vl_uint8) ((data [k] - min) * scale) ;
00572 }
00573
00574 err = vl_pgm_write (name, buffer, width, height) ;
00575
00576 vl_free (buffer) ;
00577 return err ;
00578 }