about summary refs log tree commit diff
path: root/converter/ppm/ppmtopict.c
diff options
context:
space:
mode:
Diffstat (limited to 'converter/ppm/ppmtopict.c')
-rw-r--r--converter/ppm/ppmtopict.c481
1 files changed, 481 insertions, 0 deletions
diff --git a/converter/ppm/ppmtopict.c b/converter/ppm/ppmtopict.c
new file mode 100644
index 00000000..e2428fb6
--- /dev/null
+++ b/converter/ppm/ppmtopict.c
@@ -0,0 +1,481 @@
+/*
+** ppmtopict.c - read a portable pixmap and produce a Macintosh PICT2 file.
+**
+** Copyright (C) 1990 by Ken Yap <ken@cs.rochester.edu>.
+**
+** 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 "ppm.h"
+
+#define HEADER_SIZE		512
+
+#define	RUN_THRESH		3
+#define	MAX_RUN			128		/* 0xff = 2, 0xfe = 3, etc */
+#define	MAX_COUNT		128		/* 0x00 = 1, 0x01 = 2, etc */
+
+/* Opcodes */
+#define PICT_NOP		0x00
+#define PICT_clipRgn		0x01
+#define PICT_bkPat		0x02
+#define PICT_txFont		0x03
+#define PICT_txFace		0x04
+#define PICT_txMode		0x05
+#define PICT_spExtra		0x06
+#define PICT_pnSize		0x07
+#define PICT_pnMode		0x08
+#define PICT_pnPat		0x09
+#define PICT_thePat		0x0A
+#define PICT_ovSize		0x0B
+#define PICT_origin		0x0C
+#define PICT_txSize		0x0D
+#define PICT_fgColor		0x0E
+#define PICT_bkColor		0x0F
+#define PICT_txRatio		0x10
+#define PICT_picVersion		0x11
+#define	PICT_blPixPat		0x12
+#define	PICT_pnPixPat		0x13
+#define	PICT_fillPixPat		0x14
+#define	PICT_pnLocHFrac		0x15
+#define	PICT_chExtra		0x16
+#define	PICT_rgbFgCol		0x1A
+#define	PICT_rgbBkCol		0x1B
+#define	PICT_hiliteMode		0x1C
+#define	PICT_hiliteColor	0x1D
+#define	PICT_defHilite		0x1E
+#define	PICT_opColor		0x1F
+#define PICT_line		0x20
+#define PICT_line_from		0x21
+#define PICT_short_line		0x22
+#define PICT_short_line_from	0x23
+#define PICT_long_text		0x28
+#define PICT_DH_text		0x29
+#define PICT_DV_text		0x2A
+#define PICT_DHDV_text		0x2B
+#define PICT_frameRect		0x30
+#define PICT_paintRect		0x31
+#define PICT_eraseRect		0x32
+#define PICT_invertRect		0x33
+#define PICT_fillRect		0x34
+#define PICT_frameSameRect	0x38
+#define PICT_paintSameRect	0x39
+#define PICT_eraseSameRect	0x3A
+#define PICT_invertSameRect	0x3B
+#define PICT_fillSameRect	0x3C
+#define PICT_frameRRect		0x40
+#define PICT_paintRRect		0x41
+#define PICT_eraseRRect		0x42
+#define PICT_invertRRect	0x43
+#define PICT_fillRRect		0x44
+#define PICT_frameSameRRect	0x48
+#define PICT_paintSameRRect	0x49
+#define PICT_eraseSameRRect	0x4A
+#define PICT_invertSameRRect	0x4B
+#define PICT_fillSameRRect	0x4C
+#define PICT_frameOval		0x50
+#define PICT_paintOval		0x51
+#define PICT_eraseOval		0x52
+#define PICT_invertOval		0x53
+#define PICT_fillOval		0x54
+#define PICT_frameSameOval	0x58
+#define PICT_paintSameOval	0x59
+#define PICT_eraseSameOval	0x5A
+#define PICT_invertSameOval	0x5B
+#define PICT_fillSameOval	0x5C
+#define PICT_frameArc		0x60
+#define PICT_paintArc		0x61
+#define PICT_eraseArc		0x62
+#define PICT_invertArc		0x63
+#define PICT_fillArc		0x64
+#define PICT_frameSameArc	0x68
+#define PICT_paintSameArc	0x69
+#define PICT_eraseSameArc	0x6A
+#define PICT_invertSameArc	0x6B
+#define PICT_fillSameArc	0x6C
+#define PICT_framePoly		0x70
+#define PICT_paintPoly		0x71
+#define PICT_erasePoly		0x72
+#define PICT_invertPoly		0x73
+#define PICT_fillPoly		0x74
+#define PICT_frameSamePoly	0x78
+#define PICT_paintSamePoly	0x79
+#define PICT_eraseSamePoly	0x7A
+#define PICT_invertSamePoly	0x7B
+#define PICT_fillSamePoly	0x7C
+#define PICT_frameRgn		0x80
+#define PICT_paintRgn		0x81
+#define PICT_eraseRgn		0x82
+#define PICT_invertRgn		0x83
+#define PICT_fillRgn		0x84
+#define PICT_frameSameRgn	0x88
+#define PICT_paintSameRgn	0x89
+#define PICT_eraseSameRgn	0x8A
+#define PICT_invertSameRgn	0x8B
+#define PICT_fillSameRgn	0x8C
+#define PICT_BitsRect		0x90
+#define PICT_BitsRgn		0x91
+#define PICT_PackBitsRect	0x98
+#define PICT_PackBitsRgn	0x99
+#define PICT_shortComment	0xA0
+#define PICT_longComment	0xA1
+#define PICT_EndOfPicture	0xFF
+#define	PICT_headerOp		0x0C00
+
+static void putFill ARGS(( FILE *fd, int n ));
+static void putShort ARGS(( FILE *fd, int i ));
+static void putLong ARGS(( FILE *fd, long i ));
+static void putFixed ARGS(( FILE *fd, int in, int frac ));
+static void putRect ARGS(( FILE *fd, int x1, int x2, int y1, int y2 ));
+static int putRow ARGS(( FILE *fd, int row, int cols, pixel *rowpixels, char *packed ));
+
+#define MAXCOLORS 256
+static colorhash_table cht;
+
+int
+main(argc, argv)
+int argc;
+char *argv[];
+{
+	FILE *ifp;
+	int argn, rows, cols, colors, i, row, oc;
+	register pixel **pixels;
+	char *packed;
+	pixval maxval;
+	long lmaxval, rval, gval, bval;
+	colorhist_vector chv;
+
+
+	ppm_init( &argc, argv );
+
+	argn = 1;
+	if (argn < argc)
+	{
+		ifp = pm_openr(argv[1]);
+		argn++;
+	}
+	else
+		ifp = stdin;
+	if (argn != argc)
+		pm_usage("[ppmfile]");
+
+	pixels = ppm_readppm(ifp, &cols, &rows, &maxval);
+	if (cols < 8)
+		pm_error("ppm input too narrow, must be >= 8 pixels wide" );
+	lmaxval = (long)maxval;
+	pm_close(ifp);
+
+	/* Figure out the colormap. */
+	pm_message("computing colormap..." );
+	chv = ppm_computecolorhist(pixels, cols, rows, MAXCOLORS, &colors);
+	if (chv == (colorhist_vector) 0)
+		pm_error("too many colors - try doing a 'pnmquant %d'", MAXCOLORS);
+	pm_message("%d colors found", colors );
+
+	/* Make a hash table for fast color lookup. */
+	cht = ppm_colorhisttocolorhash(chv, colors);
+
+	/* write the header */
+	putFill(stdout, HEADER_SIZE);
+
+	/* write picSize and picFrame */
+	putShort(stdout, 0);
+	putRect(stdout, 0, 0, rows, cols);
+
+	/* write version op and version */
+	putShort(stdout, PICT_picVersion);
+	putShort(stdout, 0x02FF);
+	putShort(stdout, PICT_headerOp);
+	putLong(stdout, -1L);
+	putFixed(stdout, 0, 0);
+	putFixed(stdout, 0, 0);
+	putFixed(stdout, cols, 0);
+	putFixed(stdout, rows, 0);
+	putFill(stdout, 4);
+
+	/* seems to be needed by many PICT2 programs */
+	putShort(stdout, PICT_clipRgn);
+	putShort(stdout, 10);
+	putRect(stdout, 0, 0, rows, cols);
+
+	/* write picture */
+	putShort(stdout, PICT_PackBitsRect);
+	putShort(stdout, cols | 0x8000);
+	putRect(stdout, 0, 0, rows, cols);
+	putShort(stdout, 0);	/* pmVersion */
+	putShort(stdout, 0);	/* packType */
+	putLong(stdout, 0L);	/* packSize */
+	putFixed(stdout, 72, 0);	/* hRes */
+	putFixed(stdout, 72, 0);	/* vRes */
+	putShort(stdout, 0);	/* pixelType */
+	putShort(stdout, 8);	/* pixelSize */
+	putShort(stdout, 1);	/* cmpCount */
+	putShort(stdout, 8);	/* cmpSize */
+	putLong(stdout, 0L);	/* planeBytes */
+	putLong(stdout, 0L);	/* pmTable */
+	putLong(stdout, 0L);	/* pmReserved */
+	putLong(stdout, 0L);	/* ctSeed */
+	putShort(stdout, 0);	/* ctFlags */
+	putShort(stdout, colors-1);	/* ctSize */
+
+	/* Write out the colormap. */
+	for (i = 0; i < colors; i++)
+	{
+		putShort(stdout, i);
+		rval = PPM_GETR(chv[i].color);
+		gval = PPM_GETG(chv[i].color);
+		bval = PPM_GETB(chv[i].color);
+		if (lmaxval != 65535L)
+		{
+			rval = rval * 65535L / lmaxval;
+			gval = gval * 65535L / lmaxval;
+			bval = bval * 65535L / lmaxval;
+		}
+		putShort(stdout, (short)rval);
+		putShort(stdout, (short)gval);
+		putShort(stdout, (short)bval);
+	}
+
+	putRect(stdout, 0, 0, rows, cols);	/* srcRect */
+	putRect(stdout, 0, 0, rows, cols);	/* dstRect */
+	putShort(stdout, 0);			/* mode */
+
+	/* Finally, write out the data. */
+	packed = (char*) malloc((unsigned)(cols+cols/MAX_COUNT+1));
+	oc = 0;
+	for (row = 0; row < rows; row++)
+		oc += putRow(stdout, row, cols, pixels[row], packed);
+
+	/* if we wrote an odd number of pixdata bytes, pad */
+	if (oc & 1)
+		(void) putc(0, stdout);
+	putShort(stdout, PICT_EndOfPicture);
+
+	lmaxval = ftell(stdout) - HEADER_SIZE;
+	if (fseek(stdout, (long)HEADER_SIZE, 0) >= 0)
+		putShort(stdout, (short)(lmaxval & 0xffff));
+
+	exit(0);
+}
+
+static void
+putFill(fd, n)
+FILE *fd;
+int n;
+{
+	register int i;
+
+	for (i = 0; i < n; i++)
+		(void) putc(0, fd);
+}
+
+static void
+putShort(fd, i)
+FILE *fd;
+int i;
+{
+	(void) putc((i >> 8) & 0xff, fd);
+	(void) putc(i & 0xff, fd);
+}
+
+#if __STDC__
+static void
+putLong( FILE *fd, long i )
+#else /*__STDC__*/
+static void
+putLong(fd, i)
+FILE *fd;
+long i;
+#endif /*__STDC__*/
+{
+	(void) putc((int)((i >> 24) & 0xff), fd);
+	(void) putc(((int)(i >> 16) & 0xff), fd);
+	(void) putc(((int)(i >> 8) & 0xff), fd);
+	(void) putc((int)(i & 0xff), fd);
+}
+
+static void
+putFixed(fd, in, frac)
+FILE *fd;
+int in, frac;
+{
+	putShort(fd, in);
+	putShort(fd, frac);
+}
+
+static void
+putRect(fd, x1, x2, y1, y2)
+FILE *fd;
+int x1, x2, y1, y2;
+{
+	putShort(fd, x1);
+	putShort(fd, x2);
+	putShort(fd, y1);
+	putShort(fd, y2);
+}
+
+#define	RUNLENGTH
+#ifdef	RUNLENGTH
+
+#define		runtochar(c)	(257-(c))
+#define		counttochar(c)	((c)-1)
+
+static int
+putRow(fd, row, cols, rowpixels, packed)
+FILE *fd;
+int row, cols;
+pixel *rowpixels;
+char *packed;
+{
+	register int i;
+	int packcols, count, run, rep, oc;
+	register pixel *pP;
+	pixel lastp;
+	register char *p;
+
+	run = count = 0;
+	for (cols--, i = cols, pP = rowpixels + cols, p = packed, lastp = *pP;
+		i >= 0; i--, lastp = *pP, pP--)
+	{
+		if (PPM_EQUAL(lastp, *pP))
+			run++;
+		else if (run < RUN_THRESH)
+		{
+			while (run > 0)
+			{
+				*p++ = ppm_lookupcolor(cht, &lastp);
+				run--;
+				count++;
+				if (count == MAX_COUNT)
+				{
+					*p++ = counttochar(MAX_COUNT);
+					count -= MAX_COUNT;
+				}
+			}
+			run = 1;
+		}
+		else
+		{
+			if (count > 0)
+				*p++ = counttochar(count);
+			count = 0;
+			while (run > 0)
+			{
+				rep = run > MAX_RUN ? MAX_RUN : run;
+				*p++ = ppm_lookupcolor(cht, &lastp);
+				*p++ = runtochar(rep);
+				run -= rep;
+			}
+			run = 1;
+		}
+	}
+	if (run < RUN_THRESH)
+	{
+		while (run > 0)
+		{
+			*p++ = ppm_lookupcolor(cht, &lastp);
+			run--;
+			count++;
+			if (count == MAX_COUNT)
+			{
+				*p++ = counttochar(MAX_COUNT);
+				count -= MAX_COUNT;
+			}
+		}
+	}
+	else
+	{
+		if (count > 0)
+			*p++ = counttochar(count);
+		count = 0;
+		while (run > 0)
+		{
+			rep = run > MAX_RUN ? MAX_RUN : run;
+			*p++ = ppm_lookupcolor(cht, &lastp);
+			*p++ = runtochar(rep);
+				run -= rep;
+		}
+		run = 1;
+	}
+	if (count > 0)
+		*p++ = counttochar(count);
+
+	packcols = p - packed;		/* how many did we write? */
+	if (cols > 250)
+	{
+		putShort(fd, packcols);
+		oc = packcols + 2;
+	}
+	else
+	{
+		(void) putc(packcols, fd);
+		oc = packcols + 1;
+	}
+
+	/* now write out the packed row */
+	while(p != packed)
+	{
+		--p;
+		(void) putc(*p, fd);
+	}
+
+	return (oc);
+}
+
+#else	/* RUNLENGTH */
+
+/* real dumb putRow with no compression */
+static int
+putRow(fd, row, cols, rowpixels, packed)
+FILE *fd;
+int row, cols;
+pixel *rowpixels;
+char *packed;
+{
+	register int i, j, bc, oc;
+	register pixel *pP;
+
+#if notdef
+	bzero(aux, cols); /* aux?? */
+#endif /*notdef*/
+	bc = cols + (cols + MAX_COUNT - 1) / MAX_COUNT;
+	if (bc > 250)
+	{
+		putShort(fd, bc);
+		oc = bc + 2;
+	}
+	else
+	{
+		(void) putc(bc, fd);
+		oc = bc + 1;
+	}
+	for (i = 0, pP = rowpixels; i < cols;)
+	{
+		if (cols - i > MAX_COUNT)
+		{
+			(void) putc(MAX_COUNT - 1, fd);
+			for (j = 0; j < MAX_COUNT; j++)
+			{
+				(void) putc(ppm_lookupcolor(cht, pP), fd);
+				pP++;
+			}
+			i += MAX_COUNT;
+		}
+		else
+		{
+			(void) putc(cols - i - 1, fd);
+			for (j = 0; j < cols - i; j++)
+			{
+				(void) putc(ppm_lookupcolor(cht, pP), fd);
+				pP++;
+			}
+			i = cols;
+		}
+	}
+	return (oc);
+}
+#endif	/* RUNLENGTH */