Newsgroups: comp.sources.misc
From: jef@well.sf.ca.us (Jef Poskanzer)
Subject:  REPOST: v23i054:  pbmplus - Extended Portable Bitmap Toolkit, Part19/24
Message-ID: <1991Oct17.041413.14976@sparky.imd.sterling.com>
X-Md4-Signature: 8c650c6295ed7fc209ffdb5baa975584
Date: Thu, 17 Oct 1991 04:14:13 GMT
Approved: kent@sparky.imd.sterling.com

Submitted-by: jef@well.sf.ca.us (Jef Poskanzer)
Posting-number: Volume 23, Issue 54
Archive-name: pbmplus/part19
Environment: UNIX

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	ppm/pjtoppm.c
#	ppm/pjtoppm.1
#	ppm/ppmtopj.c
#	ppm/ppmtopj.1
#	ppm/ppmdither.c
#	ppm/ppmdither.1
#	ppm/ppmtotga.c
#	ppm/ppmtotga.1
#	ppm/ppmtosixel.c
#	ppm/ppmtosixel.1
#	ppm/ppmtoyuv.c
#	ppm/ppmtoyuv.1
#	ppm/yuvtoppm.c
#	ppm/yuvtoppm.1
# This archive created: Fri Sep 27 17:50:44 1991
# By:	Jef Poskanzer (Acme Software)
export PATH; PATH=/bin:$PATH
if test ! -d 'ppm'
then
	echo shar: creating directory "'ppm'"
	mkdir 'ppm'
fi
echo shar: extracting "'ppm/pjtoppm.c'" '(6150 characters)'
if test -f 'ppm/pjtoppm.c'
then
	echo shar: will not over-write existing file "'ppm/pjtoppm.c'"
else
sed 's/^X//' << \SHAR_EOF > 'ppm/pjtoppm.c'
X/* pjtoppm.c - convert an HP PainJetXL image to a portable pixmap file
X**
X** Copyright (C) 1990 by Christos Zoulas (christos@ee.cornell.edu)
X**
X** Permission to use, copy, modify, and distribute this software and its
X** documentation for any purpose and without fee is hereby granted, provided
X** that the above copyright notice appear in all copies and that both that
X** copyright notice and this permission notice appear in supporting
X** documentation.  This software is provided "as is" without express or
X** implied warranty.
X*/
X
X#include "ppm.h"
X
Xstatic char usage[] =  "[paintjetfile]";
X
Xstatic int
Xegetc(fp)
XFILE *fp;
X{
X    int c;
X    if ((c = fgetc(fp)) == -1)
X	pm_error("unexpected end of file");
X    return(c);
X}
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X    int cmd, val;
X    char buffer[BUFSIZ];
X    int planes = 3, rows = -1, cols = -1;
X    int r = 0, c = 0, p = 0, i;
X    unsigned char **image = NULL;
X    int *imlen;
X    FILE *fp = stdin;
X    int mode;
X    int argn;
X    unsigned char bf[3];
X    pixel *pixrow;
X
X    ppm_init(&argc, argv);
X    argn = 1;
X    if (argn != argc)
X	fp = pm_openr(argv[argn++]);
X    else
X	fp = stdin;
X
X    if (argn != argc)
X	pm_usage(usage);
X
X    while ((c = fgetc(fp)) != -1) {
X	if (c != '\033')
X	    continue;
X	switch (c = egetc(fp)) {
X	case 'E':	/* reset */
X	    break;
X	case '*':
X	    cmd = egetc(fp);
X	    for (i = 0; i < BUFSIZ; i++) {
X		if (!isdigit(c = egetc(fp)) && c != '+' && c != '-')
X		    break;
X		buffer[i] = c;
X	    }
X	    if (i != 0) {
X		buffer[i] = '\0';
X		if (sscanf(buffer, "%d", &val) != 1) 
X		    pm_error("bad value `%s' at <ESC>*%c%c", buffer, cmd, c);
X	    }
X	    else
X		val = -1;
X	    switch (cmd) {
X	    case 't':
X		switch (c) {
X		case 'J':	/* render */
X		    break;
X		case 'K':	/* back scale */
X		    break;
X		case 'I':	/* gamma */
X		    break;
X		case 'R':
X		    break;	/* set resolution */
X		default:
X		    pm_message("uninmplemented <ESC>*%c%d%c", cmd, val, c);
X		    break;
X		}
X		break;
X	    case 'r':
X		switch (c) {
X		case 'S':	/* width */
X		    cols = val;
X		    break;
X		case 'T':	/* height */
X		    rows = val;
X		    break;
X		case 'U':	/* planes */
X		    planes = val;
X		    if (planes != 3) 
X			pm_error("can handle only 3 plane files");
X		    break;
X		case 'A':	/* begin raster */
X		    break;
X		case 'B':
X		case 'C':	/* end raster */
X		    break;
X		case 'V':
X		    break;	/* set deci height */
X		case 'H':
X		    break;	/* set deci width */
X		default:
X		    pm_message("uninmplemented <ESC>*%c%d%c", cmd, val, c);
X		    break;
X		}
X		break;
X	    case 'b':
X		switch (c) {
X		case 'M':	/* transmission mode */
X		    if (val != 0 && val != 1)
X			pm_error("unimplemented trasmission mode %d", val);
X		    mode = val;
X		    break;
X		case 'V':	/* send plane */
X		case 'W':	/* send last plane */
X		    if (rows == -1 || r >= rows || image == NULL) {
X			if (rows == -1 || r >= rows)
X			    rows += 100;
X			if (image == NULL) {
X			    image = (unsigned char **) 
X				malloc(rows * planes * sizeof(unsigned char *));
X			    imlen = (int *) malloc(rows * planes * sizeof(int));
X			}
X			else {
X			    image = (unsigned char **) 
X				realloc(image, rows * planes * 
X					sizeof(unsigned char *));
X			    imlen = (int *) realloc(imlen, rows * planes * 
X						    sizeof(int));
X			}
X		    }
X		    if (image == NULL || imlen == NULL)
X			pm_error("out of memory");
X		    if (p == planes) 
X			pm_error("too many planes");
X		    cols = cols > val ? cols : val;
X		    imlen[r * planes + p] = val;
X		    image[r * planes + p] = (unsigned char *) 
X			malloc(val * sizeof(unsigned char));
X		    if (image[r * planes + p] == NULL) 
X			pm_error("out of memory");
X		    if (fread(image[r * planes + p], 1, val, fp) != val) 
X			pm_error("short data");
X		    if (c == 'V')
X			p++;
X		    else {
X			p = 0;
X			r++;
X		    }
X		    break;
X		default:
X		    pm_message("uninmplemented <ESC>*%c%d%c", cmd, val, c);
X		    break;
X		}
X		break;
X	    case 'p': /* Position */
X		if (p != 0) 
X		    pm_error("changed position in the middle of transferring planes");
X		switch (c) {
X		case 'X':
X		    pm_message("can only position in y");
X		    break;
X		case 'Y':
X		    if (buffer[0] == '+')
X			val = r + val;
X		    if (buffer[0] == '-')
X			val = r - val;
X		    for (; val > r; r++) 
X			for (p = 0; p < 3; p++) {
X			    imlen[r * planes + p] = 0;
X			    image[r * planes + p] = NULL;
X			}
X		    r = val;
X		    break;
X		default:
X		    pm_message("uninmplemented <ESC>*%c%d%c", cmd, val, c);
X		    break;
X		}
X	    default:
X		pm_message("uninmplemented <ESC>*%c%d%c", cmd, val, c);
X		break;
X	    }
X	}
X    }
X    pm_close(fp);
X    rows = r;
X    if (mode == 1) {
X	unsigned char *buf;
X	int newcols = 0;
X	newcols = 10240; /* It could not be larger that that! */
X	cols = 0;
X	for (r = 0; r < rows; r++) {
X	    if (image[r * planes] == NULL)
X		continue;
X	    for (p = 0; p < planes; p++) {
X		buf = (unsigned char *) malloc(newcols * 
X					       sizeof(unsigned char *));
X		if (buf == NULL) 
X		    pm_error("out of memory");
X		for (i = 0, c = 0; c < imlen[p + r * planes]; c += 2)
X		    for (cmd = image[p + r * planes][c],
X			 val = image[p + r * planes][c+1]; 
X			 cmd >= 0 && i < newcols; cmd--, i++) 
X			 buf[i] = val;
X		cols = cols > i ? cols : i;
X		free(image[p + r * planes]);
X		/* 
X		 * This is less than what we have so it realloc should 
X		 * not return null. Even if it does, tough! We will
X		 * lose a line, and probably die on the next line anyway
X		 */
X		image[p + r * planes] = (unsigned char *) realloc(buf, i);
X	    }
X	}
X	cols *= 8;
X    }
X			
X	   
X    ppm_writeppminit(stdout, cols, rows, (pixval) 255, 0);
X    pixrow = ppm_allocrow(cols);
X    for (r = 0; r < rows; r++) {
X	if (image[r * planes] == NULL) {
X	    for (c = 0; c < cols; c++)
X		PPM_ASSIGN(pixrow[c], 0, 0, 0);
X	    continue;
X	}
X	for (cmd = 0, c = 0; c < cols; c += 8, cmd++) 
X	    for (i = 0; i < 8 & c + i < cols; i++) {
X		for (p = 0; p < planes; p++) 
X		    if (mode == 0 && cmd >= imlen[r * planes + p])
X			bf[p] = 0;
X		    else
X			bf[p] = (image[r * planes + p][cmd] & 
X				     (1 << (7 - i))) ? 255 : 0;
X		PPM_ASSIGN(pixrow[c + i], bf[0], bf[1], bf[2]);
X	    }
X	    ppm_writeppmrow(stdout, pixrow, cols, (pixval) 255, 0);
X    }
X    exit(0);
X}
SHAR_EOF
if test 6150 -ne "`wc -c < 'ppm/pjtoppm.c'`"
then
	echo shar: error transmitting "'ppm/pjtoppm.c'" '(should have been 6150 characters)'
fi
fi # end of overwriting check
if test ! -d 'ppm'
then
	echo shar: creating directory "'ppm'"
	mkdir 'ppm'
fi
echo shar: extracting "'ppm/pjtoppm.1'" '(966 characters)'
if test -f 'ppm/pjtoppm.1'
then
	echo shar: will not over-write existing file "'ppm/pjtoppm.1'"
else
sed 's/^X//' << \SHAR_EOF > 'ppm/pjtoppm.1'
X.TH pjtoppm 1 "14 July 1991"
X.IX pjtoppm
X.SH NAME
Xpjtoppm - convert an HP PaintJet file to a portable pixmap
X.SH SYNOPSIS
X.B pjtoppm
X.RI [ paintjet ]
X.SH DESCRIPTION
XReads an HP PaintJet file as input and converts it into a portable pixmap.
XThis was a quick hack to save some trees, and it only handles a small
Xsubset of the paintjet commands.
XIn particular, it will only handle 
Xenough commands to convert most raster image files.
X.SH REFERENCES
XHP PaintJet XL Color Graphics Printer User's Guide
X.SH "SEE ALSO"
Xppmtopj(1)
X.SH AUTHOR
XCopyright (C) 1991 by Christos Zoulas.
X.\" Permission to use, copy, modify, and distribute this software and its
X.\" documentation for any purpose and without fee is hereby granted, provided
X.\" that the above copyright notice appear in all copies and that both that
X.\" copyright notice and this permission notice appear in supporting
X.\" documentation.  This software is provided "as is" without express or
X.\" implied warranty.
SHAR_EOF
if test 966 -ne "`wc -c < 'ppm/pjtoppm.1'`"
then
	echo shar: error transmitting "'ppm/pjtoppm.1'" '(should have been 966 characters)'
fi
fi # end of overwriting check
if test ! -d 'ppm'
then
	echo shar: creating directory "'ppm'"
	mkdir 'ppm'
fi
echo shar: extracting "'ppm/ppmtopj.c'" '(6853 characters)'
if test -f 'ppm/ppmtopj.c'
then
	echo shar: will not over-write existing file "'ppm/ppmtopj.c'"
else
sed 's/^X//' << \SHAR_EOF > 'ppm/ppmtopj.c'
X/* ppmtopj.c - convert a portable pixmap to an HP PainJetXL image
X**
X** Copyright (C) 1990 by Christos Zoulas (christos@ee.cornell.edu)
X**
X** Permission to use, copy, modify, and distribute this software and its
X** documentation for any purpose and without fee is hereby granted, provided
X** that the above copyright notice appear in all copies and that both that
X** copyright notice and this permission notice appear in supporting
X** documentation.  This software is provided "as is" without express or
X** implied warranty.
X*/
X
X#include "ppm.h"
X
X/*
X * XXX: Only 8.5 x 11 paper
X */
X#define WIDTH	  8.5
X#define HEIGHT	  11.0
X#define DPI	  180
X#define XPIX	  ((int) ((DPI * WIDTH + 7) / 8) << 3)
X#define YPIX	  ((int) ((DPI * HEIGHT + 7) / 8) << 3)
X
X#define C_RESET 			"\033E"
X#define C_RENDER 			"\033*t%dJ"
X# define C_RENDER_NONE			0
X# define C_RENDER_SNAP			1
X# define C_RENDER_BW			2
X# define C_RENDER_DITHER		3
X# define C_RENDER_DIFFUSE		4
X# define C_RENDER_MONODITHER		5
X# define C_RENDER_MONODIFFUSE		6
X# define C_RENDER_MONO_CL_DITHER	5
X# define C_RENDER_MONO_CL_DIFFUSE	6
X#define C_BACK_SCALE			"\033*t%dK"
X# define C_BACK_SCALE_LIGHT		0
X# define C_BACK_SCALE_DARK		1
X#define C_GAMMA				"\033*t%dI"
X#define C_IMAGE_WIDTH			"\033*r%dS"
X#define C_IMAGE_HEIGHT			"\033*r%dT"
X#define C_DATA_PLANES			"\033*r%dU"
X#define C_TRANS_MODE			"\033*b%dM"
X# define C_TRANS_MODE_STD		0
X# define C_TRANS_MODE_RLE		1
X# define C_TRANS_MODE_TIFF		2
X#define C_SEND_PLANE			"\033*b%dV"
X#define C_LAST_PLANE			"\033*b%dW"
X#define C_BEGIN_RASTER			"\033*r%dA"
X# define C_BEGIN_RASTER_MARGIN		0
X# define C_BEGIN_RASTER_ACTIVE		1
X# define C_BEGIN_RASTER_NOSCALE		0
X# define C_BEGIN_RASTER_SCALE		2
X#define C_END_RASTER			"\033*r%dC"
X# define C_END_RASTER_UNUSED		0
X#define C_RESOLUTION			"\033*t%dR"
X# define C_RESOLUTION_90DPI		90
X# define C_RESOLUTION_180DPI		180
X#define C_MOVE_X			"\033*p+%dX"
X#define C_MOVE_Y			"\033*p+%dY"
X
Xchar *testimage;
X
Xstatic char *rmode[] = { "none", "snap", "bw", "dither", "diffuse", 
X			 "monodither", "monodiffuse", "clusterdither", 
X			 "monoclusterdither", NULL };
X
X/*
X * Run-length encoding for the PaintJet. We have pairs of <instances>
X * <value>, where instances goes from 0 (meaning one instance) to 255
X * If we are unlucky we can double the size of the image.
X */
Xstatic int
Xcompress_row(op, oe, cp)
Xunsigned char *op, *oe, *cp;
X{
X    unsigned char *ce = cp;
X    while ( op < oe ) {	
X	unsigned char px = *op++;
X	unsigned char *pr = op;
X	while ( op < oe && *op == px && op - pr < 255) op++;
X	*ce++ = op - pr;
X	*ce++ = px;
X    }
X    return ce - cp;
X}
X
Xvoid main(argc, argv)
Xint argc;
Xchar *argv[];
X{
X	pixel **pixels;
X	FILE *ifp;
X	int argn, rows, cols, colors, r, c, k, m, p;
X	pixval maxval;
X	int planes = 3;
X	unsigned char *obuf, *op, *cbuf;
X	int render_mode = C_RENDER_NONE;
X	int back_scale = C_BACK_SCALE_DARK;
X	int gamma = 0;
X	int mode = C_TRANS_MODE_STD;
X	int deciwidth = 0, deciheight = 0;
X	int center = 0;
X	int xoff = 0, yoff = 0;
X	/*
X	 * XXX: Someday we could make this command line options.
X	 */
X	int posscale = C_BEGIN_RASTER_MARGIN | C_BEGIN_RASTER_NOSCALE;
X	int resolution = C_RESOLUTION_180DPI;
X
X	char *usage = "[-center] [-xpos <pos>] [-ypos <pos>] [-gamma <val>] [-back <dark|lite>] [-rle] [-render <none|snap|bw|dither|diffuse|monodither|monodiffuse|clusterdither|monoclusterdither>] [ppmfile]";
X
X	ppm_init( &argc, argv );
X
X	argn = 1;
X	while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
X	    {
X	    if ( pm_keymatch(argv[argn],"-render",2) && argn + 1 < argc )
X		{
X		++argn;
X		for (r = 0; rmode[r] != NULL; r++)
X		     if (strcmp(rmode[r], argv[argn]) == 0)
X			 break;
X		if (rmode[r] != NULL)
X		    render_mode = r;
X		else
X		    pm_usage(usage);
X		}
X	    else if ( pm_keymatch(argv[argn],"-back",2) && argn + 1 < argc )
X		{
X		++argn;
X		if (strcmp(argv[argn], "dark") == 0)
X		    back_scale = C_BACK_SCALE_DARK;
X		else if (strcmp(argv[argn], "lite") == 0)
X		    back_scale = C_BACK_SCALE_LIGHT;
X		else
X		    pm_usage(usage);
X		}
X	    else if ( pm_keymatch(argv[argn],"-gamma",2) && argn + 1 < argc )
X		{
X		++argn;
X		if ( sscanf( argv[argn], "%d",&gamma ) != 1 )
X		    pm_usage( usage );
X		}
X	    else if ( pm_keymatch(argv[argn],"-xpos",2) && argn + 1 < argc )
X		{
X		++argn;
X		if ( sscanf( argv[argn], "%d",&xoff ) != 1 )
X		    pm_usage( usage );
X		}
X	    else if ( pm_keymatch(argv[argn],"-ypos",2) && argn + 1 < argc )
X		{
X		++argn;
X		if ( sscanf( argv[argn], "%d",&yoff ) != 1 )
X		    pm_usage( usage );
X		}
X	    else if (pm_keymatch(argv[argn],"-rle",2))
X		mode = C_TRANS_MODE_RLE;
X	    else if (pm_keymatch(argv[argn],"-center",2))
X		center = 1;
X	    else
X		pm_usage( usage );
X	    ++argn;
X	    }
X
X	if ( argn < argc )
X	    {
X	    ifp = pm_openr( argv[argn] );
X	    ++argn;
X	    }
X	else
X	    ifp = stdin;
X
X	if ( argn != argc )
X	    pm_usage( usage );
X
X	pixels = ppm_readppm( ifp, &cols, &rows, &maxval );
X
X	pm_close( ifp );
X	obuf = (unsigned char *) pm_allocrow(cols, sizeof(unsigned char));
X	cbuf = (unsigned char *) pm_allocrow(cols * 2, sizeof(unsigned char));
X
X        if (cols > XPIX || rows > YPIX)
X	    pm_message("image too large for page");
X        if (center) {
X	    if (xoff || yoff)
X		pm_error("cannot specify both center and position");
X	    xoff = (XPIX - cols) / 2;
X	    yoff = (YPIX - rows) / 2;
X	}
X
X	(void) printf(C_RESET);
X	/*
X	 * Set the resolution before begin raster otherwise it
X	 * does not work.
X	 */
X	(void) printf(C_RESOLUTION, resolution);
X	(void) printf(C_BEGIN_RASTER, posscale);
X	if (xoff)
X	    (void) printf(C_MOVE_X, xoff);
X	if (yoff)
X	    (void) printf(C_MOVE_Y, yoff);
X	(void) printf(C_TRANS_MODE, mode);
X	(void) printf(C_RENDER, render_mode);
X	(void) printf(C_BACK_SCALE, back_scale);
X	(void) printf(C_GAMMA,	 gamma);
X	(void) printf(C_IMAGE_WIDTH, cols);
X	(void) printf(C_IMAGE_HEIGHT, rows);
X	(void) printf(C_DATA_PLANES, 3);
X
X        for (r = 0; r < rows; r++)
X	    /* for each primary */
X	    for (p = 0; p < 3; p++) {
X		switch (p) {
X		case 0:
X		    for (c = 0, op = &obuf[-1]; c < cols; c++) {
X			if ((k = (c & 7)) == 0)
X			    *++op = 0;
X			if (PPM_GETR(pixels[r][c]) > maxval / 2)
X			    *op |= 1 << (7 - k);
X		    }
X		    break;
X		case 1:
X		    for (c = 0, op = &obuf[-1]; c < cols; c++) {
X			if ((k = (c & 7)) == 0)
X			    *++op = 0;
X			if (PPM_GETG(pixels[r][c]) > maxval / 2)
X			    *op |= 1 << (7 - k);
X		    }
X		    break;
X		case 2:
X		    for (c = 0, op = &obuf[-1]; c < cols; c++) {
X			if ((k = (c & 7)) == 0)
X			    *++op = 0;
X			if (PPM_GETB(pixels[r][c]) > maxval / 2)
X			    *op |= 1 << (7 - k);
X		    }
X		    break;
X		}
X		++op;
X		if (mode == C_TRANS_MODE_RLE) {
X		    k = compress_row(obuf, op, cbuf);
X		    op = cbuf;
X		}
X		else {
X		    k = op - obuf;
X		    op = obuf;
X		}
X		(void) printf(p == 2 ? C_LAST_PLANE : C_SEND_PLANE, k);
X		(void) fwrite(op, 1, k, stdout);
X	    }
X	(void) printf(C_END_RASTER, C_END_RASTER_UNUSED);
X	exit(0);
X}
SHAR_EOF
if test 6853 -ne "`wc -c < 'ppm/ppmtopj.c'`"
then
	echo shar: error transmitting "'ppm/ppmtopj.c'" '(should have been 6853 characters)'
fi
fi # end of overwriting check
if test ! -d 'ppm'
then
	echo shar: creating directory "'ppm'"
	mkdir 'ppm'
fi
echo shar: extracting "'ppm/ppmtopj.1'" '(2151 characters)'
if test -f 'ppm/ppmtopj.1'
then
	echo shar: will not over-write existing file "'ppm/ppmtopj.1'"
else
sed 's/^X//' << \SHAR_EOF > 'ppm/ppmtopj.1'
X.TH ppmtopj 1 "13 July 1991"
X.IX ppmtopj
X.SH NAME
Xppmtopj - convert a portable pixmap to an HP PaintJet file
X.SH SYNOPSIS
X.B ppmtopj
X.RB [-gamma
X.IR val ]
X.RB [ -xpos
X.IR val ]
X.RB [ -ypos
X.IR val ]
X.RB [ -back
X.BR dark | lite ]
X.RB [ -rle ]
X.RB [ -center ]
X.RB [ -render
X.BR none|snap|bw|dither|diffuse|monodither|monodiffuse|clusterdither|monoclusterdither ]
X.RI [ ppmfile ]
X.SH DESCRIPTION
XReads a portable pixmap as input and converts it into a format suitable
Xto be printed by an HP PaintJet printer.
X.PP
XFor best results, the input file should be in 8-color RGB form;
Xi.e. it should have only
Xthe 8 binary combinations of full-on and full-off primaries.
XYou could get this by sending the input file through
X.I ppmquant -map
Xwith a map file such as:
X.nf
X    P3
X    8 1
X    255
X    0 0 0      255 0 0    0 255 0    0 0 255
X    255 255 0  255 0 255  0 255 255  255 255 255
X.fi
XOr else you could use use
X.I ppmdither -red 2 -green 2 -blue 2.
X.SH OPTIONS
X.TP 14
X.B -rle
XRun length encode the image.
X(This can result in larger images)
X.TP
X.B -back
XEnhance the foreground by indicating if the background is light or
Xdark compated to the foreground.
X.TP
X.BI -render " alg"
XUse an internal rendering algorithm (default dither).
X.TP
X.BI -gamma " int"
XGamma correct the image using the integet parameter as a gamma (default 0).
X.TP
X.B -center
XCenter the image to an 8.5 by 11 page
X.TP
X.BI -xpos " pos"
XMove by pos pixels in the x direction.
X.TP
X.BI -ypos " pos"
XMove by pos pixels in the y direction.
X.SH REFERENCES
XHP PaintJet XL Color Graphics Printer User's Guide
X.SH "SEE ALSO"
Xpnmdepth(1), ppmquant(1), ppmdither(1), ppm(5)
X.SH BUGS
XMost of the options have not been tested because of the price of the paper.
X.SH AUTHOR
XCopyright (C) 1991 by Christos Zoulas.
X.\" Permission to use, copy, modify, and distribute this software and its
X.\" documentation for any purpose and without fee is hereby granted, provided
X.\" that the above copyright notice appear in all copies and that both that
X.\" copyright notice and this permission notice appear in supporting
X.\" documentation.  This software is provided "as is" without express or
X.\" implied warranty.
SHAR_EOF
if test 2151 -ne "`wc -c < 'ppm/ppmtopj.1'`"
then
	echo shar: error transmitting "'ppm/ppmtopj.1'" '(should have been 2151 characters)'
fi
fi # end of overwriting check
if test ! -d 'ppm'
then
	echo shar: creating directory "'ppm'"
	mkdir 'ppm'
fi
echo shar: extracting "'ppm/ppmdither.c'" '(6521 characters)'
if test -f 'ppm/ppmdither.c'
then
	echo shar: will not over-write existing file "'ppm/ppmdither.c'"
else
sed 's/^X//' << \SHAR_EOF > 'ppm/ppmdither.c'
X/* ppmdither.c - Ordered dithering of a color ppm file to a specified number
X**               of primary shades.
X**
X** Copyright (C) 1991 by Christos Zoulas.
X**
X** Permission to use, copy, modify, and distribute this software and its
X** documentation for any purpose and without fee is hereby granted, provided
X** that the above copyright notice appear in all copies and that both that
X** copyright notice and this permission notice appear in supporting
X** documentation.  This software is provided "as is" without express or
X** implied warranty.
X*/
X
X#include "ppm.h"
X
X#define NC 256			/* Total number of colors		*/
X#define NS 256			/* Max number of shades in primary	*/
X
Xtypedef unsigned char ubyte;
X
Xstatic int dith_nr  =   5;	/* number of red shades			*/
Xstatic int dith_ng  =   9;	/* number of green shades		*/
Xstatic int dith_nb  =   5;	/* number of blue shades		*/
Xstatic int dith_nc  = 225;	/* total number of colors 5 x 9 x 5	*/
Xstatic int dith_dim =   4;	/* dimension of the dither matrix	*/
Xstatic int dith_dm2 =  16;	/* dim square				*/
Xstatic int **dith_mat; 		/* the dithering matrix			*/
X
X/* COLOR():
X *	returns the index in the color table for the
X *      r, g, b values specified.
X */
X#define COLOR(r,g,b) (((r) * dith_ng + (g)) * dith_nb + (b))
X
X/* LEVELS():
X *	Returns the total number of levels after dithering.
X */
X#define LEVELS(s)     (dith_dm2 * ((s) - 1) + 1)
X
X/* DITHER():
X *	Returns the dithered color for a single primary.
X *      p = the input pixel
X *      d = entry in the dither matrix
X *      s = the number of levels of the primary
X *
X */
X#define DITHER(p,d,s) ((ubyte) ((LEVELS(s) * (p) + (d)) / (dith_dm2 * NS)))
X
X
X/* dith_value():
X *	Return the value of a dither matrix of size x size at x, y 
X *	[graphics gems, p. 714]
X */
Xstatic int
Xdith_value(y, x, size)
Xint y, x, size;
X{
X    register int d;
X
X    /*
X     * Think of d as the density. At every iteration, d is shifted
X     * left one and a new bit is put in the low bit based on x and y.
X     * If x is odd and y is even, or visa versa, then a bit is shifted in.
X     * This generates the checkerboard pattern seen in dithering.
X     * This quantity is shifted again and the low bit of y is added in.
X     * This whole thing interleaves a checkerboard pattern and y's bits
X     * which is what you want.
X     */
X    for (d = 0; size-- > 0; x >>= 1, y >>= 1)
X	d = (d << 2) | (((x & 1) ^ (y & 1)) << 1) | (y & 1);
X    return(d);
X} /* end dith_value */
X
X
X/* dith_matrix():
X *	Form the dithering matrix for the dimension specified
X *	(Scaled by NS)
X */
Xstatic void
Xdith_matrix(dim)
Xint dim;
X{
X    int x, y, *dat;
X
X    dith_dim = (1 << dim);
X    dith_dm2 = dith_dim * dith_dim;
X
X    dith_mat = (int **) malloc((dith_dim * sizeof(int *)) + /* pointers */
X			       (dith_dm2 * sizeof(int)));   /* data */
X
X    if (dith_mat == NULL) 
X	pm_error("out of memory");
X
X    dat =  (int *) &dith_mat[dith_dim];
X    for (y = 0; y < dith_dim; y++)
X	dith_mat[y] = &dat[y * dith_dim];
X
X    for (y = 0; y < dith_dim; y++) {
X	for (x = 0; x < dith_dim; x++) {
X	     dith_mat[y][x] = NS * dith_value(y, x, dim);
X#ifdef DEBUG
X	     (void) fprintf(stderr, "%4d ", dith_mat[y][x]);
X#endif
X	}
X#ifdef DEBUG
X	(void) fprintf(stderr, "\n");
X#endif
X    }
X} /* end dith_matrix */
X
X    
X/* dith_setup():
X *	Setup the dithering parameters, lookup table and dithering matrix
X */
Xvoid
Xdith_setup(dim, nr, ng, nb, ptab)
Xint dim, nr, ng, nb;
Xpixel *ptab;
X{
X    register int r, g, b, i;
X
X    dith_nr  = nr;
X    dith_ng  = ng;
X    dith_nb  = nb;
X    dith_nc  = nr * ng * nb;
X
X    if (dith_nc > NC)
X	pm_error("too many shades %d, max %d", dith_nc, NC);
X    if (dith_nr < 2) 
X	pm_error("too few shades for red, minimum of 2");
X    if (dith_ng < 2) 
X	pm_error("too few shades for green, minimum of 2");
X    if (dith_nb < 2) 
X	pm_error("too few shades for blue, minimum of 2");
X    
X    for (r = 0; r < dith_nr; r++) 
X	for (g = 0; g < dith_ng; g++) 
X	    for (b = 0; b < dith_nb; b++) {
X		i = COLOR(r,g,b);
X		PPM_ASSIGN(ptab[COLOR(r,g,b)], 
X		           (r * (NC-1) / (dith_nr - 1)),
X		           (g * (NC-1) / (dith_ng - 1)),
X		           (b * (NC-1) / (dith_nb - 1)));
X	    }
X    
X    dith_matrix(dim);
X} /* end dith_setup */
X
X
X/* dith_color():
X *  Return the closest color index for the one we ask
X */
Xint
Xdith_color(r, g, b)
Xfloat r, g, b;
X{
X    int rr, gg, bb;
X
X    rr = r * (dith_nr - 1);
X    gg = g * (dith_ng - 1);
X    bb = b * (dith_nb - 1);
X    return((int) COLOR(rr, gg, bb));
X} /* end dith_color */
X
X
X/* dith_dither():
X *  Dither height scanlines at a time
X */
Xvoid
Xdith_dither(w, h, t, i, o)
Xint w, h;
Xregister pixel *t;
Xregister pixel *i;
Xregister pixel *o;
X{
X    int y, dm = (dith_dim - 1);
X    register int x, d;
X    register int *m;
X
X    for (y = 0; y < h; y++)
X	for (m = dith_mat[y & dm], x = w; --x >= 0;i++) {
X	    d = m[x & dm];
X	    *o++ = t[COLOR(DITHER(PPM_GETR(*i), d, dith_nr), 
X		           DITHER(PPM_GETG(*i), d, dith_ng), 
X		           DITHER(PPM_GETB(*i), d, dith_nb))];
X	}
X} /* end dith_dither */
X
X
Xvoid
Xmain( argc, argv )
X    int argc;
X    char* argv[];
X    {
X    FILE* ifp;
X    pixel ptab[256];
X    pixel **ipixels, **opixels;
X    int cols, rows;
X    pixval maxval;
X    int argn;
X    char* usage = 
X	"[-dim <num>] [-red <num>] [-green <num>] [-blue <num>] [pbmfile]";
X
X    ppm_init( &argc, argv );
X
X    argn = 1;
X
X    while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
X	{
X	if ( pm_keymatch( argv[argn], "-dim", 1) &&  argn + 1 < argc ) {
X	    argn++;
X	    if (sscanf(argv[argn], "%d", &dith_dim) != 1)
X		pm_usage( usage );
X	}
X	else if ( pm_keymatch( argv[argn], "-red", 1 ) && argn + 1 < argc ) {
X	    argn++;
X	    if (sscanf(argv[argn], "%d", &dith_nr) != 1)
X		pm_usage( usage );
X	}
X	else if ( pm_keymatch( argv[argn], "-green", 1 ) && argn + 1 < argc ) {
X	    argn++;
X	    if (sscanf(argv[argn], "%d", &dith_ng) != 1)
X		pm_usage( usage );
X	}
X	else if ( pm_keymatch( argv[argn], "-blue", 1 ) && argn + 1 < argc ) {
X	    argn++;
X	    if (sscanf(argv[argn], "%d", &dith_nb) != 1)
X		pm_usage( usage );
X	}
X	else
X	    pm_usage( usage );
X	++argn;
X	}
X
X    if ( argn != argc )
X	{
X	ifp = pm_openr( argv[argn] );
X	++argn;
X	}
X    else
X	ifp = stdin;
X
X    if ( argn != argc )
X	pm_usage( usage );
X
X    ipixels = ppm_readppm( ifp, &cols, &rows, &maxval );
X    pm_close( ifp );
X    opixels = ppm_allocarray(cols, rows);
X    maxval = 255;
X    dith_setup(dith_dim, dith_nr, dith_ng, dith_nb, ptab);
X    dith_dither(cols, rows, ptab, &ipixels[0][0], &opixels[0][0]);
X    ppm_writeppm(stdout, opixels, cols, rows, maxval, 0);
X    exit(0);
X}
SHAR_EOF
if test 6521 -ne "`wc -c < 'ppm/ppmdither.c'`"
then
	echo shar: error transmitting "'ppm/ppmdither.c'" '(should have been 6521 characters)'
fi
fi # end of overwriting check
if test ! -d 'ppm'
then
	echo shar: creating directory "'ppm'"
	mkdir 'ppm'
fi
echo shar: extracting "'ppm/ppmdither.1'" '(1557 characters)'
if test -f 'ppm/ppmdither.1'
then
	echo shar: will not over-write existing file "'ppm/ppmdither.1'"
else
sed 's/^X//' << \SHAR_EOF > 'ppm/ppmdither.1'
X.TH ppmdither 1 "14 July 1991"
X.IX ppmdither
X.SH NAME
Xppmdither - ordered dither for color images
X.SH SYNOPSIS
X.B ppmdither
X.RB [ -dim
X.IR dimension ]
X.RB [ -red
X.IR shades ]
X.RB [ -green
X.IR shades ]
X.RB [ -blue
X.IR shades ]
X.RI [ ppmfile ]
X.SH DESCRIPTION
XReads a portable pixmap as input, and applies dithering to it to reduce
Xthe number of colors used down to the specified number of shades for
Xeach primary.
XThe default number of shades is red=5, green=9, blue=5, for
Xa total of 225 colors.
XTo convert the image to a binary rgb format 
Xsuitable for color printers, use -red 2 -green 2 -blue 2.
XThe maximum
Xnumber of colors that can be used is 256 and can be computed as the 
Xproduct of the number of red, green and blue shades.
X.SH OPTIONS
X.TP 14
X.BI -dim " dimension"
XThe size of the dithering matrix.
XMust be a power of 2.
X.TP 14
X.BI -red " shades"
XThe number of red shades to be used; minimum of 2.
X.TP 14
X.BI -green " shades"
XThe number of green shades to be used; minimum of 2.
X.TP 14
X.BI -blue " shades"
XThe number of blue shades to be used; minimum of 2.
X.SH "SEE ALSO"
Xpnmdepth(1), ppmquant(1), ppm(5)
X.SH AUTHOR
XCopyright (C) 1991 by Christos Zoulas.
X.\" Permission to use, copy, modify, and distribute this software and its
X.\" documentation for any purpose and without fee is hereby granted, provided
X.\" that the above copyright notice appear in all copies and that both that
X.\" copyright notice and this permission notice appear in supporting
X.\" documentation.  This software is provided "as is" without express or
X.\" implied warranty.
SHAR_EOF
if test 1557 -ne "`wc -c < 'ppm/ppmdither.1'`"
then
	echo shar: error transmitting "'ppm/ppmdither.1'" '(should have been 1557 characters)'
fi
fi # end of overwriting check
if test ! -d 'ppm'
then
	echo shar: creating directory "'ppm'"
	mkdir 'ppm'
fi
echo shar: extracting "'ppm/ppmtotga.c'" '(8560 characters)'
if test -f 'ppm/ppmtotga.c'
then
	echo shar: will not over-write existing file "'ppm/ppmtotga.c'"
else
sed 's/^X//' << \SHAR_EOF > 'ppm/ppmtotga.c'
X/* ppmtotga.c - read a portable pixmap and produce a TrueVision Targa file
X**
X** Copyright (C) 1991 by Mark Shand
X**
X** Permission to use, copy, modify, and distribute this software and its
X** documentation for any purpose and without fee is hereby granted, provided
X** that the above copyright notice appear in all copies and that both that
X** copyright notice and this permission notice appear in supporting
X** documentation.  This software is provided "as is" without express or
X** implied warranty.
X*/
X
X#include <ctype.h>
X#include "ppm.h"
X#include "ppmcmap.h"
X#include "tga.h"
X
X/* Max number of colors allowed in ppm input. */
X#define MAXCOLORS 256
X
Xvoid
Xmain( argc, argv )
X    int argc;
X    char* argv[];
X    {
X    FILE* ifp;
X    pixel** pixels;
X    register pixel* pP;
X    int argn, rows, cols, ncolors, row, col, i, format, realrow;
X    pixval maxval;
X    colorhash_table cht;
X    colorhist_vector chv;
X    char out_name[100];
X    char* cp;
X    char* usage = "[-name <tganame>] [-mono|-cmap|-rgb] [ppmfile]";
X    struct ImageHeader tgaHeader;
X
X    ppm_init( &argc, argv );
X    out_name[0] = '\0';
X
X    argn = 1;
X
X    tgaHeader.ImgType = TGA_Null;
X    /* Check for command line options. */
X    while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
X        {
X        if ( pm_keymatch( argv[argn], "-name", 2 ) )
X            {
X            ++argn;
X            if ( argn == argc )
X        	pm_usage( usage );
X            (void) strcpy( out_name, argv[argn] );
X            }
X        else if ( pm_keymatch( argv[argn], "-cmap", 2 ) )
X            tgaHeader.ImgType = TGA_Map;
X        else if ( pm_keymatch( argv[argn], "-mono", 2 ) )
X            tgaHeader.ImgType = TGA_Mono;
X        else if ( pm_keymatch( argv[argn], "-rgb", 2 ) )
X            tgaHeader.ImgType = TGA_RGB;
X        else
X            pm_usage( usage );
X        ++argn;
X        }
X
X    if ( argn != argc )
X        {
X        /* Open the input file. */
X        ifp = pm_openr( argv[argn] );
X
X        /* If output filename not specified, use input filename as default. */
X        if ( out_name[0] == '\0' )
X            {
X            (void) strcpy( out_name, argv[argn] );
X            cp = index( out_name, '.' );
X            if ( cp != 0 )
X        	*cp = '\0';	/* remove extension */
X            if ( strcmp( out_name, "-" ) == 0 )
X        	(void) strcpy( out_name, "noname" );
X            }
X
X        ++argn;
X        }
X    else
X        {
X        /* No input file specified. */
X        ifp = stdin;
X        if ( out_name[0] == '\0' )
X            (void) strcpy( out_name, "noname" );
X        }
X
X    if ( argn != argc )
X        pm_usage( usage );
X
X    /* Read in the ppm file. */
X    ppm_readppminit( ifp, &cols, &rows, &maxval, &format);
X    pixels = ppm_allocarray(cols, rows);
X    for (row = 0; row < rows; row++)
X	ppm_readppmrow(ifp, pixels[row], cols, maxval, format);
X    pm_close( ifp );
X
X    /* Figure out the colormap. */
X    switch (PPM_FORMAT_TYPE(format))
X    {
X        case PPM_TYPE:
X            if (tgaHeader.ImgType == TGA_Mono)
X                pm_error("input not a graymap, filter through ppmtopgm first");
X            if (tgaHeader.ImgType == TGA_Null || tgaHeader.ImgType == TGA_Map)
X            {
X                pm_message( "computing colormap..." );
X                chv = ppm_computecolorhist( pixels, cols, rows, MAXCOLORS, &ncolors );
X                if ( chv == (colorhist_vector) 0 )
X                {
X                    if (tgaHeader.ImgType == TGA_Map)
X                        pm_error(
X                            "too many colors - try doing a 'ppmquant %d'",
X                            MAXCOLORS);
X                    else
X                        tgaHeader.ImgType = TGA_RGB;
X                }
X                else
X                {
X                    pm_message( "%d colors found", ncolors );
X                    if (tgaHeader.ImgType == TGA_Null)
X                        tgaHeader.ImgType = TGA_Map;
X                }
X            }
X            break;
X        case PGM_TYPE:
X        case PBM_TYPE:
X            if (tgaHeader.ImgType == TGA_Null)
X                tgaHeader.ImgType = TGA_Mono;
X            else if (tgaHeader.ImgType == TGA_Map)
X            {
X                pm_message( "computing colormap..." );
X                chv = ppm_computecolorhist( pixels, cols, rows, MAXCOLORS, &ncolors );
X                if ( chv == (colorhist_vector) 0 )
X                    pm_error("can't happen");
X                pm_message( "%d colors found", ncolors );
X            }
X            break;
X
X        default:
X            pm_error( "can't happen");
X    }
X
X    tgaHeader.IDLength = 0;
X    
X    if (tgaHeader.ImgType == TGA_Map)
X    {
X        /* Make a hash table for fast color lookup. */
X        cht = ppm_colorhisttocolorhash( chv, ncolors );
X
X        tgaHeader.CoMapType = 1;
X        tgaHeader.Index_lo = 0;
X        tgaHeader.Index_hi = 0;
X        tgaHeader.Length_lo = ncolors%256;
X        tgaHeader.Length_hi = ncolors/256;
X        tgaHeader.CoSize = 24;
X        tgaHeader.PixelSize = 8;
X    }
X    else
X    {
X        tgaHeader.CoMapType = 0;
X        tgaHeader.Index_lo = 0;
X        tgaHeader.Index_hi = 0;
X        tgaHeader.Length_lo = 0;
X        tgaHeader.Length_hi = 0;
X        tgaHeader.CoSize = 0;
X        tgaHeader.PixelSize = (tgaHeader.ImgType == TGA_RGB) ? 24 : 8;
X    }
X    tgaHeader.X_org_lo = tgaHeader.X_org_hi = 0;
X    tgaHeader.Y_org_lo = tgaHeader.Y_org_hi = 0;
X    tgaHeader.Width_lo = cols%256; tgaHeader.Width_hi = cols/256;
X    tgaHeader.Height_lo = rows%256; tgaHeader.Height_hi = rows/256;
X    tgaHeader.AttBits = 0;
X    tgaHeader.Rsrvd = 0;
X    tgaHeader.IntrLve = 0;
X
X    /* Write out the TGA header. */
X    writetga(&tgaHeader, NULL);
X
X    if (tgaHeader.ImgType == TGA_Map)
X    {
X        /* Write out the TGA colormap. */
X        for (i = 0; i < ncolors; i++)
X            put_map_entry(chv[i].color, tgaHeader.CoSize, maxval);
X    }
X
X    /* Write out the pixels */
X    for ( row = 0; row < rows; ++row )
X        {
X            realrow = row;
X            if ( tgaHeader.OrgBit == 0 )
X                realrow = rows - realrow - 1;
X            if (tgaHeader.ImgType == TGA_Map)
X                for ( col = 0; col < cols; col++ )
X                    putchar(ppm_lookupcolor(cht, pixels[realrow]+col));
X            else if (tgaHeader.ImgType == TGA_Mono)
X                for ( col = 0; col < cols; col++ )
X                {
X                    pixel sP;
X                    PPM_DEPTH(sP, pixels[realrow][col], maxval, (pixval) 255);
X                    putchar((int) PPM_LUMIN(sP));
X                }
X            else if (tgaHeader.ImgType == TGA_RGB)
X                for ( col = 0; col < cols; col++ )
X                {
X                    pixel sP;
X                    PPM_DEPTH(sP, pixels[realrow][col], maxval, (pixval) 255);
X                    putchar(PPM_GETB(sP));
X                    putchar(PPM_GETG(sP));
X                    putchar(PPM_GETR(sP));
X                }
X        }
X    exit( 0 );
X    }
X
Xwritetga( tgaP, id)
Xstruct ImageHeader *tgaP;
Xchar *id;
X{
X    unsigned char flags;
X
X    putchar(tgaP->IDLength);
X    putchar(tgaP->CoMapType);
X    putchar(tgaP->ImgType);
X    putchar(tgaP->Index_lo);
X    putchar(tgaP->Index_hi);
X    putchar(tgaP->Length_lo);
X    putchar(tgaP->Length_hi);
X    putchar(tgaP->CoSize);
X    putchar(tgaP->X_org_lo);
X    putchar(tgaP->X_org_hi);
X    putchar(tgaP->Y_org_lo);
X    putchar(tgaP->Y_org_hi);
X    putchar(tgaP->Width_lo);
X    putchar(tgaP->Width_hi);
X    putchar(tgaP->Height_lo);
X    putchar(tgaP->Height_hi);
X    putchar(tgaP->PixelSize);
X    flags = (tgaP->AttBits & 0xf)
X            | ((tgaP->Rsrvd & 0x1) << 4)
X            | ((tgaP->OrgBit & 0x1) << 5)
X            | ((tgaP->OrgBit & 0x3) << 6);
X    putchar(flags);
X    if (tgaP->IDLength)
X        fwrite( id, 1, (int) tgaP->IDLength, stdout);
X}
X    
Xput_map_entry(Value, Size, maxval) 
Xpixel Value;
Xint Size;
Xpixval maxval;
X{
X    int j;
X    pixel sP;
X    
X    switch ( Size )
X    {
X	case 8:				/* Grey scale. */
X	
X	PPM_DEPTH(sP, Value, maxval, (pixval) 255);
X        putchar((int) PPM_LUMIN(sP));
X	break;
X
X	case 16:			/* 5 bits each of red green and blue. */
X	case 15:			/* Watch for byte order. */
X	PPM_DEPTH(sP, Value, maxval, 31);
X	j = (int) PPM_GETB(sP)
X	  | ((int) PPM_GETG(sP) << 5)
X	  | ((int) PPM_GETR(sP) << 10);
X	putchar(j%256);
X	putchar(j/256);
X	break;
X
X	case 32:
X	case 24:			/* 8 bits each of blue green and red. */
X	PPM_DEPTH(sP, Value, maxval, (pixval) 255);
X	putchar(PPM_GETB(sP));
X	putchar(PPM_GETG(sP));
X	putchar(PPM_GETR(sP));
X	break;
X
X	default:
X	pm_error( "unknown colormap pixel size (#2) - %d", Size );
X    }
X}
SHAR_EOF
if test 8560 -ne "`wc -c < 'ppm/ppmtotga.c'`"
then
	echo shar: error transmitting "'ppm/ppmtotga.c'" '(should have been 8560 characters)'
fi
fi # end of overwriting check
if test ! -d 'ppm'
then
	echo shar: creating directory "'ppm'"
	mkdir 'ppm'
fi
echo shar: extracting "'ppm/ppmtotga.1'" '(1472 characters)'
if test -f 'ppm/ppmtotga.1'
then
	echo shar: will not over-write existing file "'ppm/ppmtotga.1'"
else
sed 's/^X//' << \SHAR_EOF > 'ppm/ppmtotga.1'
X.TH ppmtotga 1 "26 August 1989"
X.IX ppmtotga
X.SH NAME
Xppmtotga - convert portable pixmap into a TrueVision Targa file
X.SH SYNOPSIS
X.B ppmtotga
X.RB [ -mono|-cmap|-rgb ]
X.RI [ ppmfile ]
X.SH DESCRIPTION
XReads a portable pixmap as input.
XProduces a TrueVision Targa file as output.
X.SH OPTIONS
X.TP
X.B -mono
XForces Targa file to be of type 8 bit monochrome.  Input must be a portable
Xbitmap or a portable graymap.
X.TP
X.B -cmap
XForces Targa file to be of type 24 bit colormapped.  Input must be a portable
Xbitmap, a portable graymap or a portable pixmap containing no more than
X256 distinct colors.
X.TP
X.B -rgb
XForces Targa file to be of type 24 bit unmapped color.
X.PP
XAll flags can be abbreviated to their shortest unique prefix.  If no
Xfile type is specified the most highly constained compatible type is
Xused, where monochrome is more constained than colormapped which is in
Xturn more constained than unmapped.
X.SH BUGS
XDoes not support all possible Targa file types.
XShould really be in PNM, not PPM.
X.SH "SEE ALSO"
Xtgatoppm(1), ppm(5)
X.SH AUTHOR
XCopyright (C) 1991 by Mark Shand.
X.\" Permission to use, copy, modify, and distribute this software and its
X.\" documentation for any purpose and without fee is hereby granted, provided
X.\" that the above copyright notice appear in all copies and that both that
X.\" copyright notice and this permission notice appear in supporting
X.\" documentation.  This software is provided "as is" without express or
X.\" implied warranty.
SHAR_EOF
if test 1472 -ne "`wc -c < 'ppm/ppmtotga.1'`"
then
	echo shar: error transmitting "'ppm/ppmtotga.1'" '(should have been 1472 characters)'
fi
fi # end of overwriting check
if test ! -d 'ppm'
then
	echo shar: creating directory "'ppm'"
	mkdir 'ppm'
fi
echo shar: extracting "'ppm/ppmtosixel.c'" '(4973 characters)'
if test -f 'ppm/ppmtosixel.c'
then
	echo shar: will not over-write existing file "'ppm/ppmtosixel.c'"
else
sed 's/^X//' << \SHAR_EOF > 'ppm/ppmtosixel.c'
X/* ppmtosix.c - read a portable pixmap and produce a color sixel file
X**
X** Copyright (C) 1991 by Rick Vinci.
X**
X** Permission to use, copy, modify, and distribute this software and its
X** documentation for any purpose and without fee is hereby granted, provided
X** that the above copyright notice appear in all copies and that both that
X** copyright notice and this permission notice appear in supporting
X** documentation.  This software is provided "as is" without express or
X** implied warranty.
X*/
X
X#include "ppm.h"
X#include "ppmcmap.h"
X
X#define MAXVAL 100
X#define MAXCOLORS 256
X
X#define DCS '\x90'   /* Device Control String */
X#define ST  '\x9c'   /* String Terminator */
X#define CSI '\x9b'   /* Control String Introducer */
X#define ESC '\x1b'   /* Escape character */
X
Xstatic pixel** pixels;   /* stored ppm pixmap input */
Xstatic colorhash_table cht;
Xint margin;
X
Xvoid
Xmain( argc, argv )
X    int argc;
X    char* argv[];
X    {
X    FILE* ifp;
X    int argn, rows, cols, colors;
X    int Red, Grn, Blue, rownum, colnum;
X    int raw;
X    pixval maxval;
X    colorhist_vector chv;
X    char* usage = "[-raw] [-margin] [ppmfile]";
X
X    ppm_init( &argc, argv );
X
X    argn = 1;
X    raw = 0;
X    margin = 0;
X
X    /* Parse args. */
X    while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
X	{
X	if ( pm_keymatch( argv[argn], "-raw", 2 ) )
X	    raw = 1;
X	else if ( pm_keymatch( argv[argn], "-margin", 2 ) )
X	    margin = 1;
X	else
X	    pm_usage( usage );
X	++argn;
X	}
X
X    if ( argn < argc )
X	{
X	ifp = pm_openr( argv[argn] );
X	++argn;
X	}
X    else
X	ifp = stdin;
X
X    if ( argn != argc )
X	pm_usage( usage );
X
X    /* Read in the whole ppmfile. */
X    pixels = ppm_readppm( ifp, &cols, &rows, &maxval );
X    pm_close( ifp );
X
X    /* Print a warning if we're could to lose accuracy when rescaling colors. */
X    if ( maxval > MAXVAL )
X	pm_message(
X	    "maxval is not %d - automatically rescaling colors", MAXVAL );
X
X    /* Figure out the colormap. */
X    pm_message( "computing colormap..." );
X    chv = ppm_computecolorhist( pixels, cols, rows, MAXCOLORS, &colors );
X    if ( chv == (colorhist_vector) 0 )
X	pm_error( "too many colors - try doing a 'ppmquant %d'", MAXCOLORS );
X    pm_message( "%d colors found", colors );
X
X    /* Make a hash table for fast color lookup. */
X    cht = ppm_colorhisttocolorhash( chv, colors );
X
X    pm_message( "delivering sixel image..." );
X    WriteHeader();
X    WriteColorMap( chv, colors, maxval );
X    if ( raw == 1 )
X	WriteRawImage( cht, rows, cols );
X    else
X	WritePackedImage( cht, rows, cols );
X    WriteEnd();
X
X    exit( 0 );
X    }
X
X
Xint
XWriteHeader()
X    {
X    if ( margin == 1 )
X	printf( "%c%d;%ds", CSI, 14, 72 );
X    printf( "%c", DCS );  /* start with Device Control String */
X    printf( "0;0;8q" );   /* Horizontal Grid Size at 1/90" and graphics On */
X    printf( "\"1;1\n" );  /* set aspect ratio 1:1 */
X    }
X
Xint
XWriteColorMap( chv, colors, maxval )
X    colorhist_vector chv;
X    int colors;
X    pixval maxval;
X    {
X    register int colornum;
X    pixel p;
X
X    for ( colornum = 0; colornum < colors ; ++colornum )
X	{
X	p = chv[colornum].color;
X	if ( maxval != MAXVAL )
X	    PPM_DEPTH( p, p, maxval, MAXVAL );
X	printf( "#%d;2;%d;%d;%d", colornum,
X	    (int) PPM_GETR( p ), (int) PPM_GETG( p ), (int) PPM_GETB( p ) );
X	}
X    printf( "\n" );
X    }
X
Xint
XWriteRawImage( cht, rows, cols )
X    colorhash_table cht;
X    int rows, cols;
X    {
X    int rownum, colnum, b;
X    char* sixel = "@ACGO_";
X    register pixel* pP;
X
X    for ( rownum = 0; rownum < rows; ++rownum )
X	{
X	b = rownum % 6;
X	for ( colnum = 0, pP = pixels[rownum]; colnum < cols; ++colnum, ++pP )
X	    printf( "#%d%c", ppm_lookupcolor(cht, pP), sixel[b] );
X	printf( "$\n" );   /* Carriage Return */
X	if ( b == 5 )
X	    printf( "-\n" );   /* Line Feed (one sixel height) */
X	}
X    }
X
Xint
XWritePackedImage( cht, rows, cols )
X    colorhash_table cht;
X    int rows, cols;
X    {
X    int rownum, colnum, b, repeat, thiscolor, nextcolor;
X    char* sixel = "@ACGO_";
X    register pixel* pP;
X
X    for ( rownum = 0; rownum < rows; ++rownum )
X	{
X	b = rownum % 6;
X	repeat = 1;
X	for ( colnum = 0, pP = pixels[rownum]; colnum < cols; ++colnum, ++pP )
X	    {
X	    thiscolor = ppm_lookupcolor(cht, pP);
X	    if ( colnum == cols -1 )   /* last pixel in row */
X		if ( repeat == 1 )
X		    printf( "#%d%c", thiscolor, sixel[b] );
X		else
X		    printf( "#%d!%d%c", thiscolor, repeat, sixel[b] );
X	    else   /* not last pixel in row */
X		{
X		nextcolor =  ppm_lookupcolor(cht, pP+1);
X		if ( thiscolor == nextcolor )
X		    ++repeat;
X		else
X		    if ( repeat == 1 )
X			printf( "#%d%c", thiscolor, sixel[b] );
X		    else
X		    {
X		    printf( "#%d!%d%c", thiscolor, repeat, sixel[b] );
X		    repeat = 1;
X		    }
X		}
X	    }   /* end column loop */
X	printf( "$\n" );   /* Carriage Return */
X	if ( b == 5 )
X	    printf( "-\n" );   /* Line Feed (one sixel height) */
X	}
X    }
X
Xint
XWriteEnd()
X    {
X    if ( margin == 1 )
X	printf ( "%c%d;%ds", CSI, 1, 80 );
X    printf( "%c\n", ST );
X    }
SHAR_EOF
if test 4973 -ne "`wc -c < 'ppm/ppmtosixel.c'`"
then
	echo shar: error transmitting "'ppm/ppmtosixel.c'" '(should have been 4973 characters)'
fi
fi # end of overwriting check
if test ! -d 'ppm'
then
	echo shar: creating directory "'ppm'"
	mkdir 'ppm'
fi
echo shar: extracting "'ppm/ppmtosixel.1'" '(2147 characters)'
if test -f 'ppm/ppmtosixel.1'
then
	echo shar: will not over-write existing file "'ppm/ppmtosixel.1'"
else
sed 's/^X//' << \SHAR_EOF > 'ppm/ppmtosixel.1'
X.TH ppmtosixel 1 "26 April 1991"
X.IX ppmtosixel
X.SH NAME
Xppmtosixel - convert a portable pixmap into DEC sixel format
X.SH SYNOPSIS
X.B ppmtosixel
X.RB [ -raw ]
X.RB [ -margin ]
X.RI [ ppmfile ]
X.SH DESCRIPTION
XReads a portable pixmap as input.
XProduces sixel commands (SIX) as output.
XThe output is formatted for color printing, e.g. for a DEC LJ250 color
Xinkjet printer. 
X.PP
XIf RGB values from the PPM file do not have maxval=100,
Xthe RGB values are rescaled.
XA printer control header and a color assignment table begin the SIX file.
XImage data is written in a compressed format by default.
XA printer control footer ends the image file.
X.SH OPTIONS
X.TP
X.B -raw
XIf specified, each pixel will be explicitly described in the image file.
XIf
X.B -raw
Xis not specified, output will default to compressed format in which
Xidentical adjacent pixels are replaced by "repeat pixel" commands.
XA raw file is often an order of magnitude larger than a compressed
Xfile and prints much slower.
X.TP
X.B -margin
XIf
X.B -margin
Xis not specified, the image will be start at the left margin
X(of the window, paper, or whatever).
XIf
X.B -margin
Xis specified, a 1.5 inch left margin will offset the image.
X.SH PRINTING
XGenerally, sixel files must reach the printer unfiltered.
XUse the lpr -x option or cat filename > /dev/tty0?.
X.SH BUGS
XUpon rescaling, truncation of the least significant bits of RGB values
Xmay result in poor color conversion.
XIf the original PPM maxval was greater than 100, rescaling also
Xreduces the image depth.
XWhile the actual RGB values from the ppm file are more or less
Xretained, the color palette of the LJ250 may not match the colors
Xon your screen.
XThis seems to be a printer limitation.
X.SH "SEE ALSO"
Xppm(5)
X.SH AUTHOR
XCopyright (C) 1991 by Rick Vinci.
X.\" Permission to use, copy, modify, and distribute this software and its
X.\" documentation for any purpose and without fee is hereby granted, provided
X.\" that the above copyright notice appear in all copies and that both that
X.\" copyright notice and this permission notice appear in supporting
X.\" documentation.  This software is provided "as is" without express or
X.\" implied warranty.
SHAR_EOF
if test 2147 -ne "`wc -c < 'ppm/ppmtosixel.1'`"
then
	echo shar: error transmitting "'ppm/ppmtosixel.1'" '(should have been 2147 characters)'
fi
fi # end of overwriting check
if test ! -d 'ppm'
then
	echo shar: creating directory "'ppm'"
	mkdir 'ppm'
fi
echo shar: extracting "'ppm/ppmtoyuv.c'" '(2365 characters)'
if test -f 'ppm/ppmtoyuv.c'
then
	echo shar: will not over-write existing file "'ppm/ppmtoyuv.c'"
else
sed 's/^X//' << \SHAR_EOF > 'ppm/ppmtoyuv.c'
X/* ppmtoyuv.c - convert a portable pixmap into an Abekas YUV file
X**
X** by Marc Boucher
X** Internet: marc@PostImage.COM
X** 
X** Based on Example Conversion Program, A60/A64 Digital Video Interface
X** Manual, page 69.
X**
X** Copyright (C) 1991 by DHD PostImage Inc.
X** Copyright (C) 1987 by Abekas Video Systems Inc.
X**
X** Permission to use, copy, modify, and distribute this software and its
X** documentation for any purpose and without fee is hereby granted, provided
X** that the above copyright notice appear in all copies and that both that
X** copyright notice and this permission notice appear in supporting
X** documentation.  This software is provided "as is" without express or
X** implied warranty.
X*/
X
X#include "ppm.h"
X
Xvoid
Xmain(argc, argv)
Xchar **argv;
X{
X	FILE *ifp;
X	pixel          *pixelrow;
X	register pixel *pP;
X	int             rows, cols, format, row;
X	register int    col;
X	pixval          maxval;
X	unsigned long   y1, y2=0, u=0, v=0, u0=0, u1, u2, v0=0, v1, v2;
X	unsigned char  *yuvbuf;
X
X	ppm_init(&argc, argv);
X
X	if (argc > 2) pm_usage("[ppmfile]");
X
X	if (argc == 2) ifp = pm_openr(argv[1]);
X	else ifp = stdin;
X
X	ppm_readppminit(ifp, &cols, &rows, &maxval, &format);
X	pixelrow = ((pixel*) pm_allocrow( cols, sizeof(pixel) ));
X	yuvbuf = (unsigned char *) pm_allocrow( cols, 2 );
X
X	for (row = 0; row < rows; ++row) {
X		unsigned char *yuvptr;
X
X		ppm_readppmrow(ifp, pixelrow, cols, maxval, format);
X
X		for (col = 0, pP = pixelrow, yuvptr=yuvbuf; col < cols; col += 2, ++pP) {
X			pixval r, g, b;
X
X			/* first pixel gives Y and 0.5 of chroma */
X			r = PPM_GETR(*pP);
X			g = PPM_GETG(*pP);
X			b = PPM_GETB(*pP);
X
X			y1 = 16829 * r + 33039 * g + 6416 * b + (0xffff & y2);
X			u1 = -4853 * r - 9530 * g + 14383 * b;
X			v1 = 14386 * r - 12046 * g - 2340 * b;
X
X			pP++;
X			/* second pixel just yields a Y and 0.25 U, 0.25 V */
X			r = PPM_GETR(*pP);
X			g = PPM_GETG(*pP);
X			b = PPM_GETB(*pP);
X
X			y2 = 16829 * r + 33039 * g + 6416 * b + (0xffff & y1);
X			u2 = -2426 * r - 4765 * g + 7191 * b;
X			v2 = 7193 * r - 6023 * g - 1170 * b;
X
X			/* filter the chroma */
X			u = u0 + u1 + u2 + (0xffff & u);
X			v = v0 + v1 + v2 + (0xffff & v);
X
X			u0 = u2;
X			v0 = v2;
X
X			*yuvptr++ = (u >> 16) + 128;
X			*yuvptr++ = (y1 >> 16) + 16;
X			*yuvptr++ = (v >> 16) + 128;
X			*yuvptr++ = (y2 >> 16) + 16;
X		}
X		fwrite(yuvbuf, cols*2, 1, stdout);
X	}
X
X	pm_close(ifp);
X
X	exit(0);
X}
SHAR_EOF
if test 2365 -ne "`wc -c < 'ppm/ppmtoyuv.c'`"
then
	echo shar: error transmitting "'ppm/ppmtoyuv.c'" '(should have been 2365 characters)'
fi
fi # end of overwriting check
if test ! -d 'ppm'
then
	echo shar: creating directory "'ppm'"
	mkdir 'ppm'
fi
echo shar: extracting "'ppm/ppmtoyuv.1'" '(909 characters)'
if test -f 'ppm/ppmtoyuv.1'
then
	echo shar: will not over-write existing file "'ppm/ppmtoyuv.1'"
else
sed 's/^X//' << \SHAR_EOF > 'ppm/ppmtoyuv.1'
X.TH ppmtoyuv 1 "25 March 91"
X.IX ppmtoyuv
X.SH NAME
Xppmtoyuv - convert a portable pixmap into an Abekas YUV file
X.SH SYNOPSIS
X.B ppmtoyuv
X.RI [ ppmfile ]
X.SH DESCRIPTION
XReads a portable pixmap as input.
XProduces an Abekas YUV file as output.
X.IX Abekas
X.SH "SEE ALSO"
Xyuvtoppm(1), ppm(5)
X.SH AUTHOR
XMarc Boucher <marc@PostImage.COM>,
Xbased on Example Conversion Program, A60/A64 Digital Video Interface
XManual, page 69.
X.PP
XCopyright (C) 1991 by DHD PostImage Inc.
X.PP
XCopyright (C) 1987 by Abekas Video Systems Inc.
X.\" Permission to use, copy, modify, and distribute this software and its
X.\" documentation for any purpose and without fee is hereby granted, provided
X.\" that the above copyright notice appear in all copies and that both that
X.\" copyright notice and this permission notice appear in supporting
X.\" documentation.  This software is provided "as is" without express or
X.\" implied warranty.
SHAR_EOF
if test 909 -ne "`wc -c < 'ppm/ppmtoyuv.1'`"
then
	echo shar: error transmitting "'ppm/ppmtoyuv.1'" '(should have been 909 characters)'
fi
fi # end of overwriting check
if test ! -d 'ppm'
then
	echo shar: creating directory "'ppm'"
	mkdir 'ppm'
fi
echo shar: extracting "'ppm/yuvtoppm.c'" '(2496 characters)'
if test -f 'ppm/yuvtoppm.c'
then
	echo shar: will not over-write existing file "'ppm/yuvtoppm.c'"
else
sed 's/^X//' << \SHAR_EOF > 'ppm/yuvtoppm.c'
X/* yuvtoppm.c - convert Abekas YUV bytes into a portable pixmap
X**
X** by Marc Boucher
X** Internet: marc@PostImage.COM
X** 
X** Based on Example Conversion Program, A60/A64 Digital Video Interface
X** Manual, page 69
X**
X** Uses integer arithmetic rather than floating point for better performance
X**
X** Copyright (C) 1991 by DHD PostImage Inc.
X** Copyright (C) 1987 by Abekas Video Systems Inc.
X** Copyright (C) 1991 by Jef Poskanzer.
X**
X** Permission to use, copy, modify, and distribute this software and its
X** documentation for any purpose and without fee is hereby granted, provided
X** that the above copyright notice appear in all copies and that both that
X** copyright notice and this permission notice appear in supporting
X** documentation.  This software is provided "as is" without express or
X** implied warranty.
X*/
X
X#include "ppm.h"
X
X/* x must be signed for the following to work correctly */
X#define limit(x) (((x>0xffffff)?0xff0000:((x<=0xffff)?0:x&0xff0000))>>16)
X
Xvoid
Xmain(argc, argv)
X	char          **argv;
X{
X	FILE           *ifp;
X	pixel          *pixrow;
X	int             argn, rows, cols, row, i;
X	char           *usage = "<width> <height> [yuvfile]";
X	long  *yuvbuf;
X
X	ppm_init(&argc, argv);
X
X	argn = 1;
X
X	if (argn + 2 > argc)
X		pm_usage(usage);
X
X	cols = atoi(argv[argn++]);
X	rows = atoi(argv[argn++]);
X	if (cols <= 0 || rows <= 0)
X		pm_usage(usage);
X
X	if (argn < argc) {
X		ifp = pm_openr(argv[argn]);
X		++argn;
X	} else
X		ifp = stdin;
X
X	if (argn != argc)
X		pm_usage(usage);
X
X	if (255 > PGM_MAXMAXVAL)
X		pm_error(
X      "maxval of 255 is too large - try recompiling with a larger pixval type");
X
X	ppm_writeppminit(stdout, cols, rows, (pixval) 255, 0);
X	pixrow = ppm_allocrow(cols);
X	yuvbuf = (long *) pm_allocrow(cols, 2);
X
X	for (row = 0; row < rows; ++row) {
X		long   tmp, y, u, v, y1, r, g, b, *yuvptr;
X		register pixel *pP;
X		register int    col;
X
X		fread(yuvbuf, cols * 2, 1, ifp);
X
X		for (col = 0, pP = pixrow, yuvptr = yuvbuf; col < cols; col += 2) {
X			tmp = *yuvptr++;
X			u = (0xff & (tmp >> 24)) - 128;
X			y = ((0xff & (tmp >> 16)) - 16);
X			if (y < 0) y = 0;
X
X			v = (0xff & (tmp >> 8)) - 128;
X			y1 = ((0xff & tmp) - 16);
X			if (y1 < 0) y1 = 0;
X
X			r = 104635 * v;
X			g = -25690 * u + -53294 * v;
X			b = 132278 * u;
X
X			y*=76310; y1*=76310;
X
X			PPM_ASSIGN(*pP, limit(r+y), limit(g+y), limit(b+y));
X			pP++;
X			PPM_ASSIGN(*pP, limit(r+y1), limit(g+y1), limit(b+y1));
X			pP++;
X		}
X		ppm_writeppmrow(stdout, pixrow, cols, (pixval) 255, 0);
X	}
X	pm_close(ifp);
X
X	exit(0);
X}
SHAR_EOF
if test 2496 -ne "`wc -c < 'ppm/yuvtoppm.c'`"
then
	echo shar: error transmitting "'ppm/yuvtoppm.c'" '(should have been 2496 characters)'
fi
fi # end of overwriting check
if test ! -d 'ppm'
then
	echo shar: creating directory "'ppm'"
	mkdir 'ppm'
fi
echo shar: extracting "'ppm/yuvtoppm.1'" '(1114 characters)'
if test -f 'ppm/yuvtoppm.1'
then
	echo shar: will not over-write existing file "'ppm/yuvtoppm.1'"
else
sed 's/^X//' << \SHAR_EOF > 'ppm/yuvtoppm.1'
X.TH yuvtoppm 1 "25 March 91"
X.IX yuvtoppm
X.SH NAME
Xyuvtoppm - convert Abekas YUV bytes into a portable pixmap
X.SH SYNOPSIS
X.B yuvtoppm
X.I width height
X.RI [ imagedata ]
X.SH DESCRIPTION
XReads raw Abekas YUV bytes as input.
X.IX Abekas
XProduces a portable pixmap as output.
XThe input file is just YUV bytes.
XYou have to specify the width and height on the command line,
Xsince the program obviously can't get them from the file.
XThe maxval is assumed to be 255.
X.SH "SEE ALSO"
Xppmtoyuv(1), ppm(5)
X.SH AUTHOR
XMarc Boucher <marc@PostImage.COM>,
Xbased on Example Conversion Program, A60/A64 Digital Video Interface
XManual, page 69.
X.PP
XCopyright (C) 1991 by DHD PostImage Inc.
X.PP
XCopyright (C) 1987 by Abekas Video Systems Inc.
X.\" Permission to use, copy, modify, and distribute this software and its
X.\" documentation for any purpose and without fee is hereby granted, provided
X.\" that the above copyright notice appear in all copies and that both that
X.\" copyright notice and this permission notice appear in supporting
X.\" documentation.  This software is provided "as is" without express or
X.\" implied warranty.
SHAR_EOF
if test 1114 -ne "`wc -c < 'ppm/yuvtoppm.1'`"
then
	echo shar: error transmitting "'ppm/yuvtoppm.1'" '(should have been 1114 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0

exit 0 # Just in case...
-- 
Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
Sterling Software, IMD           UUCP:     uunet!sparky!kent
Phone:    (402) 291-8300         FAX:      (402) 291-4362
Please send comp.sources.misc-related mail to kent@uunet.uu.net.
