diff options
Diffstat (limited to 'converter/ppm/ppmtopj.c')
-rw-r--r-- | converter/ppm/ppmtopj.c | 256 |
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); +} |