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