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.c480
1 files changed, 249 insertions, 231 deletions
diff --git a/converter/ppm/ppmtopj.c b/converter/ppm/ppmtopj.c
index d116773f..8fe6c05d 100644
--- a/converter/ppm/ppmtopj.c
+++ b/converter/ppm/ppmtopj.c
@@ -1,4 +1,4 @@
-/* ppmtopj.c - convert a portable pixmap to an HP PainJetXL image
+/* ppmtopj.c - convert a PPM to an HP PainJetXL image
 **
 ** Copyright (C) 1990 by Christos Zoulas (christos@ee.cornell.edu)
 **
@@ -12,245 +12,263 @@
 
 #include <string.h>
 
+#include "mallocvar.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 
+#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;
+
+
+static void
+compressRow(const unsigned char * const opArg,
+            const unsigned char * const oe,
+            unsigned char *       const cp,
+            int *                 const szP) {
+/*----------------------------------------------------------------------------
+  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.
+-----------------------------------------------------------------------------*/
+    unsigned char * ce;
+    const unsigned char * op;
+
+    for (op = opArg, ce = cp; op < oe; ) {
+        unsigned char         const px = *op++;
+        const unsigned char * const pr = op;
+
+        while (op < oe && *op == px && op - pr < 255)
+            ++op;
+
+        *ce++ = op - pr;
+        *ce++ = px;
     }
-    return ce - cp;
+    *szP = 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);
+
+
+int
+main(int argc, const char ** argv) {
+
+    pixel ** pixels;
+    FILE * ifP;
+    int argn, rows, cols, k;
+    unsigned int row;
+    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 const posscale = C_BEGIN_RASTER_MARGIN | C_BEGIN_RASTER_NOSCALE;
+    int const 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]";
+
+
+    pm_proginit( &argc, argv );
+
+    argn = 1;
+    while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
+        {
+        if ( pm_keymatch(argv[argn],"-render",2) && argn + 1 < argc )
+        {
+        unsigned int r;
+        ++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);
+
+    MALLOCARRAY_NOFAIL(obuf, cols);
+
+    if (cols > UINT_MAX / 2)
+        pm_error("Image too wide (%u columns) for computation", cols);
+
+    MALLOCARRAY_NOFAIL(cbuf, cols * 2);
+
+    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;
+    }
+
+    printf(C_RESET);
+    /*
+     * Set the resolution before begin raster otherwise it
+     * does not work.
+     */
+    printf(C_RESOLUTION, resolution);
+    printf(C_BEGIN_RASTER, posscale);
+    if (xoff)
+        printf(C_MOVE_X, xoff);
+    if (yoff)
+        printf(C_MOVE_Y, yoff);
+    printf(C_TRANS_MODE, mode);
+    printf(C_RENDER, render_mode);
+    printf(C_BACK_SCALE, back_scale);
+    printf(C_GAMMA,   gamma);
+    printf(C_IMAGE_WIDTH, cols);
+    printf(C_IMAGE_HEIGHT, rows);
+    printf(C_DATA_PLANES, 3);
+
+    for (row = 0; row < rows; ++row) {
+        /* for each primary */
+        unsigned int plane;
+        for (plane = 0; plane < 3; ++plane) {
+            unsigned int col;
+
+            for (col = 0, op = &obuf[-1]; col < cols; ++col) {
+                pixel  const p = pixels[row][col];
+                pixval const comp =
+                    plane == 0 ? PPM_GETR(p) :
+                    plane == 1 ? PPM_GETG(p) :
+                    plane == 2 ? PPM_GETB(p) :
+                    0; /* can't happen */
+
+                if ((k = (col & 0x7)) == 0)
+                    *++op = 0;
+                if (comp > maxval / 2)
+                        *op |= 1 << (7 - k);
+            }
+            ++op;
+            if (mode == C_TRANS_MODE_RLE) {
+                compressRow(obuf, op, cbuf, &k);
+                op = cbuf;
+            } else {
+                k = op - obuf;
+                op = obuf;
+            }
+            printf(plane == 2 ? C_LAST_PLANE : C_SEND_PLANE, k);
+            fwrite(op, 1, k, stdout);
+        }
+    }
+    printf(C_END_RASTER, C_END_RASTER_UNUSED);
+
+    exit(0);
 }
+
+
+