/* imgtoppm.c - read an Img-whatnot file and produce a portable pixmap ** ** Based on a simple conversion program posted to comp.graphics by Ed Falk. ** ** Copyright (C) 1989 by Jef Poskanzer. ** ** Permission to use, copy, modify, and distribute this software and its ** documentation for any purpose and without fee is hereby granted, provided ** that the above copyright notice appear in all copies and that both that ** copyright notice and this permission notice appear in supporting ** documentation. This software is provided "as is" without express or ** implied warranty. */ #include #include #include #include "nstring.h" #include "ppm.h" int main(int argc, const char ** argv) { FILE * ifP; pixel * pixelrow; pixel colormap[256]; unsigned int cols; unsigned int rows; pixval maxval; unsigned int cmaplen; bool gotAt, gotCm, gotPd; unsigned char buf[4096]; pm_proginit(&argc, argv); if (argc-1 >= 1) ifP = pm_openr(argv[1]); else ifP = stdin; if (argc-1 > 1) pm_error("Too many arguments (%u). " "The only possible argument is the input file name", argc-1); /* Get signature. */ fread(buf, 8, 1, ifP); buf[8] = '\0'; /* Get entries. */ gotAt = false; /* initial value */ gotCm = false; /* initial value */ gotPd = false; /* initial value */ while (fread( buf, 2, 1, ifP) == 1) { if (strneq((char*) buf, "AT", 2)) { unsigned int len; if (fread(buf, 8, 1, ifP) != 1) pm_error("bad attributes header"); buf[8] = '\0'; len = atoi((char*) buf); if (fread(buf, len, 1, ifP) != 1) pm_error("bad attributes buf"); buf[len] = '\0'; sscanf((char*) buf, "%4u%4u%4u", &cols, &rows, &cmaplen); if (cols > UINT_MAX/rows) pm_message("height (%u) and width (%u) in header are " "uncomputably large", rows, cols); if (cmaplen > UINT_MAX/3) pm_message("colormap length (%u) in header is " "uncomputably large", cmaplen); maxval = 255; gotAt = true; } else if (strneq((char*) buf, "CM", 2)) { unsigned int i; unsigned int len; if (!gotAt) pm_error("missing attributes header"); if (fread(buf, 8, 1, ifP) != 1) pm_error("bad colormap header"); buf[8] = '\0'; len = atoi((char*) buf); if (fread(buf, len, 1, ifP) != 1) pm_error("bad colormap buf"); if (len != cmaplen * 3) { pm_message( "cmaplen (%u) and colormap buf length (%u) do not match", cmaplen, len); if (len > cmaplen * 3) len = cmaplen * 3; else cmaplen = len / 3; } for (i = 0; i < len; i += 3) PPM_ASSIGN(colormap[i / 3], buf[i], buf[i + 1], buf[i + 2]); gotCm = true; } else if (strneq((char*) buf, "PD", 2)) { unsigned int len; unsigned int row; if (fread(buf, 8, 1, ifP) != 1) pm_error("bad pixel data header"); buf[8] = '\0'; len = atoi((char*) buf); if (len != cols * rows) pm_message( "pixel data length (%u) does not match image size (%u)", len, cols * rows); ppm_writeppminit(stdout, cols, rows, maxval, 0); pixelrow = ppm_allocrow(cols); for (row = 0; row < rows; ++row) { unsigned int col; if (fread(buf, 1, cols, ifP) != cols) pm_error("EOF / read error"); for (col = 0; col < cols; ++col) { if (gotCm) pixelrow[col] = colormap[buf[col]]; else PPM_ASSIGN(pixelrow[col], buf[col], buf[col], buf[col]); } ppm_writeppmrow(stdout, pixelrow, cols, maxval, 0); } gotPd = true; } } if (!gotPd) pm_error("missing pixel data header"); pm_close(ifP); /* If the program failed, it previously aborted with nonzero completion code, via various function calls. */ return 0; }