Howdy!
Last semester at school was rather tough for me. I had many classes and my junior project, and plus I had a lot of stress because I had no chance to fail in any class. Lucky that stress drives me through better motivation, I was successful in all of my classes and my junior project :)
Here in this post, I’d like to share a part of one of my Image Processing homeworks. It’s just two functions which read and write PGM files, so it’s no big deal. But some of my friends in class asked me if they could use my so-called API (hehe, imagine an API consisting of 2 functions :P) for their homeworks, so I thought it might be useful.
First of all, I find it necessary to say a couple of words on PGM files. The PGM Format Specifification can be found here. As you can see here, there are a couple of PGM files, and these functions (because we were supposed to do it that way in the homework) read only the raw format “P5″.
So here it goes:
typedef struct _PGMData {
int row;
int col;
int max_gray;
int **matrix;
} PGMData;
int **allocate_dynamic_matrix(int row, int col)
{
int **ret_val;
int i;
ret_val = (int **)malloc(sizeof(int *) * row);
if (ret_val == NULL) {
perror("memory allocation failure");
exit(EXIT_FAILURE);
}
for (i = 0; i < row; ++i) {
ret_val[i] = (int *)malloc(sizeof(int) * col);
if (ret_val[i] == NULL) {
perror("memory allocation failure");
exit(EXIT_FAILURE);
}
}
return ret_val;
}
void deallocate_dynamic_matrix(int **matrix, int row)
{
int i;
for (i = 0; i < row; ++i)
free(matrix[i]);
free(matrix);
}
And here we have 2 macro definitions to be used:
#define HI(num) (((num) & 0x0000FF00) >> 8) #define LO(num) ((num) & 0x000000FF)
void SkipComments(FILE *fp)
{
int ch;
char line[100];
while ((ch = fgetc(fp)) != EOF && isspace(ch))
;
if (ch == '#') {
fgets(line, sizeof(line), fp);
SkipComments(fp);
} else
fseek(fp, -1, SEEK_CUR);
}
/*for reading:*/
PGMData* readPGM(const char *file_name, PGMData *data)
{
FILE *pgmFile;
char version[3];
int i, j;
int lo, hi;
pgmFile = fopen(file_name, "rb");
if (pgmFile == NULL) {
perror("cannot open file to read");
exit(EXIT_FAILURE);
}
fgets(version, sizeof(version), pgmFile);
if (strcmp(version, "P5")) {
fprintf(stderr, "Wrong file type!\n");
exit(EXIT_FAILURE);
}
SkipComments(pgmFile);
fscanf(pgmFile, "%d", &data->col);
SkipComments(pgmFile);
fscanf(pgmFile, "%d", &data->row);
SkipComments(pgmFile);
fscanf(pgmFile, "%d", &data->max_gray);
fgetc(pgmFile);
data->matrix = allocate_dynamic_matrix(data->row, data->col);
if (data->max_gray > 255)
for (i = 0; i < data->row; ++i)
for (j = 0; j < data->col; ++j) {
hi = fgetc(pgmFile);
lo = fgetc(pgmFile);
data->matrix[i][j] = (hi << 8) + lo;
}
else
for (i = 0; i < data->row; ++i)
for (j = 0; j < data->col; ++j) {
lo = fgetc(pgmFile);
data->matrix[i][j] = lo;
}
fclose(pgmFile);
return data;
}
/*and for writing*/
void writePGM(const char *filename, const PGMData *data)
{
FILE *pgmFile;
int i, j;
int hi, lo;
pgmFile = fopen(filename, "wb");
if (pgmFile == NULL) {
perror("cannot open file to write");
exit(EXIT_FAILURE);
}
fprintf(pgmFile, "P5 ");
fprintf(pgmFile, "%d %d ", data->col, data->row);
fprintf(pgmFile, "%d ", data->max_gray);
if (data->max_gray > 255) {
for (i = 0; i < data->row; ++i) {
for (j = 0; j < data->col; ++j) {
hi = HI(data->matrix[i][j]);
lo = LO(data->matrix[i][j]);
fputc(hi, pgmFile);
fputc(lo, pgmFile);
}
}
} else {
for (i = 0; i < data->row; ++i)
for (j = 0; j < data->col; ++j) {
lo = LO(data->matrix[i][j]);
fputc(lo, pgmFile);
}
}
fclose(pgmFile);
deallocate_dynamic_matrix(data->matrix, data->row);
}
Well, that’s all. I told you that it’s not a big deal, I just wanted to paste it somewhere.
Good luck,
Hayri Uğur KOLTUK
thanks man!
we have to implement an image compression algorithm, a simplified version of JPEG-LS.
thanks to your code we don’t need to deal with the i/o!
:)
if you’re interested, i’ll post a link to our code if we get something reasonable done.
thanks again!
thanx buddy
i was looking for a handy code to read and write a pgm image
i got it , thanx