------------------------------------------------- ppm.c ------------------------------------------------- /**************************************************************** * * ppm.c * * Read and write PPM files. Only works for "raw" format. * * AF970205 * ****************************************************************/ #include #include #include #include "ppm.h" /************************ private functions ****************************/ /* die gracelessly */ static void die(char *message) { fprintf(stderr, "ppm: %s\n", message); exit(1); } /* check a dimension (width or height) from the image file for reasonability */ static void checkDimension(int dim) { if (dim < 1 || dim > 4000) die("file contained unreasonable width or height"); } /* read a header: verify format and get width and height */ static void readPPMHeader(FILE *fp, int *width, int *height) { char ch; int maxval; if (fscanf(fp, "P%c\n", &ch) != 1 || ch != '6') die("file is not in ppm raw format; cannot read"); /* skip comments */ ch = getc(fp); while (ch == '#') { do { ch = getc(fp); } while (ch != '\n'); /* read to the end of the line */ ch = getc(fp); /* thanks, Elliot */ } if (!isdigit(ch)) die("cannot read header information from ppm file"); ungetc(ch, fp); /* put that digit back */ /* read the width, height, and maximum value for a pixel */ fscanf(fp, "%d%d%d\n", width, height, &maxval); if (maxval != 255) die("image is not true-color (24 bit); read failed"); checkDimension(*width); checkDimension(*height); } /************************ exported functions ****************************/ Image * ImageCreate(int width, int height) { Image *image = (Image *) malloc(sizeof(Image)); if (!image) die("cannot allocate memory for new image"); image->width = width; image->height = height; image->data = (u_char *) malloc(width * height * 3); if (!image->data) die("cannot allocate memory for new image"); return image; } Image * ImageRead(char *filename) { int width, height, num, size; u_char *p; Image *image = (Image *) malloc(sizeof(Image)); FILE *fp = fopen(filename, "r"); if (!image) die("cannot allocate memory for new image"); if (!fp) die("cannot open file for reading"); readPPMHeader(fp, &width, &height); size = width * height * 3; image->data = (u_char *) malloc(size); image->width = width; image->height = height; if (!image->data) die("cannot allocate memory for new image"); num = fread((void *) image->data, 1, (size_t) size, fp); if (num != size) die("cannot read image data from file"); fclose(fp); return image; } void ImageWrite(Image *image, char *filename) { int num; int size = image->width * image->height * 3; FILE *fp = fopen(filename, "w"); if (!fp) die("cannot open file for writing"); fprintf(fp, "P6\n%d %d\n%d\n", image->width, image->height, 255); num = fwrite((void *) image->data, 1, (size_t) size, fp); if (num != size) die("cannot write image data to file"); fclose(fp); } int ImageWidth(Image *image) { return image->width; } int ImageHeight(Image *image) { return image->height; } void ImageClear(Image *image, u_char red, u_char green, u_char blue) { int i; int pix = image->width * image->height; u_char *data = image->data; for (i = 0; i < pix; i++) { *data++ = red; *data++ = green; *data++ = blue; } } void ImageSetPixel(Image *image, int x, int y, int chan, u_char val) { int offset = (y * image->width + x) * 3 + chan; image->data[offset] = val; } u_char ImageGetPixel(Image *image, int x, int y, int chan) { int offset = (y * image->width + x) * 3 + chan; return image->data[offset]; } ------------------------------------------------- ppm.h ------------------------------------------------- /**************************************************************** * * ppm.h * * Read and write PPM files. Only works for "raw" format. * * AF970205 * ****************************************************************/ #ifndef PPM_H #define PPM_H #include typedef struct Image { int width; int height; u_char *data; } Image; Image *ImageCreate(int width, int height); Image *ImageRead(char *filename); void ImageWrite(Image *image, char *filename); int ImageWidth(Image *image); int ImageHeight(Image *image); void ImageClear(Image *image, u_char red, u_char green, u_char blue); void ImageSetPixel(Image *image, int x, int y, int chan, u_char val); u_char ImageGetPixel(Image *image, int x, int y, int chan); #endif /* PPM_H */ ------------------------------------------------- try.c ------------------------------------------------- #include #include "ppm.h" void main() { int i, xoff; Image *image1, *image2; image1 = ImageCreate(200,100); ImageClear(image1, 210,180,40); /* mustard color */ ImageWrite(image1, "try1.ppm"); printf("created try1.ppm\n"); image2 = ImageRead("try1.ppm"); /* put a blue-ish stripe in image */ for (i = 0; i < 100; i++) { for (xoff = 45; xoff < 55; xoff++) { ImageSetPixel(image2, i+xoff, i, 0, 20); /* red channel */ ImageSetPixel(image2, i+xoff, i, 1, 40); /* green */ ImageSetPixel(image2, i+xoff, i, 2, 250); /* blue */ } } ImageWrite(image2, "try2.ppm"); printf("created try2.ppm\n"); } ------------------------------------------------- Makefile ------------------------------------------------- # # make file for "try", a program which tests # "ppm" image code by reading and writing images. # try: try.o ppm.o cc -o try try.o ppm.o clean: rm -f try.o ppm.o try -------------------------------------------------