VLFeat.org

API docs

  • Home
    • Download and Install
    • API docs
    • Matlab docs
    • About VLFeat
  • Tutorials
    • SIFT
    • MSER
    • IKM
    • HIKM
    • AIB
    • Utils
  • Main Page
  • Related Pages
  • Data Structures
  • Files
  • Examples

pgm.c

Go to the documentation of this file.
00001 
00006 /* AUTORIGHTS
00007 Copyright 2007 (c) Andrea Vedaldi and Brian Fulkerson
00008 
00009 This file is part of VLFeat, available in the terms of the GNU
00010 General Public License version 2.
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    *                                                check magic number
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' : /* ASCII format */
00187     is_raw = 0 ;
00188     break ;
00189     
00190   case '5' : /* RAW format */
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    *                                    parse width, height, max_value
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   /* must end with a single blank */
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   /* exit */
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    *                                                         read data
00279    * -------------------------------------------------------------- */  
00280 
00281   /* 
00282      In RAW mode we read directly an array of bytes or shorts.  In
00283      the latter case, however, we must take care of the
00284      endianess. PGM files are sorted in big-endian format. If our
00285      architecture is little endian, we must do a conversion.
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     /* adjust endianess */
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      In ASCII mode we read a sequence of decimal numbers separated
00310      by whitespaces.
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   /* write preamble */
00355   fprintf(f,
00356           "P5\n%d\n%d\n%d\n",
00357           im->width,
00358           im->height,
00359           im->max_value) ;
00360 
00361   /* take care of endianness */
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 }
Copyright © 2008 Andrea Vedaldi and Brian Fulkerson