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