about summary refs log tree commit diff
path: root/converter/ppm/ppmtopj.c
diff options
context:
space:
mode:
Diffstat (limited to 'converter/ppm/ppmtopj.c')
-rw-r--r--converter/ppm/ppmtopj.c256
1 files changed, 256 insertions, 0 deletions
diff --git a/converter/ppm/ppmtopj.c b/converter/ppm/ppmtopj.c
new file mode 100644
index 00000000..5d449f7a
--- /dev/null
+++ b/converter/ppm/ppmtopj.c
@@ -0,0 +1,256 @@
+/* ppmtopj.c - convert a portable pixmap to an HP PainJetXL image
+**
+** Copyright (C) 1990 by Christos Zoulas (christos@ee.cornell.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 <string.h>
+
+#include "nstring.h"
+#include "ppm.h"
+
+static int compress_row ARGS((unsigned char *op, unsigned char *oe, unsigned char *cp));
+/*
+ * XXX: Only 8.5 x 11 paper
+ */
+#define WIDTH	  8.5
+#define HEIGHT	  11.0
+#define DPI	  180
+#define XPIX	  ((int) ((DPI * WIDTH + 7) / 8) << 3)
+#define YPIX	  ((int) ((DPI * HEIGHT + 7) / 8) << 3)
+
+#define C_RESET 			"\033E"
+#define C_RENDER 			"\033*t%dJ"
+# define C_RENDER_NONE			0
+# define C_RENDER_SNAP			1
+# define C_RENDER_BW			2
+# define C_RENDER_DITHER		3
+# define C_RENDER_DIFFUSE		4
+# define C_RENDER_MONODITHER		5
+# define C_RENDER_MONODIFFUSE		6
+# define C_RENDER_MONO_CL_DITHER	5
+# define C_RENDER_MONO_CL_DIFFUSE	6
+#define C_BACK_SCALE			"\033*t%dK"
+# define C_BACK_SCALE_LIGHT		0
+# define C_BACK_SCALE_DARK		1
+#define C_GAMMA				"\033*t%dI"
+#define C_IMAGE_WIDTH			"\033*r%dS"
+#define C_IMAGE_HEIGHT			"\033*r%dT"
+#define C_DATA_PLANES			"\033*r%dU"
+#define C_TRANS_MODE			"\033*b%dM"
+# define C_TRANS_MODE_STD		0
+# define C_TRANS_MODE_RLE		1
+# define C_TRANS_MODE_TIFF		2
+#define C_SEND_PLANE			"\033*b%dV"
+#define C_LAST_PLANE			"\033*b%dW"
+#define C_BEGIN_RASTER			"\033*r%dA"
+# define C_BEGIN_RASTER_MARGIN		0
+# define C_BEGIN_RASTER_ACTIVE		1
+# define C_BEGIN_RASTER_NOSCALE		0
+# define C_BEGIN_RASTER_SCALE		2
+#define C_END_RASTER			"\033*r%dC"
+# define C_END_RASTER_UNUSED		0
+#define C_RESOLUTION			"\033*t%dR"
+# define C_RESOLUTION_90DPI		90
+# define C_RESOLUTION_180DPI		180
+#define C_MOVE_X			"\033*p+%dX"
+#define C_MOVE_Y			"\033*p+%dY"
+
+static const char * const rmode[] = { 
+    "none", "snap", "bw", "dither", "diffuse", 
+    "monodither", "monodiffuse", "clusterdither", 
+    "monoclusterdither", NULL 
+};
+
+/*
+ * Run-length encoding for the PaintJet. We have pairs of <instances>
+ * <value>, where instances goes from 0 (meaning one instance) to 255
+ * If we are unlucky we can double the size of the image.
+ */
+static int
+compress_row(op, oe, cp)
+unsigned char *op, *oe, *cp;
+{
+    unsigned char *ce = cp;
+    while ( op < oe ) {	
+	unsigned char px = *op++;
+	unsigned char *pr = op;
+	while ( op < oe && *op == px && op - pr < 255) op++;
+	*ce++ = op - pr;
+	*ce++ = px;
+    }
+    return ce - cp;
+}
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+	pixel **pixels;
+	FILE *ifp;
+	int argn, rows, cols, r, c, k, p;
+	pixval maxval;
+	unsigned char *obuf, *op, *cbuf;
+	int render_mode = C_RENDER_NONE;
+	int back_scale = C_BACK_SCALE_DARK;
+	int gamma = 0;
+	int mode = C_TRANS_MODE_STD;
+	int center = 0;
+	int xoff = 0, yoff = 0;
+	/*
+	 * XXX: Someday we could make this command line options.
+	 */
+	int posscale = C_BEGIN_RASTER_MARGIN | C_BEGIN_RASTER_NOSCALE;
+	int resolution = C_RESOLUTION_180DPI;
+
+	const char * const usage = "[-center] [-xpos <pos>] [-ypos <pos>] [-gamma <val>] [-back <dark|lite>] [-rle] [-render <none|snap|bw|dither|diffuse|monodither|monodiffuse|clusterdither|monoclusterdither>] [ppmfile]";
+
+
+	ppm_init( &argc, argv );
+
+	argn = 1;
+	while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
+	    {
+	    if ( pm_keymatch(argv[argn],"-render",2) && argn + 1 < argc )
+		{
+		++argn;
+		for (r = 0; rmode[r] != NULL; r++)
+		     if (STREQ(rmode[r], argv[argn]))
+			 break;
+		if (rmode[r] != NULL)
+		    render_mode = r;
+		else
+		    pm_usage(usage);
+		}
+	    else if ( pm_keymatch(argv[argn],"-back",2) && argn + 1 < argc )
+		{
+		++argn;
+		if (STREQ(argv[argn], "dark"))
+		    back_scale = C_BACK_SCALE_DARK;
+		else if (STREQ(argv[argn], "lite"))
+		    back_scale = C_BACK_SCALE_LIGHT;
+		else
+		    pm_usage(usage);
+		}
+	    else if ( pm_keymatch(argv[argn],"-gamma",2) && argn + 1 < argc )
+		{
+		++argn;
+		if ( sscanf( argv[argn], "%d",&gamma ) != 1 )
+		    pm_usage( usage );
+		}
+	    else if ( pm_keymatch(argv[argn],"-xpos",2) && argn + 1 < argc )
+		{
+		++argn;
+		if ( sscanf( argv[argn], "%d",&xoff ) != 1 )
+		    pm_usage( usage );
+		}
+	    else if ( pm_keymatch(argv[argn],"-ypos",2) && argn + 1 < argc )
+		{
+		++argn;
+		if ( sscanf( argv[argn], "%d",&yoff ) != 1 )
+		    pm_usage( usage );
+		}
+	    else if (pm_keymatch(argv[argn],"-rle",2))
+		mode = C_TRANS_MODE_RLE;
+	    else if (pm_keymatch(argv[argn],"-center",2))
+		center = 1;
+	    else
+		pm_usage( usage );
+	    ++argn;
+	    }
+
+	if ( argn < argc )
+	    {
+	    ifp = pm_openr( argv[argn] );
+	    ++argn;
+	    }
+	else
+	    ifp = stdin;
+
+	if ( argn != argc )
+	    pm_usage( usage );
+
+	pixels = ppm_readppm( ifp, &cols, &rows, &maxval );
+
+	pm_close( ifp );
+	obuf = (unsigned char *) pm_allocrow(cols, sizeof(unsigned char));
+	cbuf = (unsigned char *) pm_allocrow(cols * 2, sizeof(unsigned char));
+
+        if (cols > XPIX || rows > YPIX)
+	    pm_message("image too large for page");
+        if (center) {
+	    if (xoff || yoff)
+		pm_error("cannot specify both center and position");
+	    xoff = (XPIX - cols) / 2;
+	    yoff = (YPIX - rows) / 2;
+	}
+
+	(void) printf(C_RESET);
+	/*
+	 * Set the resolution before begin raster otherwise it
+	 * does not work.
+	 */
+	(void) printf(C_RESOLUTION, resolution);
+	(void) printf(C_BEGIN_RASTER, posscale);
+	if (xoff)
+	    (void) printf(C_MOVE_X, xoff);
+	if (yoff)
+	    (void) printf(C_MOVE_Y, yoff);
+	(void) printf(C_TRANS_MODE, mode);
+	(void) printf(C_RENDER, render_mode);
+	(void) printf(C_BACK_SCALE, back_scale);
+	(void) printf(C_GAMMA,	 gamma);
+	(void) printf(C_IMAGE_WIDTH, cols);
+	(void) printf(C_IMAGE_HEIGHT, rows);
+	(void) printf(C_DATA_PLANES, 3);
+
+        for (r = 0; r < rows; r++)
+	    /* for each primary */
+	    for (p = 0; p < 3; p++) {
+		switch (p) {
+		case 0:
+		    for (c = 0, op = &obuf[-1]; c < cols; c++) {
+			if ((k = (c & 7)) == 0)
+			    *++op = 0;
+			if (PPM_GETR(pixels[r][c]) > maxval / 2)
+			    *op |= 1 << (7 - k);
+		    }
+		    break;
+		case 1:
+		    for (c = 0, op = &obuf[-1]; c < cols; c++) {
+			if ((k = (c & 7)) == 0)
+			    *++op = 0;
+			if (PPM_GETG(pixels[r][c]) > maxval / 2)
+			    *op |= 1 << (7 - k);
+		    }
+		    break;
+		case 2:
+		    for (c = 0, op = &obuf[-1]; c < cols; c++) {
+			if ((k = (c & 7)) == 0)
+			    *++op = 0;
+			if (PPM_GETB(pixels[r][c]) > maxval / 2)
+			    *op |= 1 << (7 - k);
+		    }
+		    break;
+		}
+		++op;
+		if (mode == C_TRANS_MODE_RLE) {
+		    k = compress_row(obuf, op, cbuf);
+		    op = cbuf;
+		}
+		else {
+		    k = op - obuf;
+		    op = obuf;
+		}
+		(void) printf(p == 2 ? C_LAST_PLANE : C_SEND_PLANE, k);
+		(void) fwrite(op, 1, k, stdout);
+	    }
+	(void) printf(C_END_RASTER, C_END_RASTER_UNUSED);
+	exit(0);
+}