Luiz Eduardo Simões Luiz Eduardo Simões - 2 months ago 6
C Question

Reading binary PGM on C

I'm making a library for reading PGM files and I got stuck with this problem.

My code can't read binary PGM images correctly, it looks like it reads the wrong values, thus generating an image with only "noise"

The code is really simple:

void OpenPGM(PGMImage* pgm, const char* file){
FILE *pgmfile = fopen (file, "rb");

fscanf (pgmfile, "%s", pgm->magicNumber);
fscanf (pgmfile, "%d %d", &(pgm->width),&(pgm->height));
fscanf (pgmfile, "%d", &(pgm->maxValue));

pgm->data = malloc(pgm->height * sizeof(unsigned char*));

if (pgm->magicNumber[1] == '2')
{
for (int i = 0; i < pgm->height; ++i)
{
pgm->data[i] = (unsigned char*)malloc(pgm->width * sizeof(unsigned char*));
for (int j = 0; j < pgm->width; ++j)
fscanf (pgmfile, "%d", &pgm->data[i][j]);
}
} else {
fgetc(pgmfile);// this should eat the last \n
for (int i = 0; i < pgm->height; ++i)
{
pgm->data[i] = (unsigned char*)malloc(pgm->width * sizeof(unsigned char*));
fread(pgm->data[i],sizeof(unsigned char*),pgm->width,pgmfile);//reading line by line
}
}
}


and the
PGMImage
looks like this

typedef struct PGMImage {
char magicNumber[2];
unsigned char** data;
unsigned int width;
unsigned int height;
unsigned int maxValue;
} PGMImage;


What am I doing wrong?

Answer

There is a potential issue as you read the image:

pgm->data[i] = (unsigned char*)malloc(pgm->width * sizeof(unsigned char*));
fread(pgm->data[i],sizeof(unsigned char*),pgm->width,pgmfile);//reading line by line

should be:

pgm->data[i] = malloc(pgm->width * sizeof(unsigned char));
if(pgm->data[i]==NULL){fprintf(stderr,"malloc failed\n");exit(1);}
fread(pgm->data[i],sizeof(unsigned char),pgm->width,pgmfile);//reading line by line

Indeed, unsigned char* is a pointer to an unsigned char and sizeof(unsigned char*) will be the size of a pointer (likely 8 bytes). Hence, the the image is read, 8 rows get read each time you read a line.

Comments