summaryrefslogtreecommitdiff
path: root/Build/source/utils/sam2p/input-pnm.ci
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2006-07-09 22:44:40 +0000
committerKarl Berry <karl@freefriends.org>2006-07-09 22:44:40 +0000
commit6684474324a04b457fe7019684c42eb68c4fea4b (patch)
tree63f0520f448252eb06342d5e0ea8e700c4976136 /Build/source/utils/sam2p/input-pnm.ci
parentbb92d19047f4437f2d13091072ec63a5641dc43c (diff)
new graphics utility sam2p
git-svn-id: svn://tug.org/texlive/trunk@1792 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/utils/sam2p/input-pnm.ci')
-rw-r--r--Build/source/utils/sam2p/input-pnm.ci493
1 files changed, 493 insertions, 0 deletions
diff --git a/Build/source/utils/sam2p/input-pnm.ci b/Build/source/utils/sam2p/input-pnm.ci
new file mode 100644
index 00000000000..9598ba8c687
--- /dev/null
+++ b/Build/source/utils/sam2p/input-pnm.ci
@@ -0,0 +1,493 @@
+/* This code is ripped from Autotrace-0.29. Small modifications by pts. */
+
+/* input-pnm.ci:
+ * The pnm reading and writing code was written from scratch by Erik Nygren
+ * (nygren@mit.edu) based on the specifications in the man pages and
+ * does not contain any code from the netpbm or pbmplus distributions.
+ */
+
+#ifdef __GNUC__
+#pragma implementation
+#endif
+
+/* #include "types.h" */
+#include "at_bitmap.h"
+/* #include "input-pnm.h" */
+/* #include "message.h" */
+/* #include "xstd.h" */
+
+/* #include <math.h> -- ceil(); emulated */
+#include <stdlib.h> /* atoi(...) */
+
+/**** pts ****/
+/* #include <ctype.h> */
+#define isspace(c) ((c)=='\0' || (c)==' ' || ((unsigned char)((c)-011)<=(unsigned char)(015-011)))
+/* ^^^ not strictly POSIX C locale */
+#define isdigit(c) ((unsigned char)(c-'0')<=(unsigned char)('9'-'0'))
+
+#if 0
+# define FILEE FILE
+# define fread_FILEE(s,slen,f) fread(s, 1, slen, f)
+#else
+# define FILEE /*Filter::UngetFILED*/GenBuffer::Readable
+# define fread_FILEE(s,slen,f) f->vi_read(s, slen)
+#endif
+
+/* Declare local data types
+ */
+
+typedef struct _PNMScanner
+{
+ FILEE *fd; /* The file descriptor of the file being read */
+ char cur; /* The current character in the input stream */
+ int eof; /* Have we reached end of file? */
+} PNMScanner;
+
+typedef struct _PNMInfo
+{
+ unsigned int xres, yres; /* The size of the image */
+ int maxval; /* For ascii image files, the max value
+ * which we need to normalize to */
+ int np; /* Number of image planes (0 for pbm) */
+ int asciibody; /* 1 if ascii body, 0 if raw body */
+ /* Routine to use to load the pnm body */
+ void (* loader) (PNMScanner *, struct _PNMInfo *, unsigned char *);
+} PNMInfo;
+
+/* Contains the information needed to write out PNM rows */
+typedef struct _PNMRowInfo
+{
+ FILEE *fd; /* File descriptor */
+ char *rowbuf; /* Buffer for writing out rows */
+ int xres; /* X resolution */
+ int np; /* Number of planes */
+ unsigned char *red; /* Colormap red */
+ unsigned char *grn; /* Colormap green */
+ unsigned char *blu; /* Colormap blue */
+} PNMRowInfo;
+
+/* Save info */
+typedef struct
+{
+ int raw; /* raw or ascii */
+} PNMSaveVals;
+
+typedef struct
+{
+ int run; /* run */
+} PNMSaveInterface;
+
+#define BUFLEN 512 /* The input buffer size for data returned
+ * from the scanner. Note that lines
+ * aren't allowed to be over 256 characters
+ * by the spec anyways so this shouldn't
+ * be an issue. */
+
+#define SAVE_COMMENT_STRING "# CREATOR: The GIMP's PNM Filter Version 1.0\n"
+
+/* Declare some local functions.
+ */
+
+static void pnm_load_ascii (PNMScanner *scan,
+ PNMInfo *info,
+ unsigned char *pixel_rgn);
+static void pnm_load_raw (PNMScanner *scan,
+ PNMInfo *info,
+ unsigned char *pixel_rgn);
+static void pnm_load_rawpbm (PNMScanner *scan,
+ PNMInfo *info,
+ unsigned char *pixel_rgn);
+
+static void pnmscanner_destroy (PNMScanner *s);
+#if 0
+static void pnmscanner_createbuffer (PNMScanner *s,
+ unsigned int bufsize);
+static void pnmscanner_getchar (PNMScanner *s);
+static void pnmscanner_getsmalltoken (PNMScanner *s, unsigned char *buf);
+#endif
+static void pnmscanner_eatwhitespace (PNMScanner *s);
+static void pnmscanner_gettoken (PNMScanner *s,
+ unsigned char *buf,
+ unsigned int bufsize);
+static unsigned pnmscanner_getint(PNMScanner *s);
+
+static PNMScanner * pnmscanner_create (FILEE *fd);
+
+
+#define pnmscanner_eof(s) ((s)->eof)
+#define pnmscanner_fd(s) ((s)->fd)
+
+#if 0
+/* pnmscanner_getchar ---
+ * Reads a character from the input stream
+ */
+static void
+pnmscanner_getchar (PNMScanner *s)
+{
+ if (s->inbuf)
+ {
+ s->cur = s->inbuf[s->inbufpos++];
+ if (s->inbufpos >= s->inbufvalidsize)
+ {
+ if (s->inbufsize > s->inbufvalidsize)
+ s->eof = 1;
+ else
+ s->inbufvalidsize = fread(s->inbuf, 1, s->inbufsize, s->fd);
+ s->inbufpos = 0;
+ }
+ }
+ else
+ s->eof = !fread(&(s->cur), 1, 1, s->fd);
+}
+#endif
+
+#define pnmscanner_getchar(s) do { s->eof = !fread_FILEE(&(s->cur), 1, s->fd); } while(0)
+
+/* pnmscanner_eatwhitespace ---
+ * Eats up whitespace from the input and returns when done or eof.
+ * Also deals with comments.
+ */
+static inline void pnmscanner_eatwhitespace(PNMScanner *s) { /**** pts ****/
+ while (1) {
+ if (s->cur=='#') {
+ do pnmscanner_getchar(s); while (s->cur!='\n');
+ } else if (!isspace(s->cur)) {
+ break;
+ }
+ pnmscanner_getchar(s);
+ }
+}
+
+
+static struct struct_pnm_types
+{
+ char name;
+ int np;
+ int asciibody;
+ int maxval;
+ void (* loader) (PNMScanner *, struct _PNMInfo *, unsigned char *pixel_rgn);
+} pnm_types[] =
+{
+ { '1', 0, 1, 1, pnm_load_ascii }, /* ASCII PBM */
+ { '2', 1, 1, 255, pnm_load_ascii }, /* ASCII PGM */
+ { '3', 3, 1, 255, pnm_load_ascii }, /* ASCII PPM */
+ { '4', 0, 0, 1, pnm_load_rawpbm }, /* RAW PBM */
+ { '5', 1, 0, 255, pnm_load_raw }, /* RAW PGM */
+ { '6', 3, 0, 255, pnm_load_raw }, /* RAW PPM */
+ { 0 , 0, 0, 0, NULL}
+};
+
+#if PTS_SAM2P
+bitmap_type pnm_load_image (FILEE* filename)
+#else
+bitmap_type pnm_load_image (at_string filename)
+#endif
+{
+ char buf[BUFLEN]; /* buffer for random things like scanning */
+ PNMInfo *pnminfo;
+ PNMScanner * volatile scan;
+ int ctr;
+ FILEE* fd;
+ bitmap_type bitmap;
+
+ #if PTS_SAM2P /**** pts ****/
+ fd=filename;
+ #else
+ /* open the file */
+ fd = xfopen (filename, "rb");
+ if (fd == NULL)
+ {
+ FATAL("PNM: can't open file\n");
+ BITMAP_BITS (bitmap) = NULL;
+ BITMAP_WIDTH (bitmap) = 0;
+ BITMAP_HEIGHT (bitmap) = 0;
+ BITMAP_PLANES (bitmap) = 0;
+ return (bitmap);
+ }
+ #endif
+
+
+ /* allocate the necessary structures */
+ /* pnminfo = (PNMInfo *) malloc (sizeof (PNMInfo)); */
+ XMALLOCTU(pnminfo, PNMInfo);
+
+ scan = NULL;
+ /* set error handling */
+
+ scan = pnmscanner_create(fd);
+
+ /* Get magic number */
+ pnmscanner_gettoken (scan, (unsigned char *)buf, BUFLEN);
+ if (pnmscanner_eof(scan))
+ FATALP ("PNM: premature end of file");
+ if (buf[0] != 'P' || buf[2])
+ FATALP ("PNM: is not a valid file");
+
+ /* Look up magic number to see what type of PNM this is */
+ for (ctr=0; pnm_types[ctr].name; ctr++)
+ if (buf[1] == pnm_types[ctr].name)
+ {
+ pnminfo->np = pnm_types[ctr].np;
+ pnminfo->asciibody = pnm_types[ctr].asciibody;
+ pnminfo->maxval = pnm_types[ctr].maxval;
+ pnminfo->loader = pnm_types[ctr].loader;
+ }
+ if (!pnminfo->loader)
+ FATALP ("PNM: file not in a supported format");
+
+ pnmscanner_gettoken(scan, (unsigned char *)buf, BUFLEN);
+ if (pnmscanner_eof(scan))
+ FATALP ("PNM: premature end of file");
+ pnminfo->xres = isdigit(*buf)?atoi(buf):0;
+ if (pnminfo->xres<=0)
+ FATALP ("PNM: invalid xres while loading");
+
+ pnmscanner_gettoken(scan, (unsigned char *)buf, BUFLEN);
+ if (pnmscanner_eof(scan))
+ FATALP ("PNM: premature end of file");
+ pnminfo->yres = isdigit(*buf)?atoi(buf):0;
+ if (pnminfo->yres<=0)
+ FATALP ("PNM: invalid yres while loading");
+
+ if (pnminfo->np != 0) /* pbm's don't have a maxval field */
+ {
+ pnmscanner_gettoken(scan, (unsigned char *)buf, BUFLEN);
+ if (pnmscanner_eof(scan))
+ FATALP ("PNM: premature end of file");
+
+ pnminfo->maxval = isdigit(*buf)?atoi(buf):0;
+ if ((pnminfo->maxval<=0)
+ || (pnminfo->maxval>255 && !pnminfo->asciibody))
+ FATALP ("PNM: invalid maxval while loading");
+ }
+
+ BITMAP_WIDTH (bitmap) = (unsigned short) pnminfo->xres;
+ BITMAP_HEIGHT (bitmap) = (unsigned short) pnminfo->yres;
+
+ BITMAP_PLANES (bitmap) = (pnminfo->np)?(pnminfo->np):1;
+ /* BITMAP_BITS (bitmap) = (unsigned char *) malloc (pnminfo->yres * pnminfo->xres * BITMAP_PLANES (bitmap)); */
+ XMALLOCT(BITMAP_BITS (bitmap), unsigned char *, pnminfo->yres * pnminfo->xres * BITMAP_PLANES (bitmap));
+ pnminfo->loader (scan, pnminfo, BITMAP_BITS (bitmap));
+ /* vvv Dat: We detect truncation late truncated files will just have garbage :-( */
+ if (pnmscanner_eof(scan))
+ FATALP ("PNM: truncated image data");
+
+ /* Destroy the scanner */
+ pnmscanner_destroy (scan);
+
+ /* free the structures */
+ /* free (pnminfo); */
+ XFREE(pnminfo);
+
+ /* close the file */
+ /* xfclose (fd, filename); */
+
+ return (bitmap);
+}
+
+static void
+pnm_load_ascii (PNMScanner *scan,
+ PNMInfo *info,
+ unsigned char *data)
+{
+ register unsigned char *d, *dend;
+ unsigned u, s;
+ #if 0 /**** pts ****/
+ /* Buffer reads to increase performance */
+ /* !! convert(1) is faster -- maybe buffering helps? */
+ pnmscanner_createbuffer(scan, 4096);
+ #endif
+ d = data;
+ if (info->np==0) { /* PBM */
+ dend=d+info->xres*info->yres;
+ while (d!=dend) {
+ /* pnmscanner_getsmalltoken(scan, (unsigned char *)buf); */
+ pnmscanner_eatwhitespace(scan);
+ *d++=-(scan->cur=='0');
+ pnmscanner_getchar(scan);
+ }
+ } else { /* PGM or PPM */ /**** pts ****/
+ dend=d+info->xres*info->yres*info->np;
+ switch (s=info->maxval) {
+ case 255:
+ while (d!=dend) {
+ *d++=pnmscanner_getint(scan); /* Dat: removed isdigit() */
+ }
+ break;
+ case 15:
+ while (d!=dend) {
+ *d++ = pnmscanner_getint(scan)*17;
+ }
+ break;
+ case 3:
+ while (d!=dend) {
+ *d++ = pnmscanner_getint(scan)*85;
+ }
+ break;
+ case 0: /* avoid division by 0 */
+ case 1:
+ while (d!=dend) {
+ *d++ = -(0==pnmscanner_getint(scan)); /* (*buf=='0')?0xff:0x00; */
+ }
+ default:
+ while (d!=dend) {
+ u=pnmscanner_getint(scan);
+ *d++ = (0UL+u*255UL+(s>>1))/s; /* always <= 255 */
+ }
+ }
+ }
+}
+
+static void
+pnm_load_raw (PNMScanner *scan,
+ PNMInfo *info,
+ unsigned char *data)
+{
+ unsigned char *d, *dend;
+ unsigned s=info->maxval;
+ slen_t delta, scanlines;
+ FILEE *fd=pnmscanner_fd(scan);
+
+ scanlines = info->yres;
+ d = data;
+ delta=info->xres * info->np;
+ dend=d+delta*scanlines;
+ while (d!=dend) {
+ if (info->xres*info->np != fread_FILEE((char*)d, delta, fd)) return;
+ d+=delta;
+ }
+ d=data;
+ switch (s=info->maxval) { /**** pts ****/
+ case 1: case 0:
+ for (; d!=dend; d++) if (*d!=0) *d=255;
+ break;
+ case 3:
+ while (d!=dend) *d++*=85;
+ break;
+ case 15:
+ while (d!=dend) *d++*=17;
+ break;
+ case 255:
+ break;
+ default:
+ for (; d!=dend; d++) *d=(0UL+*d*255UL+(s>>1))/s; /* always <= 255 */
+ break;
+ }
+}
+
+static void
+pnm_load_rawpbm (PNMScanner *scan,
+ PNMInfo *info,
+ unsigned char *data)
+{
+ unsigned char *buf;
+ unsigned char curbyte;
+ unsigned char *d;
+ unsigned int x, i;
+ unsigned int start, end, scanlines;
+ FILEE *fd;
+ unsigned int rowlen, bufpos;
+
+ fd = pnmscanner_fd(scan);
+ /****pts****/ /* rowlen = (unsigned int)ceil((double)(info->xres)/8.0);*/
+ rowlen=(info->xres+7)>>3;
+ /* buf = (unsigned char *)malloc(rowlen*sizeof(unsigned char)); */
+ XMALLOCT(buf, unsigned char*, rowlen*sizeof(unsigned char));
+
+ start = 0;
+ end = info->yres;
+ scanlines = end - start;
+ d = data;
+
+ for (i = 0; i < scanlines; i++)
+ {
+ if (rowlen != fread_FILEE((char*)buf, rowlen, fd))
+ FATALP ("PNM: error reading file");
+ bufpos = 0;
+ curbyte = buf[0];
+
+ for (x = 0; x < info->xres; x++)
+ {
+ if ((x % 8) == 0) {
+ curbyte = buf[bufpos++];
+ /* // if (curbyte!=0) printf("%d <%u>\n", x, curbyte); */
+ }
+ /* // if (curbyte!=0) printf("[%u]\n", curbyte); */
+ d[x] = (curbyte&0x80) ? 0x00 : 0xff;
+ curbyte <<= 1;
+ }
+
+ d += info->xres;
+ }
+
+ XFREE(buf);
+}
+
+/**************** FILE SCANNER UTILITIES **************/
+
+/* pnmscanner_create ---
+ * Creates a new scanner based on a file descriptor. The
+ * look ahead buffer is one character initially.
+ */
+static PNMScanner *
+pnmscanner_create (FILEE *fd)
+{
+ PNMScanner *s;
+
+ XMALLOCTU (s, PNMScanner);
+ s->fd = fd;
+ s->eof = !fread_FILEE(&(s->cur), 1, s->fd);
+ return s;
+}
+
+/* pnmscanner_destroy ---
+ * Destroys a scanner and its resources. Doesn't close the fd.
+ */
+static void
+pnmscanner_destroy (PNMScanner *s)
+{
+ XFREE(s);
+}
+
+#if 0 /**** pts ****/
+/* pnmscanner_createbuffer ---
+ * Creates a buffer so we can do buffered reads.
+ */
+static void
+pnmscanner_createbuffer (PNMScanner *s,
+ unsigned int bufsize)
+{
+ /* s->inbuf = (char *)malloc(sizeof(char)*bufsize); */
+ XMALLOCT(s->inbuf, char*, sizeof(char)*bufsize);
+ s->inbufsize = bufsize;
+ s->inbufpos = 0;
+ s->inbufvalidsize = fread(s->inbuf, 1, bufsize, s->fd);
+}
+#endif
+
+/* pnmscanner_gettoken ---
+ * Gets the next token, eating any leading whitespace.
+ */
+static void pnmscanner_gettoken (PNMScanner *s,
+ unsigned char *buf,
+ unsigned int bufsize)
+{
+ unsigned char *bufend=buf+bufsize-1;
+ pnmscanner_eatwhitespace(s);
+ while (!pnmscanner_eof(s) && !isspace(s->cur) && s->cur!='#') {
+ if (buf!=bufend) *buf++=s->cur;
+ pnmscanner_getchar(s);
+ }
+ *buf='\0';
+}
+
+static unsigned pnmscanner_getint(PNMScanner *s) {
+ unsigned ret=0;
+ pnmscanner_eatwhitespace(s);
+ while (!pnmscanner_eof(s)) {
+ if (isdigit(s->cur)) ret=10*ret+s->cur-'0';
+ else if (isspace(s->cur) || s->cur=='#') break;
+ pnmscanner_getchar(s);
+ }
+ return ret;
+}