0
votes

I am trying to read PGM Images using the following function:

typedef struct PGMImage{
    int w;
    int h;
    unsigned char* data;
}GrayImage;

    void ReadPGMImage(char* filename,GrayImage* image)
    {
        int width,height,size,binary,i,j;

        FILE  *fp = fopen(filename, "r");

        if(!fp){
           fprintf(stderr,"Unable to open file in 'r' mode");
           exit(errno);
        }

        readPNMHeader(fp, &width, &height,&binary);

        size = width * height;
        *image = CreateGrayImage(width,height);

        if (!(image->data)){
            fprintf(stderr,"Memory not allocated");
            exit(errno);
        }

        fread((void *)image->data, sizeof(unsigned char), (size_t) size, fp);

        fclose(fp);

        return;
    }

The image I am trying to read has these headers: P2 640 480 255

When I print out the values of certain pixels(rows:400-410,columns:300-310),'205' gets printed for all the pixels whereas the actual values as per Matlab are:

  >248  255  255  250  254  254  254  252  252  255
  >255  255  255  255  255  255  255  255  255  255
  >255  255  255  255  255  255  255  255  255  255
  >255  255  255  255  255  255  255  255  255  255
  >255  255  255  255  255  255  255  255  255  255
  >248  247  249  245  251  252  253  252  245  251
  >241  240  243  237  240  244  239  242  243  244
  >235  238  238  237  239  238  239  238  240  242
  >236  233  241  235  236  234  236  239  235  237
  >231  239  231  239  234  234  230  233  233  234

Similar code works when I read PPM images. Could someone tell me where I am going wrong?

EDIT: Final code that works:

void ReadPGMImage(char * fileName, GrayImage* image) {
    FILE * fp = NULL;
    char version[100];
    int levels = 0;
    unsigned int w = 0, h = 0;
    unsigned int i = 0;
    int pixdat = 0;



    if( fileName == NULL ) {
        fprintf(stderr,"Bad file name=%s\n", fileName );
        return;
    }

    fp = fopen(fileName,"rb");
    if( fp == NULL )    {
        fprintf(stderr,"Cannot open file = %s\n", fileName );
        return;
    }


    fscanf(fp,"%s",version);

    SkipComments(fp);
    fscanf(fp, "%d", &w);
    SkipComments(fp);
    fscanf(fp, "%d", &h);
    SkipComments(fp);
    fscanf(fp, "%d", &levels);

    CreateGrayImage(image,w,h);
    image->w = w;
    image->h = h;
    for(i=0;i<w*h;i++) {
        fscanf(fp, "%d", &pixdat);
        image->data[i] = pixdat;
    }

    fclose(fp);

    return;
}
2
I guess you should use fscanf() instead of fread() and have the function parse the numbers and convert to integers to read the image.MikeCAT

2 Answers

1
votes

PGM has a decimal representation of the data values, so use fscanf to read the values in:

int offset=0;
while(! feof(fp) ){
    fscanf(fp, "%hu", &value);
    image->data[offset++] = value;
}

The %hu gives you unsigned short values (i.e. 0..65535 value), since PGM values can be shorts as well as bytes. On this basis, when you allocate the memory for the data, make sure to use:

 x->data = (unsigned short*)malloc( width * height * sizeof(unsigned short))
0
votes

The code so far seems to be fine with one little exception.

I think the following code line is the cause of the problem

*image = CreateGrayImage(width,height);

Here you assign the pointer returned by CreateGrayImage() to *image which overwrites the content of the structure.

I assume you want to pass the pointer returned by CreateGrayImage() to the caller of CreateGrayImage(). In this case you need to change the function declaration of ReadPGMImage() to the following:

void ReadPGMImage(char* filename,GrayImage** image)

Then it should work as you expect.