extract_features.c File Reference

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <math.h>
#include <string.h>
#include <unistd.h>
#include <ppm.h>
#include "gift_features.h"
#include <stdint.h>

Go to the source code of this file.

Defines

#define numH   18
#define numS   3
#define numV   3
#define numGrey   4
#define OLDFIXED
#define num_gabor_scales   3
#define num_total_colour_blocks   (256+64+16+4)

Functions

void init_feature_variables (uint32_t, uint32_t **, uint32_t ***, uint32_t ***)
void extract_gabor_features (PPM *, uint32_t ***, uint32_t ***)
void extract_mode_features (PPM *, uint32_t *, uint32_t, uint32_t **, byte *, uint32_t *)
enum ppm_error write_mode_features (char *, uint32_t, uint32_t *, uint32_t ***, uint32_t ***, byte *)
int main (int argc, char *argv[])


Define Documentation

#define num_gabor_scales   3

Definition at line 28 of file extract_features.c.

#define num_total_colour_blocks   (256+64+16+4)

Definition at line 30 of file extract_features.c.

#define numGrey   4

Definition at line 23 of file extract_features.c.

Referenced by main().

#define numH   18

Definition at line 20 of file extract_features.c.

Referenced by main().

#define numS   3

Definition at line 21 of file extract_features.c.

Referenced by main().

#define numV   3

Definition at line 22 of file extract_features.c.

Referenced by main().

#define OLDFIXED

Definition at line 25 of file extract_features.c.


Function Documentation

void extract_gabor_features ( PPM ,
uint32_t ***  ,
uint32_t ***   
)

Definition at line 126 of file extract_block_features.c.

References create_filter_kernels(), gabor_block_size, gabor_filter(), gabor_ranges, _PPM::height, MAX_HEIGHT, MAX_WIDTH, num_gabor_ranges, num_gabor_scales, num_gabors_per_scale, square, _PPM::value_plane_double_reversed, and _PPM::width.

Referenced by main().

00126                                                                                                        {
00127 
00128   int i, j, x, y, k;
00129   int scale, orientation;
00130   int energy_class;
00131   PPM *value_plane;
00132   double *value_image_dbl, *filtered_image;
00133   double *conv;
00134   double *conv2;
00135   double gabor_mean;
00136   double * kernelsxy[num_gabor_scales*num_gabors_per_scale];
00137 
00138   /* for Gabor features, this is what I'm going to do:
00139     - Apply each of the 12 filters (3 scales, 4 orientations) to each
00140       pixel in the image.
00141     - Use 16x16 blocks only.
00142     - In each block find the rms energy of each filter.
00143     - quantize these into num_gabor_ranges levels, as specified in the
00144       "array" gabor_ranges[]
00145   */
00146 
00147   /* this is all created with one malloc, so that it can be cleared in one memset() call */
00148   filtered_image = (double *)malloc(im_hsv->width*im_hsv->height*sizeof(double)*3);
00149   conv=&filtered_image[im_hsv->width*im_hsv->height];
00150   conv2=&conv[im_hsv->width*im_hsv->height];
00151 
00152   create_filter_kernels(kernelsxy);
00153 
00154   /* apply each filter to the image */
00155   for (scale = 0; scale < num_gabor_scales; scale++) {
00156     for (orientation = 0; orientation < num_gabors_per_scale; orientation++) {
00157 
00158       /* this clears conv, conv2, and filtered_image in one call. */
00159       memset(filtered_image, 0, MAX_WIDTH*MAX_HEIGHT*sizeof(double)*3);
00160 
00161       /* filter the image */
00162       gabor_filter(im_hsv->value_plane_double_reversed, im_hsv->width, im_hsv->height, scale, orientation, kernelsxy, conv, conv2, filtered_image);
00163 
00164       /* extract the rms energy for each block */
00165       k = 0; /* block counter */
00166       for (y = 0; y < im_hsv->height; y += gabor_block_size) {
00167       for (x = 0; x < im_hsv->width; x += gabor_block_size) {
00168         gabor_mean = 0;
00169         for (i = 0; (i < gabor_block_size) &&  (y+i < im_hsv->height); i++) {
00170         for (j = 0; (j < gabor_block_size) &&  (x+j < im_hsv->height); j++) {
00171           gabor_mean += square((filtered_image[(y + i)*im_hsv->width + (x + j)]));
00172         }
00173         }
00174         gabor_mean /= square(gabor_block_size);
00175         gabor_mean = sqrt(gabor_mean);
00176 
00177         /* find the energy class for this block */
00178         for (energy_class = 0; energy_class < num_gabor_ranges; energy_class++) {
00179           if (gabor_mean < gabor_ranges(energy_class))
00180             break;
00181         }
00182 
00183         /* store this class in the appropriate place */
00184         block_gabor_class[scale][orientation][k] = energy_class;
00185 
00186         /* increment the histogram entry for this combination */
00187         gabor_histogram[scale][orientation][energy_class]++;
00188         
00189         k++; /* increment block counter */
00190       }
00191       }
00192     }
00193   }
00194 }

void extract_mode_features ( PPM ,
uint32_t *  ,
uint32_t  ,
uint32_t **  ,
byte ,
uint32_t *   
)

Definition at line 196 of file extract_block_features.c.

References _PPM::bytes_per_pixel, colmap2rgb_ppm(), destroy_ppm(), _PPM::height, hsv2rgb_ppm(), image_size, _PPM::max_col_comp, new_ppm(), num_colour_scales, PGM_RAW, _PPM::pixel, ppm_handle_error(), PPM_OK, PPM_RAW, smallest_colour_block, square, _PPM::type, _PPM::width, and write_ppm().

Referenced by main().

00196                                                                                                                                                  {
00197 
00198   int i, j, k, last_k, k1, m, n, r, x, y;
00199   byte colour;
00200   int scale, block_size, num_blocks, old_num_blocks;
00201   int max_count, mode_index;
00202   int b1, b2, b3, b4;
00203 #ifdef GENERATE_BLOCK_IMAGES
00204   PPM *out_image, *out_image_hsv, *out_image_rgb;
00205   enum ppm_error the_error;
00206   FILE *outfile;
00207   char out_fname[256];
00208 #endif
00209 
00210 #ifdef GENERATE_BLOCK_IMAGES
00211     /* make space for an HSV image of the same size as that read */
00212     out_image = new_ppm();
00213     out_image->type = PGM_RAW;
00214     out_image->width = im->width;
00215     out_image->height = im->height;
00216     out_image->max_col_comp = im->max_col_comp;
00217     out_image->bytes_per_pixel = 1;
00218     out_image->pixel = (byte *)malloc(out_image->width*out_image->height*sizeof(byte));
00219 #endif
00220 
00221   /* first extract the lowest level blocks, directly from the pixels of
00222   the PGM image */
00223   scale = 0;
00224   block_size = smallest_colour_block;
00225   num_blocks = square(image_size/block_size);
00226   k = last_k = 0;
00227   for (y = 0; y < im->height; y += block_size) {
00228   for (x = 0; x < im->width; x += block_size) {
00229     for (n = 0; n < colmap_size; n++) {
00230       col_counts[k][n] = 0; 
00231     }
00232     for (i = 0; (i < block_size) && (y+i < im->height); i++) {
00233       for (j = 0; (j < block_size) && (x+j < im->width); j++) {
00234         colour = im->pixel[(y + j)*im->width + (x + i)];
00235         col_counts[k][colour]++;
00236       }
00237     }
00238 
00239     /* find the mode */
00240     max_count = mode_index = 0;
00241     for (n = 0; n < colmap_size; n++) {
00242       if (col_counts[k][n] > max_count) {
00243         max_count = col_counts[k][n];
00244         mode_index = n;
00245       }
00246     }
00247     block_mode[k] = mode_index;
00248     k++;
00249   }
00250   }
00251 
00252 #ifdef GENERATE_BLOCK_IMAGES
00253   /* generate an image with this */ 
00254   k1 = 0;
00255   for (y = 0; y < im->height; y += block_size) {
00256   for (x = 0; x < im->width; x += block_size) {
00257     for (i = 0; i < block_size; i++) {
00258     for (j = 0; j < block_size; j++) {
00259       out_image->pixel[(y + j)*im->width + (x + i)] = block_mode[k1];
00260     }
00261     }
00262     k1++;
00263   }
00264   }
00265   /* convert from the colour map to an HSV image */
00266   if ((the_error = colmap2rgb_ppm(out_image, colmap, colmap_size, &out_image_hsv)) != PPM_OK) {
00267     ppm_handle_error(the_error);
00268     exit(1);
00269   }
00270   /* convert to RGB */
00271   if ((the_error = hsv2rgb_ppm(out_image_hsv, &out_image_rgb)) != PPM_OK) {
00272     ppm_handle_error(the_error);
00273     exit(1);
00274   }
00275   /* write it */
00276   sprintf(out_fname, "blocks_%dx%d.ppm", block_size, block_size);
00277   outfile = fopen(out_fname, "wb");
00278   if ((the_error = write_ppm(outfile, out_image_rgb, PPM_RAW)) != PPM_OK) {
00279     ppm_handle_error(the_error);
00280     exit(1);
00281   }
00282   fclose(outfile);
00283   destroy_ppm(&out_image_rgb);
00284   destroy_ppm(&out_image_hsv);
00285 #endif
00286 
00287 
00288   /* now do the other scales */
00289   for (scale = 1; scale < num_colour_scales; scale++) {
00290     block_size *= 2;
00291     num_blocks /= 4;
00292     r = (int)sqrt((double)num_blocks);
00293     for (i = 0; i < num_blocks; i++) {
00294       m = (i/r)*2*r; /* note: this first is *integer* division */
00295       b1 = last_k + 2*i + m;
00296       b2 = last_k + 2*i + m + 1;
00297       b3 = last_k + 2*i + m + 2*r;
00298       b4 = last_k + 2*i + m + 2*r + 1;
00299       max_count = mode_index = 0;
00300       for (n = 0; n < colmap_size; n++) {
00301         col_counts[k + i][n] = 
00302           col_counts[b1][n] + col_counts[b2][n] + 
00303           col_counts[b3][n] + col_counts[b4][n];
00304         if (col_counts[k + i][n] > max_count) {
00305           max_count = col_counts[k + i][n];
00306           mode_index = n;
00307         }
00308       }
00309       block_mode[k + i] = mode_index;
00310     }
00311 #ifdef GENERATE_BLOCK_IMAGES
00312     /* generate an image with this */ 
00313     for (y = 0; y < im->height; y += block_size) {
00314     for (x = 0; x < im->width; x += block_size) {
00315       for (i = 0; i < block_size; i++) {
00316       for (j = 0; j < block_size; j++) {
00317         out_image->pixel[(y + j)*im->width + (x + i)] = block_mode[k1];
00318       }
00319       }
00320       k1++;
00321     }
00322     }
00323     /* convert from the colour map to an HSV image */
00324     if ((the_error = colmap2rgb_ppm(out_image, colmap, colmap_size, &out_image_hsv)) != PPM_OK) {
00325       ppm_handle_error(the_error);
00326       exit(1);
00327     }
00328     /* convert to RGB */
00329     if ((the_error = hsv2rgb_ppm(out_image_hsv, &out_image_rgb)) != PPM_OK) {
00330       ppm_handle_error(the_error);
00331       exit(1);
00332     }
00333     /* write it */
00334     sprintf(out_fname, "blocks_%dx%d.ppm", block_size, block_size);
00335     outfile = fopen(out_fname, "wb");
00336     if ((the_error = write_ppm(outfile, out_image_rgb, PPM_RAW)) != PPM_OK) {
00337       ppm_handle_error(the_error);
00338       exit(1);
00339     }
00340     fclose(outfile);
00341     destroy_ppm(&out_image_rgb);
00342     destroy_ppm(&out_image_hsv);
00343 #endif
00344     last_k = k;
00345     k += num_blocks;
00346   }
00347 
00348   /* now finally consolidate all the colour counts to produce the
00349   histogram for the whole image */
00350   k -= num_blocks;
00351   for (n = 0; n < colmap_size; n++)
00352     col_histogram[n] = 
00353       col_counts[k][n] + col_counts[k + 1][n] + 
00354       col_counts[k + 2][n] + col_counts[k + 3][n];
00355 }

void init_feature_variables ( uint32_t  ,
uint32_t **  ,
uint32_t ***  ,
uint32_t ***   
)

Definition at line 105 of file extract_block_features.c.

References gabor_block_size, image_size, num_blocks_at_scale, num_colour_scales, num_gabor_ranges, num_gabor_scales, num_gabors_per_scale, and square.

Referenced by main().

00105                                                                                                                                         {
00106 
00107   uint32_t i, j, k=0;
00108   /* colour features */
00109   for (i = 0; i < num_colour_scales; i++) {
00110     for (j = 0; j < num_blocks_at_scale(i); j++) {
00111       col_counts[k++] = (uint32_t *)malloc(colmap_size*sizeof(uint32_t));
00112     }
00113   }
00114 
00115   /* Gabor features */
00116   for (i = 0; i < num_gabor_scales; i++) {
00117     block_gabor_class[i] = (uint32_t **)malloc(num_gabors_per_scale*sizeof(uint32_t *));
00118     gabor_histogram[i] = (uint32_t **)malloc(num_gabors_per_scale*sizeof(uint32_t *));
00119     for (j = 0; j < num_gabors_per_scale; j++) {
00120       block_gabor_class[i][j] = (uint32_t *)malloc(square(image_size/gabor_block_size)*sizeof(uint32_t));
00121       gabor_histogram[i][j] = (uint32_t *)calloc(num_gabor_ranges, sizeof(uint32_t));
00122     }
00123   }
00124 }

int main ( int  argc,
char *  argv[] 
)

Definition at line 38 of file extract_features.c.

References destroy_ppm(), extract_gabor_features(), extract_mode_features(), hsv_quantize_ppm(), init_feature_variables(), num_gabor_scales, num_total_colour_blocks, numGrey, numH, numS, numV, PGM_ASC, PGM_RAW, PPM_ASC, ppm_handle_error(), PPM_OK, PPM_RAW, read_magic_no(), read_ppm(), rgb2hsv_ppm(), and write_mode_features().

00038                                  {
00039 
00040   char *in_fname, *out_fname;
00041   char *point_pos;
00042   FILE *ppm_file;
00043   PPM *im_rgb, *im_hsv, *im_quant;
00044   uint32_t *colmap, colmap_size;
00045   enum file_types ppm_type;
00046   enum ppm_error the_error;
00047   uint32_t ** block_gabor_class[num_gabor_scales];
00048   uint32_t ** gabor_histogram[num_gabor_scales];
00049   /* the "mode" of each color block. */
00050   byte block_mode[num_total_colour_blocks];
00051   /* the colour count of each block. for quantizing the image */
00052   uint32_t * col_counts[num_total_colour_blocks];
00053   uint32_t * col_histogram;
00054  
00055   switch(argc) {
00056   case 2:
00057     in_fname = argv[1];
00058     break;
00059   default:
00060     fprintf(stderr, "Usage: %s ppm_file \n\n", argv[0]);
00061     exit(1);
00062     break;
00063   }
00064 
00065   if ((ppm_file = fopen (in_fname, "r")) == NULL) {
00066     fprintf(stderr, "Can't open file: %s", in_fname);
00067     exit(1);
00068   }
00069 
00070   /* now get the filename prefix */
00071   out_fname = (char *)malloc((strlen(in_fname) + 10)*sizeof(char));
00072   if ((point_pos = strchr(in_fname, '.')) == NULL) {
00073     fprintf(stderr, "File %s has no ""."" - can't generate features filename\n\n", in_fname);
00074     exit(1);
00075   }
00076   else {
00077     /* must find the *last* "." in the filename */
00078     point_pos = &in_fname[strlen(in_fname)];
00079     while (*point_pos != '.') {
00080       point_pos--;
00081     }
00082     strncpy(out_fname, in_fname, (int)(point_pos - in_fname));
00083     strcat(out_fname, ".fts");
00084   }
00085 #ifdef DEBUG
00086   fprintf(stderr, "Features will be written to file %s\n", out_fname);
00087 #endif
00088   
00089 
00090   /* read the rgb image from we are going to extract features */
00091   switch(ppm_type = read_magic_no(ppm_file)) {
00092   case PGM_ASC: case PPM_ASC: case PGM_RAW: case PPM_RAW:
00093     if ((the_error = read_ppm(ppm_file, &im_rgb, ppm_type)) != PPM_OK) {
00094       ppm_handle_error(the_error);
00095       exit(1);
00096     }
00097     break;
00098   default:
00099     fprintf(stderr, "Unrecognized file type.\n");
00100     exit(1);
00101     break;
00102   }
00103 
00104   /* convert it to hsv */
00105   if ((the_error = rgb2hsv_ppm(im_rgb, &im_hsv)) != PPM_OK) {
00106     ppm_handle_error(the_error);
00107     exit(1);
00108   }
00109 
00110   /* quantize the image */
00111   colmap_size = numH*numS*numV + numGrey;
00112   if ((the_error = hsv_quantize_ppm(im_hsv, &im_quant, &colmap, numH, numS, numV, numGrey)) != PPM_OK) {
00113     ppm_handle_error(the_error);
00114     exit(1);
00115   }
00116 
00117   /* FIXME: move this back into init_feature_variables. */
00118   col_histogram = (uint32_t *)malloc(colmap_size*sizeof(uint32_t));
00119 
00120   /* initialise the variables required for the feature extraction */
00121   init_feature_variables(colmap_size, col_counts, block_gabor_class, gabor_histogram);
00122 
00123   /* extract the features */
00124 
00125   extract_mode_features(im_quant, colmap, colmap_size, col_counts, block_mode, col_histogram);
00126 
00127   extract_gabor_features(im_hsv, block_gabor_class, gabor_histogram);
00128 
00129   /* write them to the file */
00130   if ((the_error = write_mode_features(out_fname, colmap_size, col_histogram, block_gabor_class, gabor_histogram, block_mode)) != PPM_OK) {
00131     ppm_handle_error(the_error);
00132     exit(1);
00133   }
00134   
00135   /* everything is OK */
00136   destroy_ppm(&im_hsv);
00137   destroy_ppm(&im_quant);
00138   free(colmap);
00139   exit(0);
00140 }

enum ppm_error write_mode_features ( char *  ,
uint32_t  ,
uint32_t *  ,
uint32_t ***  ,
uint32_t ***  ,
byte  
)

HACK: convert all this features to floats.

WARNING: we write here floats into an integer field of a structure

Why is this necessary? The original version rounds at many places So we cannot just set FREQ_MAX=1. (WM)

Definition at line 357 of file extract_block_features.c.

References FILE_CLOSE_ERROR, FILE_OPEN_ERROR, FILE_WRITE_ERROR, FREQ_MAX, _FEATURE_DATA::frequency, gabor_block_size, _FEATURE_DATA::id, image_size, num_gabor_ranges, num_gabor_scales, num_gabors_per_scale, num_total_colour_blocks, PPM_OK, and square.

Referenced by main().

00357                                                                                                                                                                                      {
00358 
00359   FILE *out_file = NULL;
00360   int feature_index;
00361   int block_features_offset;
00362   int scale, orientation, energy_class;
00363   int num_features;
00364   FEATURE_DATA *feature;
00365   int i;
00366 
00367   /***** count the features *****/
00368 
00369   /* we know that there will be a mode color for each block */
00370   num_features = num_total_colour_blocks;
00371 
00372   /* and there will be one for each non-zero histogram entry. Convert
00373   histogram entries to range [0, FREQ_MAX] while we're at it */
00374   for (i = 0; i < colmap_size; i++) {
00375     col_histogram[i] = (int)(rint(FREQ_MAX*(double)col_histogram[i]/(double)(square(image_size))));
00376     if (col_histogram[i] != 0)
00377       num_features++;
00378   }
00379 
00380 #ifdef NO_FLAT_FEATURES
00381   /* count the block entries which are not of class zero (which indicates
00382   a filter response too low to write), and the non-zero gabor histogram
00383   entries */
00384   for (scale = 0; scale < num_gabor_scales; scale++) {
00385     for (orientation = 0; orientation < num_gabors_per_scale; orientation++) {
00386       /* blocks */
00387       for (i = 0; i < square((image_size/gabor_block_size)); i++) {
00388         if (block_gabor_class[scale][orientation][i] != 0)
00389           num_features++;
00390       }
00391 
00392       /* histogram */
00393       for (energy_class = 0; energy_class < num_gabor_ranges; energy_class++) {
00394         if (gabor_histogram[scale][orientation][energy_class] != 0)
00395           num_features++;
00396       }
00397     }
00398   }
00399 #else
00400   /* here we ARE storing features for filter responses in the lowest
00401    * energy band, so the number of block features is fixed (and v.
00402    * large!). We also count the non-zero gabor histogram entries */
00403 
00404   /* blocks */
00405   num_features += num_gabor_scales*num_gabors_per_scale*square((image_size/gabor_block_size));
00406 
00407   /* histogram */
00408   for (scale = 0; scale < num_gabor_scales; scale++) {
00409     for (orientation = 0; orientation < num_gabors_per_scale; orientation++) {
00410       for (energy_class = 0; energy_class < num_gabor_ranges; energy_class++) {
00411         if (gabor_histogram[scale][orientation][energy_class] != 0)
00412           num_features++;
00413       }
00414     }
00415   }
00416 #endif
00417 
00418 #ifdef DEBUG
00419   fprintf(stderr, "Image contains %d features.\n", num_features);
00420 #endif
00421 
00422   /* allocate space to store the features */
00423   feature = (FEATURE_DATA *)malloc(num_features*sizeof(FEATURE_DATA));
00424 
00425   /***** store the features in the array *****/
00426   feature_index = 0;
00427 
00428   /* colour block features */
00429   for (i = 0; i < num_total_colour_blocks; i++) {
00430     /* note that each block can have colmap_size values */
00431     feature[feature_index].id = i*colmap_size + (int)block_mode[i];
00432     feature[feature_index].frequency = FREQ_MAX; /* binary features */
00433     feature_index++;
00434   }
00435   block_features_offset = num_total_colour_blocks*colmap_size;
00436 
00437   /* colour histogram features */
00438   for (i = 0; i < colmap_size; i++) {
00439     if (col_histogram[i] != 0) {
00440       feature[feature_index].id = block_features_offset + i;
00441       feature[feature_index].frequency = (freq_type)col_histogram[i];
00442       feature_index++;
00443     }
00444   }
00445   block_features_offset += colmap_size;
00446 
00447   /* gabor block features */
00448   for (scale = 0; scale < num_gabor_scales; scale++) {
00449     for (orientation = 0; orientation < num_gabors_per_scale; orientation++) {
00450       /* blocks */
00451       for (i = 0; i < square((image_size/gabor_block_size)); i++) {
00452 #ifdef NO_FLAT_FEATURES
00453         if (block_gabor_class[scale][orientation][i] != 0) {
00454           feature[feature_index].id = block_features_offset + block_gabor_class[scale][orientation][i];
00455           feature[feature_index].frequency = FREQ_MAX;
00456           feature_index++;
00457         }
00458 #else
00459         feature[feature_index].id = block_features_offset + block_gabor_class[scale][orientation][i];
00460         feature[feature_index].frequency = FREQ_MAX;
00461         feature_index++;
00462 #endif
00463         block_features_offset += num_gabor_ranges;
00464       }
00465     }
00466   }
00467 
00468   /* gabor histogram features */
00469   for (scale = 0; scale < num_gabor_scales; scale++) {
00470     for (orientation = 0; orientation < num_gabors_per_scale; orientation++) {
00471       for (energy_class = 0; energy_class < num_gabor_ranges; energy_class++) {
00472         if (gabor_histogram[scale][orientation][energy_class] != 0) {
00473           feature[feature_index].id = block_features_offset;
00474           feature[feature_index].frequency = (freq_type)rint(FREQ_MAX*(double)gabor_histogram[scale][orientation][energy_class]/(double)square((image_size/gabor_block_size)));
00475           feature_index++;
00476         }
00477         block_features_offset++;
00478       }
00479     }
00480   }
00481 
00482 #ifdef DEBUG
00483   fprintf(stderr, "%d features found.\n", feature_index);
00484   fprintf(stderr, "block_features_offset = %d.\n", block_features_offset);
00485 #endif  
00486 
00487     
00488   /***** now write the file *****/
00489 
00490   /* open it */
00491   if ((out_file = fopen(out_fname, "wb")) == NULL) {
00492     fprintf(stderr, "Error opening file %s for writing.\n\n", out_fname);
00493     return(FILE_OPEN_ERROR);
00494   }
00495 
00496   /* write the number of features */
00497   if (fwrite(&num_features, sizeof(int), 1, out_file) != 1) {
00498     fprintf(stderr, "Error writing file %s.\n\n", out_fname);
00499     return(FILE_WRITE_ERROR);
00500   }
00501 
00511   for(i=0;
00512       i<num_features;
00513       i++){
00514     *((float*)&(feature[i].frequency))=((float)feature[i].frequency/(float)FREQ_MAX);//(WM HACK)
00515   };
00516 
00517   /* write the features, as a block */
00518   if (fwrite(feature, sizeof(FEATURE_DATA), num_features, out_file) != num_features) {
00519     fprintf(stderr, "Error writing file %s.\n\n", out_fname);
00520     return(FILE_WRITE_ERROR);
00521   }
00522 
00523   if (fclose(out_file) == EOF) {
00524     fprintf(stderr, "Error closing file %s.\n\n", out_fname);
00525     return(FILE_CLOSE_ERROR);
00526   }
00527 
00528   /* everything is OK if we got this far */
00529   return(PPM_OK);
00530 }


Generated on Tue Jan 6 00:30:51 2009 for Gift by  doxygen 1.5.6