/* -*- C -*- pgm-io.c -- provides functions fore reading and writing PGM files. $Id$ */ #include /* PGMs can written in ascii or binary mode */ typedef enum {ascii, binary} mode_t; /** * @memo Reads a PGM file into an array of integers * * @doc The function reads a PGM file into an array of integers. The * array is allocated at the heap and must be deleted somewhere * within the program. The method can read binary and ascii * PGM files. * * @param filename Name of the PGM input file * @param width The function returns the width of the image in * this field. * @param height The function returns the height of the image in * this field * @param maxval The function returns the maximum grayscale value * of the image in this field * * @return Pointer to an allocated buffer that contains the image * data, i.e. the grayscale value of each pixel. */ int *read_pgm(char *filename, int *width, int *height, int *maxval) { FILE *fd = fopen(filename, "r"); /* file descriptor of input file */ mode_t mode = ascii; /* correct value will be set when file is read */ int c = 0; /* holds most currently read pixel value */ int *buf = NULL; /* buffer for pixel values */ int size = 0; /* number of pixels in buffer; will be set when file is read */ int i = 0; /* guess what, a counter */ if (fd == NULL) { fprintf(stderr, "Can't open file \"%s\" for reading.", filename); return NULL; } /* check file type */ if ( fgetc(fd) != 'P' ) { fprintf(stderr, "File \"%s\" is not an PGM file.", filename); fclose(fd); return NULL; } switch(fgetc(fd)) { case '2': mode= ascii; break; case '5': mode= binary; break; default: fprintf(stderr, "File \"%s\" is not an PGM file.", filename); fclose(fd); return NULL; } /* read comments */ do while ( (c= fgetc(fd)) != '\n') ; while ( (c= fgetc(fd)) == '#' ); ungetc(c, fd); /* read picture width, height and maxval */ fscanf(fd, "%d%d%d", width, height, maxval); /* allocate memory */ size= (*width) * (*height); buf= (int *) malloc( size * sizeof(int) ); /* read from file to buffer */ switch(mode) { case binary: for (i= 0; i < size; i++) buf[i]= fgetc(fd); break; case ascii: for (i= 0; i < size; i++) fscanf(fd, "%d", &buf[i]); } fclose(fd); return buf; } /** * @memo Writes an array of integers as a PGM file * * @doc The function writes an array of integers as a PGM file. The * function can write binary as well as ascii versions. * * @param filename Name of the PGM output file * @param mode Decides if file is written in binary or ascii * format. * @param buf points to the field of pixel values (grayscale values). * @param width Width of the image. * @param height Height of the image. * @param maxval Maximum grayscale value of the pixels in the field. * * @return returns -1 if an error ocurred, otherwise returns 0. */ int write_pgm( char *filename, mode_t mode, int *buf, int width, int height, int maxval ) { FILE *fd = fopen(filename, "w"); int size = width*height; int i = 0; if (fd == NULL) { fprintf(stderr, "Can't open file \"%s\" for writing.", filename); return -1; } /* write file type */ switch(mode) { case ascii: fprintf(fd, "P2\n"); break; case binary: fprintf(fd, "P5\n"); break; default: fprintf( stderr, "Illegal mode %d. File %s is not written.", mode, filename ); fclose(fd); return -1; } /* write comment */ fprintf(fd, "# File written by write_pgm.\n"); /* write picture width, height and maxval */ fprintf(fd, "%d %d\n%d\n", width, height, maxval); /* write image data */ switch(mode) { case binary: for (i= 1; i <= size; i++) fputc(buf[i], fd); break; case ascii: for (i= 1; i <= size; i++) if ( (i % 10) == 0 ) fprintf(fd, "%d\n", buf[i]); else fprintf(fd, "%d\t", buf[i]); break; } fprintf(fd, "\n"); fclose(fd); return 0; } /** * @memo programm reads an PGM file and writes it as an ascii PGM file. */ int main(int argc, char *argv[]) { int width, height, maxval; int *image_data; int result= 0; if (argc < 3) { fprintf(stderr, "Not enough arguements.\n"); fprintf(stderr, "Synopsis: %s ", argv[0]); fprintf(stderr, "\n"); return -1; } image_data= read_pgm(argv[1], &width, &height, &maxval); if (image_data == NULL) return -1; result= write_pgm( argv[2], ascii, image_data, width, height, maxval ); free(image_data); image_data= NULL; return 0; }