/******************************************************************************* * Program: imageio.c * Purpose: This souce code file contains functions for dynamically allocating * and freeing 8-bit (unsigned char) images. It also contains functions for * reading and writing images to files in raw PGM format. This code was written * to be used as a teaching resource. * Name: Michael Heath, University of South Florida * Date: 1/7/2000 *******************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "imageio.h" /******************************************************************************* * Function: allocate_image * Purpose: This function allocates an image. The image is an array of pointers * to arrays. The array of pointers will have a length of the number of rows, * and each of these pointers will point to a separate one dimensional array * whose length is the number of columns in the image. This scheme was used * because it allows the image to be accessed using the syntax image[r][c] * yet still allow the image to be any size. * Name: Michael Heath, University of South Florida * Date: 1/7/2000 *******************************************************************************/ unsigned char **allocate_image(int rows, int cols) { unsigned char **image=NULL; int r, br; /**************************************************************************** * Allocate an array of pointers of type (unsigned char *). The array is * allocated to have a length of the number of rows. ****************************************************************************/ if((image = (unsigned char **) calloc(rows, sizeof(unsigned char *)))==NULL){ fprintf(stderr, "Error allocating the array of pointers in allocate_image().\n"); return((unsigned char **)NULL); } /**************************************************************************** * For each row, allocate an array of type (unigned char). ****************************************************************************/ for(r=0;r<rows;r++){ if((image[r] = (unsigned char *) calloc(cols, sizeof(unsigned char)))==NULL){ fprintf(stderr, "Error allocating an array in allocate_image().\n"); for(br=0;br<r;br++) free(image[br]); free(image); return((unsigned char **)NULL); } } return(image); } /******************************************************************************* * Function: free_image * Purpose: This function frees the memort that was previously allocated to * store an image. * Name: Michael Heath, University of South Florida * Date: 1/7/2000 *******************************************************************************/ void free_image(unsigned char **image, int rows) { int r; /**************************************************************************** * Free each row of the image. ****************************************************************************/ for(r=0;r<rows;r++) free(image[r]); /**************************************************************************** * Free the array of pointers. ****************************************************************************/ free(image); } /****************************************************************************** * Function: read_pgm_image * Purpose: This function reads in an image in raw PGM format. Because the PGM * format includes the number of columns and the number of rows in the image, * these are read from the file. Memory to store the image is allocated in this * function. All comments in the header are discarded in the process of reading * the image. Upon failure, this function returns 0, upon sucess it returns 1. * Name: Michael Heath, University of South Florida * Date: 1/7/2000 ******************************************************************************/ int read_pgm_image(char *infilename, unsigned char ***image, int *rows, int *cols) { FILE *fp; int r; char buf[71]; /*************************************************************************** * Open the input image file for reading. If the file can not be opened for * reading return an error code of 0. ***************************************************************************/ if((fp = fopen(infilename, "r")) == NULL){ fprintf(stderr, "Error reading the file %s in read_pgm_image().\n", infilename); return(0); } /*************************************************************************** * Verify that the image is in PGM format, read in the number of columns * and rows in the image and scan past all of the header information. ***************************************************************************/ fgets(buf, 70, fp); if(strncmp(buf,"P5",2) != 0){ fprintf(stderr, "The file %s is not in PGM format in ", infilename); fprintf(stderr, "read_pgm_image().\n"); fclose(fp); return(0); } do{ fgets(buf, 70, fp); }while(buf[0] == '#'); /* skip all comment lines */ sscanf(buf, "%d %d", cols, rows); do{ fgets(buf, 70, fp); }while(buf[0] == '#'); /* skip all comment lines */ /*************************************************************************** * Allocate memory to store the image. ***************************************************************************/ if(((*image) = allocate_image(*rows, *cols)) == NULL) return(0); /*************************************************************************** * Read in the image from the file, one row at a time. ***************************************************************************/ for(r=0;r<(*rows);r++){ if((*cols) != fread((*image)[r], 1, (*cols), fp)){ fprintf(stderr, "Error reading the image data in read_pgm_image().\n"); fclose(fp); free_image((*image), *rows); return(0); } } fclose(fp); return(1); } /****************************************************************************** * Function: write_pgm_image * Purpose: This function writes an image in raw PGM format. A comment can be * written to the header if coment != NULL. If there is a comment, it can * be up to 70 characters long. * Name: Michael Heath, University of South Florida * Date: 1/7/2000 ******************************************************************************/ int write_pgm_image(char *outfilename, unsigned char **image, int rows, int cols, char *comment, int maxval) { FILE *fp; int r; /*************************************************************************** * Open the output image file for writing. ***************************************************************************/ if((fp = fopen(outfilename, "w")) == NULL){ fprintf(stderr, "Error writing the file %s in write_pgm_image().\n", outfilename); return(0); } /*************************************************************************** * Write the header information to the PGM file. ***************************************************************************/ fprintf(fp, "P5\n"); if(comment != NULL) if(strlen(comment) <= 70) fprintf(fp, "# %s\n", comment); fprintf(fp, "%d %d\n", cols, rows); fprintf(fp, "%d\n", maxval); /*************************************************************************** * Write the image data to the file. ***************************************************************************/ for(r=0;r<rows;r++){ if(cols != fwrite(image[r], 1, cols, fp)){ fprintf(stderr, "Error writing the image data in write_pgm_image().\n"); fclose(fp); return(0); } } fclose(fp); return(1); }