/* triple.c Very simple I/O routines for triple-res rgb-separated 24-bit color raw PPM file I/O February 1999 by H. Dietz */ #include #include typedef struct { int xdim, ydim; /* image dimensions */ int maxval; /* maximum value */ void *data; /* data */ int fd; /* file descriptor */ void *map; /* map map address */ int fsize; /* mapped file size */ } info_P6; extern info_P6 map_P6(register char *filename); extern void unmap_P6(info_P6 info); extern int write_P6(register char *filename, register char *comment, register int xdim, register int ydim, register int maxval, register unsigned char *data); main(register int argc, register char **argv) { register unsigned char *buf, *p, *q; register int i, j, k; /* Process command line... */ if (argc != 3) { fprintf(stderr, "Usage: %s input_ppm output_ppm\n", argv[0]); exit(1); } /* Do the I/O */ { info_P6 info; /* Read the input */ info = map_P6(argv[1]); if (info.fd < 0) { fprintf(stderr, "%s: could not map P6 PPM file %s\n", argv[0], argv[1]); exit(2); } buf = malloc(info.xdim * info.ydim * (3 * 3 * 3)); p = buf; for (i=0; i #include info_P6 map_P6(register char *filename) { /* The following is a fast and sloppy way to read a color raw PPM (P6) image file */ register int fd; register int fsize; register unsigned char *map; register unsigned char *p; info_P6 info; /* First, open the file... */ if ((fd = open(filename, O_RDONLY)) < 0) { info.xdim = 0; info.ydim = 0; info.maxval = 0; info.data = 0; info.fd = -1; info.map = 0; info.fsize = 0; return(info); } /* Read size and map the whole file... */ fsize = lseek(fd, ((off_t) 0), SEEK_END); map = ((unsigned char *) mmap(0, /* Put it anywhere */ fsize, /* Map the whole file */ PROT_READ, /* Read only */ MAP_SHARED, /* Not just for me */ fd, /* The file */ 0)); /* Right from the start */ if (((int) map) == -1) { info.xdim = 0; info.ydim = 0; info.maxval = 0; info.data = 0; info.fd = -2; info.map = 0; info.fsize = 0; return(info); } /* File should now be mapped; read magic value */ p = map; if (*(p++) != 'P') goto ppm_exit; if (*(p++) != '6') goto ppm_exit; #define Eat_Space \ while ((*p == ' ') || \ (*p == '\t') || \ (*p == '\n') || \ (*p == '\r') || \ (*p == '#')) { \ if (*p == '#') while (*(++p) != '\n') ; \ ++p; \ } Eat_Space; /* Eat white space and comments */ #define Get_Number(n) \ { \ register int charval = *p; \ \ if ((charval < '0') || (charval > '9')) goto ppm_exit; \ \ n = (charval - '0'); \ charval = *(++p); \ while ((charval >= '0') && (charval <= '9')) { \ n *= 10; \ n += (charval - '0'); \ charval = *(++p); \ } \ } Get_Number(info.xdim); /* Get image width */ Eat_Space; /* Eat white space and comments */ Get_Number(info.ydim); /* Get image width */ Eat_Space; /* Eat white space and comments */ Get_Number(info.maxval); /* Get image max value */ /* Should be 8-bit binary after one whitespace char... */ if (info.maxval > 255) { ppm_exit: close(fd); munmap(map, fsize); info.xdim = 0; info.ydim = 0; info.maxval = 0; info.data = 0; info.fd = -3; info.map = 0; info.fsize = 0; return(info); } if ((*p != ' ') && (*p != '\t') && (*p != '\n') && (*p != '\r')) goto ppm_exit; /* Here we are... next byte begins the 24-bit data */ info.data = (p + 1); info.fd = fd; info.map = map; info.fsize = fsize; return(info); } #undef Eat_Space #undef Get_Number void unmap_P6(info_P6 info) { if (info.fd >= 0) { close(info.fd); munmap(info.map, info.fsize); } } int write_P6(register char *filename, register char *comment, register int xdim, register int ydim, register int maxval, register unsigned char *data) { register int fd; register int len; char buf[512]; /* First, open the file... */ fd = open(filename, (O_WRONLY | O_CREAT), 0666); if (fd < 0) { return(1); } /* Then write the header... */ sprintf(&(buf[0]), "P6\n#%s\n%d %d\n%d\n", (comment ? comment : filename), xdim, ydim, maxval); len = strlen(&(buf[0])); if (write(fd, &(buf[0]), len) != len) { close(fd); return(2); } /* Then write the data... */ len = (xdim * ydim * 3); if (write(fd, data, len) != len) { close(fd); return(3); } /* All looks good */ close(fd); return(0); }