[alt.sources] lineprinter art to graymap

ken@csis.dit.csiro.au (Ken Yap) (05/28/91)

I wrote this for fun a while back. It converts lineprinter art to
PBMPLUS graymaps. You need multipart and multistrike pictures to get
reasonable results. You also need the rest of the PBMPLUS distribution,
e.g. export.lcs.mit.edu:contrib is one archive site.

Take it for what it's worth and have fun.

#! /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:
#	lptopgm.1
#	lptopgm.c
# This archive created: Tue May 28 16:47:24 1991
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'lptopgm.1'" '(2148 characters)'
if test -f 'lptopgm.1'
then
	echo shar: "will not over-write existing file 'lptopgm.1'"
else
cat << \SHAR_EOF > 'lptopgm.1'
.TH LPTOPGM 1 "7 May 90"
.SH NAME
lptopgm - convert line printer picture into a portable graymap
.SH SYNOPSIS
lptopgm [lppic]
.SH DESCRIPTION
Reads a line printer picture as input.
Produces a portable graymap as output.
Overstruck lines created with carriage returns and/or backspaces
are handled correctly.
The gray values are based on a dot count of a typical dot matrix font.
.SH "EXAMPLE"
Best results are obtained from large, multiple strike pictures.
Small pictures will not have sufficient resolution and
single strike pictures will not have sufficient gray levels.
Conversion can be divided into three phases:
.PP
Initial preparation:
Multipart pictures must be divided into one file per part,
junk lines should be trimmed, tabs must be expanded,
and Fortran carriage control must be converted to the appropriate
sequence of newlines and carriage returns.
.I Lptopgm
also understands backspaces.
The only control characters not ignored are backspace,
newline and carriage return.
.PP
Conversion:
.B lptopgm
produces a graymap but this graymap needs
to be normalized and inverted (because pictures are black on white) so
run the result through
.B pgmnorm
and
.B pnminvert
also.
.PP
Final cleanup:
Put multi-part pictures back together with
.BR pnmcat .
Graymaps produced from line printer pictures
look compressed in the vertical direction because of the dimensions of the
characters in print chains. Run the picture through
.B pmscale
to expand the vertical scale. A ratio of 1.25 is about right.
.SH BUGS
If the picture has too many overstrikes, the gray value per cell
may exceed 255 and clipping at 255 will occur.
This has never happened with real pictures; the most I ever got
was a gray value of 129.
.SH "SEE ALSO"
pgm(5)
.SH AUTHOR
Copyright (C) 1990 by Ken Yap.

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.
SHAR_EOF
if test 2148 -ne "`wc -c < 'lptopgm.1'`"
then
	echo shar: "error transmitting 'lptopgm.1'" '(should have been 2148 characters)'
fi
fi
echo shar: "extracting 'lptopgm.c'" '(3374 characters)'
if test -f 'lptopgm.c'
then
	echo shar: "will not over-write existing file 'lptopgm.c'"
else
cat << \SHAR_EOF > 'lptopgm.c'
/* lptppgm.c - convert line printer picture into a portable graymap
**
** Copyright (C) 1990 by Ken Yap.
**
** 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 <stdio.h>
#include "pgm.h"
#ifdef SYSV
#include <string.h>
#else /*SYSV*/
#include <strings.h>
#endif /*SYSV*/

#define	TEMPLATE	"/tmp/lpXXXXXX"

char	grayvals[128] = {
	 0,  0,  0,  0,  0,  0,  0,  0,
	 0,  0,  0,  0,  0,  0,  0,  0,
	 0,  0,  0,  0,  0,  0,  0,  0,
	 0,  0,  0,  0,  0,  0,  0,  0,
	 0,  6,  6, 22, 19, 17, 15,  3,
	11, 11, 11,  9,  6,  5,  4, 10,
	16, 11, 15, 14, 18, 15, 15, 12,
	16, 15,  8, 10,  7,  8,  7,  9,
	19, 19, 21, 15, 20, 20, 17, 18,
	24, 16, 14, 20, 15, 24, 25, 20,
	18, 23, 20, 17, 16, 19, 17, 21,
	18, 17, 18, 15, 10, 15,  5,  5,
	 3, 13, 17, 10, 17, 13, 15, 18,
	19, 13, 12, 16, 14, 18, 16, 12,
	18, 18, 13, 12, 12, 15, 12, 17,
	14, 17, 14, 13, 10, 13,  7,  0
};

FILE *prepass(ifd, cols, rows)
FILE *ifd;
int *cols, *rows;
{
	register int c, col;
	register FILE *tfd;
	char tempname[sizeof(TEMPLATE)];
	char *mktemp();

	(void)strcpy(tempname, TEMPLATE);
	(void)mktemp(tempname);
	if ((tfd = fopen(tempname, "w+")) == NULL)
		return (NULL);
	(void)unlink(tempname);
	*rows = 0;
	*cols = 0;
	col = 0;
	while ((c = getc(ifd)) != EOF)
	{
		putc(c, tfd);
		c &= 0xff;
		switch (c)
		{
		case '\b':
			if (cols > 0)
				--cols;
			break;
		case '\n':
			++*rows;
			if (col > *cols)
				*cols = col;
			col = 0;
			break;
		case '\r':
			if (col > *cols)
				*cols = col;
			col = 0;
			break;
		default:
			if (c >= ' ' && c <= '~')
				++col;
			break;
		}
	}
	(void)fclose(ifd);
	(void)fseek(tfd, 0L, 0);
	return (tfd);
}

postpass(ifd, cols, rows)
FILE *ifd;
int cols, rows;
{
	register int c, maxval, i;
	register gray *grayrow, *gP;

	maxval = 255;
	if (maxval > PGM_MAXMAXVAL)
		pm_error("maxval of 255 is too large - try recompiling with a larger gray type");
	pgm_writepgminit(stdout, cols, rows, (gray)maxval);
	gP = grayrow = pgm_allocrow(cols);
	/* clear out row */
	for (i = 0, gP = grayrow; i < cols; ++i)
		*gP++ = (gray)0;
	while ((c = getc(ifd)) != EOF)
	{
		c &= 0xff;
		switch (c)
		{
		case '\b':
			if (gP != grayrow)
				--gP;
			break;
		case '\n':
			pgm_writepgmrow(stdout, grayrow, cols, (gray)maxval);
			/* clear out row */
			for (i = 0, gP = grayrow; i < cols; ++i)
				*gP++ = (gray)0;
			gP = grayrow;
			break;
		case '\r':
			gP = grayrow;
			break;
		default:
			if (c >= ' ' && c <= '~')
			{
				*gP += grayvals[c];
				if (*gP > maxval)
					*gP = maxval;
				++gP;
			}
			break;
		}
	}
	pm_close(ifd);
}

main(argc, argv)
int argc;
char *argv[];
{
	register FILE *ifd;
	register int argn;
	int cols, rows;
	char *usage = "[lppic]";

	pm_progname = argv[0];
	argn = 1;
	if (argn < argc)
	{
		ifd = pm_openr(argv[argn]);
		argn++;
	}
	else
		ifd = stdin;
	if (argn != argc)
		pm_usage(usage);

	if ((ifd = prepass(ifd, &cols, &rows)) == NULL)
		pm_error("problems reading line printer picture");
	(void)fprintf(stderr, "%d columns, %d rows\n", cols, rows);
	postpass(ifd, cols, rows);
	exit(0);
}
SHAR_EOF
if test 3374 -ne "`wc -c < 'lptopgm.c'`"
then
	echo shar: "error transmitting 'lptopgm.c'" '(should have been 3374 characters)'
fi
fi
exit 0
#	End of shell archive