/* Simple PPM library ---------------------------------------------------------- * Based on specification: http://netpbm.sourceforge.net/doc/ppm.html * -------------------------------------------------------------------------- */ #include "ppm.h" #include #include #include #include #include #define PPM_FLIP 1 #define PPM_LINE_MAX 4096 /* PPM write ---------------------------------------------------------------- */ int ppm_write(const char *fname, unsigned char *buffer, size_t width, size_t height) { FILE *fs = NULL; int result = 0; fs = fopen(fname, "w+"); if (!fs) goto pgm_write_cleanup; fprintf(fs, "P6\n"); /* Magic Number */ fprintf(fs, "# Simple PPM library\n"); /* Comment */ fprintf(fs, "%lu %lu\n", width, height); /* Image width, height */ fprintf(fs, "255\n"); /* Maximum color value */ /* Pixel values */ #if PPM_FLIP size_t r; for (r = 0; r < height; r++) fwrite(&buffer[width*(height - r - 1)*3], sizeof(unsigned char), width * 3, fs); #else fwrite(buffer, sizeof(unsigned char), width * height * 3, fs); #endif result = 1; pgm_write_cleanup: if (fs) fclose(fs); return result; } char * ppm_read_token(FILE *fs) { static char buffer[PPM_LINE_MAX] = ""; static char *front = buffer; static char *back = buffer; if (*back == 0) { if (!fgets(buffer, sizeof(char) * PPM_LINE_MAX, fs)) goto ppm_read_token_failure; buffer[strlen(buffer) - 1] = 0; front = buffer; back = buffer; } if (*front == '#') { *front = 0; return ppm_read_token(fs); } for (front = back; *front != 0 && isspace(*front); front++); for (back = front; *back != 0 && !isspace(*back); back++); if (*back != 0) *back++ = 0; return front; ppm_read_token_failure: return NULL; } int ppm_read(const char *fname, unsigned char **buffer, size_t *width, size_t *height) { FILE *fs = NULL; char *token = NULL; int max_value; fs = fopen(fname, "r"); if (!fs) { fprintf(stderr, "ppm_read: could not open file %s = %s\n", fname, strerror(errno)); goto ppm_read_cleanup; } token = ppm_read_token(fs); if (strcmp(token, "P6") != 0) { fprintf(stderr, "ppm_read: file %s has wrong magic number %s\n", fname, token); goto ppm_read_cleanup; } token = ppm_read_token(fs); if (!token) { fprintf(stderr, "ppm_read: could not read width\n"); goto ppm_read_cleanup; } *width = strtol(token, NULL, 10); token = ppm_read_token(fs); if (!token) { fprintf(stderr, "ppm_read: could not read height\n"); goto ppm_read_cleanup; } *height = strtol(token, NULL, 10); token = ppm_read_token(fs); if (!token) { fprintf(stderr, "ppm_read: could not read max_value\n"); goto ppm_read_cleanup; } max_value = strtol(token, NULL, 10); *buffer = (unsigned char *)malloc(sizeof(unsigned char) * (*width) * (*height) * 3); if (!*buffer) { fprintf(stderr, "ppm_read: could not allocate memory for image buffer = %s\n", strerror(errno)); goto ppm_read_cleanup; } #if PPM_FLIP size_t r; for (r = 0; r < *height; r++) { fread(&(*buffer)[(*width)*((*height) - r - 1)*3], sizeof(unsigned char), (*width) * 3, fs); } #else fread(*buffer, sizeof(unsigned char), (*width) * (*height) * 3, fs); #endif return 1; ppm_read_cleanup: if (fs) fclose(fs); return 0; } /* vim: set sts=4 sw=4 ts=8 ft=cpp: ----------------------------------------- */