basicColorImage.c

To create a program that consists of one big file: Copy and paste all of the following code into a file called basicColorImage.c which will be #included at the top of the source file. The suggested answers to the puzzles show this style.

If you want to create a project (rather than one big source file), copy and paste sections of this file into two individual files of the project as indicated by the dotted lines. Add the two files to your project along with your source files. Include the header file image.h at the top of source files where appropriate.


/* - - - - - - - - - - colorImage.h - - - - - - - - - - - - - - */


#include <stdlib.h>
#include <stdio.h>

typedef struct
{
  unsigned char red, grn, blu;
} pixel;

typedef struct
{
  int nrows;
  int ncols;
  pixel *pixels;
} colorImage;

pixel *newColorImage( colorImage *img, int nrows, int ncols );
void  freeColorImage( colorImage *img );
void  setColorPixel ( colorImage  img, int  row, int col, pixel val );
pixel getColorPixel ( colorImage  img, int  row, int col );
void  writePPMimage ( colorImage  img, char *filename );
void  readPPMimage  ( colorImage *img, char *filename );


/* - - - - - - - - - - colorImageFunctions.c - - - - - - - - - - */

pixel *newColorImage( colorImage *img, int nrows, int ncols ) { img->nrows = nrows; img->ncols = ncols; img->pixels = (pixel *)malloc( nrows * ncols * sizeof( pixel) ); return img->pixels; } void freeColorImage( colorImage *img ) { img->nrows = 0; img->ncols = 0; free( img->pixels ); } void setColorPixel( colorImage img, int row, int col, pixel val ) { img.pixels[ img.ncols*row + col ] = val; } pixel getColorPixel( colorImage img, int row, int col ) { return img.pixels[ img.ncols*row + col ] ; } void writePPMimage( colorImage img, char *filename ) { int row, col; FILE *file; pixel pix; /* open the image file for writing */ if ( (file = fopen( filename, "wb") ) == NULL ) { printf("file %s could not be created\n", filename ); exit( EXIT_FAILURE ); } /* write out the PPM Header information */ fprintf( file, "P6\n"); fprintf( file, "# Created by writeColorImage\n"); fprintf( file, "%d %d %d\n", img.ncols, img.nrows, 255 ); /* write the pixel data */ /* Maybe sizeof( pixel ) != 3, so do this pixel by pixel */ for ( row=0; row<img.nrows; row++ ) for ( col=0; col<img.ncols; col++ ) { pix = img.pixels[ img.ncols*row + col ]; fputc( pix.red, file ); fputc( pix.grn, file ); fputc( pix.blu, file ); } /* close the file */ fclose( file ); } void readPPMimage( colorImage *img, char *filename ) { int row, col; FILE *file; char buffer[1024]; int nrows, ncols, ngray, red, grn, blu ; /* open the image file for reading binary */ if ( (file = fopen( filename, "rb") ) == NULL ) { printf("readPPMImage(): file %s could not be opened\n", filename ); exit( EXIT_FAILURE ); } /* read signature on first line */ if ( fscanf( file, "%s", buffer ) != 1 ) { printf("readPPMImage(): error in image header, no signature\n" ); exit( EXIT_FAILURE ); } if ( strncmp( buffer, "P6", 2 ) != 0 ) { printf("readPPMimage(): file %s is not a PPM file\n", filename ); printf("Signature: %s\n", buffer ); exit( EXIT_FAILURE ); } /* skip over comment lines */ int moreComments = 1, ch; while ( moreComments ) { /* skip over possible white space */ while ( (ch=fgetc(file)) && isspace(ch) ); if ( ch=='#' ) { /* comments are required to end with line-feed */ fgets( buffer, 1024, file ); } else { moreComments = 0; ungetc( ch, file ); } } /* get ncols, nrows, ngray and eat the required single white space */ int count = fscanf( file, "%d %d %d", &ncols, &nrows, &ngray ); if ( count != 3 ) { printf("readPPMimage(): error in image header\n" ); exit( EXIT_FAILURE ); } fgetc(file); if ( ngray != 255 ) { printf("readPPMimage(): file %s is %d, not 8 bits per color\n", filename, ngray ); exit( EXIT_FAILURE ); } /* construct an image structure of the appropriate size */ if ( !newColorImage( img, nrows, ncols ) ) { printf("readPPMimage(): newImage failed\n" ); exit( EXIT_FAILURE ); } /* read the pixel data: 3 bytes per disk pixel */ /* (not nec. same size as sizeof(pixel) */ for ( row=0; row<nrows; row++ ) for ( col=0; col<ncols; col++ ) { red = fgetc( file ); grn = fgetc( file ); blu = fgetc( file ); img->pixels[ ncols*row + col ].red = red; img->pixels[ ncols*row + col ].grn = grn; img->pixels[ ncols*row + col ].blu = blu; } /* close the file */ fclose( file ); }