uggworek@sunybcs.UUCP (Don Gworek) (12/07/86)
Here is a filter for converting Sun screendump output to QMS quic codes. The filter takes advantage of the QMS data repeat commands to reduce the printjob size by 65% on average. From 260 kb to 90 kb on average, for a 900 by 1152 pixel rasterfile. -------------------------- cut here ----------------------------------- # This is a shell archive. Remove anything before this line, then # unpack it by saving it in a file and typing "sh file". (Files # unpacked will be owned by you and have default permissions.) # # This archive contains: # screendump2qms.1 screendump2qms.c printer.h Makefile echo x - screendump2qms.1 sed -e 's/^X//' > "screendump2qms.1" << '//E*O*F screendump2qms.1//' X.\" @(#)screendump2qms.1 1.1 (Don Gworek) 7/19/86 X.\" This document uses the troff(1) -man macros X.TH SCREENDUMP2QMS 1 "19 July 1986" "" "Local UNIX Programmer's Manual" X.SH NAME Xscreendump2qms \- filter Sun screendump output to QMS printer codes X.SH SYNOPSIS X.B screendump2qms X[ X-l X] [ Xrasterfile X] X.SH DESCRIPTION XThis filter converts X.I screendump(1) Xoutput to printer codes for a QMS Laser printer. It reads Xfrom standard input, or a file. XThe image is printed in landscape mode. Printjobs average 90 kb Xfor a 900 by 1152 pixel screendump. X.PP XThe X-l option Xdisables QMS data repeat commands. Instead, the screendump is Xprinted in a ``long'' format, approximately 260 kb. The option will print Xthe same image, but the raster by raster output could piped Xto X.I sed(1) Xto yield an ascii-hex bitmap. X.SH SEE ALSO Xscreendump(1) X.SH AUTHOR XDon Gworek //E*O*F screendump2qms.1// echo x - screendump2qms.c sed -e 's/^X//' > "screendump2qms.c" << '//E*O*F screendump2qms.c//' X#ifndef lint Xstatic char rcsid[] = X "$Header: screendump2qms.c,v 1.1 86/08/30 22:14:33 gworek Exp $"; X#endif X X/* X * screendump2qms - Filter SUN screendump into QMS quic code. X * X * Usage: screendump2qms [-l] [rasterfile] X * X * Option: X * -l Don't use QMS data repeat commands. X */ X X#include <stdio.h> X#include <sys/types.h> X#include <sys/file.h> X#include <signal.h> X X#ifdef sun X# include <rasterfile.h> X#else X# include "rasterfile.h" X#endif X X#include "printer.h" X X#define STDIN_FDESC 0 /* stdin's file descriptor */ X#define BITSPERBYTE 8 /* number of bits per byte */ X#define TRUE 1 X#define FALSE 0 X Xint count; /* count of bytes read */ Xint total; /* total to read (ras_length) */ Xint longf = FALSE; /* Want printer codes in long format? */ X Xchar *progname; /* who am i? */ Xchar *inputfile; /* where's my input from? */ X Xunsigned char buf[BUFSIZ]; /* The input buffer */ X Xint cleanup(); Xchar *rindex(); Xchar *ctime(); X Xmain(argc, argv) Xint argc; Xchar **argv; X{ X int f, n; X struct rasterfile rh; X X progname = (progname = rindex(*argv, '/')) ? ++progname : *argv; X/* X * Parse args X */ X for (argc--, argv++; (argc > 0) && (**argv == '-'); argc--, argv++) X switch (*++(*argv)) { X case 'l': X longf = TRUE; X break; X default: X usage(); X } X/* X * Open the raster file, or use standard input. X */ X if (argc > 0) { X inputfile = *argv; X if ((f = open(*argv, O_RDONLY)) < 0) { X perror(*argv); X exit(1); X } X } X else { X inputfile = "stdin"; X f = STDIN_FDESC; X } X/* X * Get the header information, and check that everything is okay. X */ X if ((n = read(f, (char *) &rh, sizeof(struct rasterfile))) < 0) { X perror(inputfile); X exit(1); X } X if (n == 0) X die_on_error("empty file"); X if (rh.ras_magic != RAS_MAGIC) X die_on_error("bad magic number"); X if (rh.ras_type != RT_STANDARD) X die_on_error("ras_type %d not RT_STANDARD", rh.ras_type); X if (rh.ras_maptype != RMT_NONE) X die_on_error("ras_maptype %d not RMT_NONE", rh.ras_maptype); X if (rh.ras_depth != 1) X die_on_error("depth %d != 1", rh.ras_depth); X/* X * Access, set, and check image parameters. X */ X total = rh.ras_length; X if (((rh.ras_width / BITSPERBYTE) * rh.ras_height) != rh.ras_length) X die_on_error("calculated data length %d != ras_length %d", X ((rh.ras_width / BITSPERBYTE) * rh.ras_height), X rh.ras_length); X/* X * Set up some cleaning up X */ X (void) signal(SIGHUP, cleanup); X (void) signal(SIGINT, cleanup); X (void) signal(SIGQUIT, cleanup); X (void) signal(SIGTERM, cleanup); X/* X * Set up the printer X */ X printf(RESETPRINTER); X printf(STARTPRINTER); X printf(MARGINSET); X printf(BITMAPSTART, rh.ras_width); X/* X * Print out in long form, or with data repeat commands? X */ X if (longf == TRUE) X printlong(f, rh.ras_width / BITSPERBYTE); X else X printrepeat(f); X/* X * Clean up shop X */ X printf(BITMAPEND); X printf(NEWPAGE); X if (count != rh.ras_length) X fprintf(stderr, "warning: %d bytes read != ras_length %d", X count, rh.ras_length); X (void) close(f); X} X X/* X * Print in long format. Read a raster at a time, and print X * it byte by byte. X */ Xprintlong(f, rasterlen) Xint f, rasterlen; X{ X int i, n; X X if (rasterlen > BUFSIZ) { X fprintf(stderr, "%s: printlong: Internal error. ", progname); X fprintf(stderr, "Increase buffer size from %d to at least %d\n", X BUFSIZ, rasterlen); X exit(1); X } X for (count=0; (n = read(f, (char *) buf, rasterlen)) > 0; count += n) { X for (i = 0; i < n; i++) X printf(DEFFORMAT, buf[i]); X printf("\n"); X } X} X X/* X * Read bytes, counting repeated values. If there are enough X * repeats, use a data compression print command. Otherwise, X * print the data as is. X */ Xprintrepeat(f) Xint f; X{ X int i, n, rep; X unsigned char lastb; X X/* X * Start things off. X */ X if ((n = read(f, (char *) buf, BUFSIZ)) <= 0) X return; X i = 0; X count = n; X rep = 1; X lastb = buf[0]; X/* X * Read bytes until a different value is read. X */ X for (;;) { X if (++i >= n) { X if ((n = read(f, (char *) buf, BUFSIZ)) <= 0) X return; X i = 0; X count += n; X } X if (buf[i] == lastb) { X if (rep < MAXREPEAT) { X rep++; X continue; X } X } X/* X * If the byte pattern didn't repeat long enough, print out X * that count of bytes. Otherwise, print out the pattern X * according to the correct repeat format. X */ X if (rep < MINREPEAT) X while (rep-- > 0) X printf(DEFFORMAT, lastb); X else X switch (lastb) { X case 0xFF: X printf(BITSON, 2 * rep); X break; X case 0x00: X printf(BITSOFF, 2 * rep); X break; X default: X printf(BITSOFFON, rep, lastb); X break; X } X lastb = buf[i]; X rep = 1; X } X} X X/* X * Cleanup shop before you die X */ Xcleanup() X{ X printf(BITMAPEND); X printf(NEWPAGE); X fprintf(stderr, "%s: cleaning up. read %d of %d bytes.\n", X progname, count, total); X exit(1); X} X X/* X * Print an error message with the program and input file names, X * and then die. X */ X X/* VARARGS */ Xdie_on_error(mesg, arg1, arg2) Xchar *mesg; X{ X fprintf(stderr, "%s: %s: ", progname, inputfile); X fprintf(stderr, mesg, arg1, arg2); X fprintf(stderr, ".\n"); X exit(1); X} X X/* X * How do you use this darn thing anyway? X */ Xusage() X{ X fprintf(stderr, "Usage: %s [-l] [rasterfile]", progname); X exit(1); X} //E*O*F screendump2qms.c// echo x - printer.h sed -e 's/^X//' > "printer.h" << '//E*O*F printer.h//' X/* X * $Header: printer.h,v 1.6 86/07/19 12:47:17 gworek Exp $ X */ X X/* X * QMS quic code sequences are defined here X */ X X#define RESETPRINTER "ReSeTrEsEtReSeT\n" X#define STARTPRINTER "^PY^-\n^F^ISYNTAX00000^ISTF00\n" X#define MARGINSET "^IOL^IJ01000^IT01000\n" X#define BITMAPSTART "^T00000^J00000^IP0202^P%04d\n" X#define MINREPEAT 3 X#define MAXREPEAT 499 /* half of 999 */ X#define BITSON "^B%03d" X#define BITSOFF "^D%03d" X#define BITSOFFON "^C%03d%02X" X#define DEFFORMAT "%02X" X#define LO4MASK 0x0F X#define HI4MASK 0xF0 X#define BITMAPEND "^G\n" X#define NEWPAGE "^,\n" //E*O*F printer.h// echo x - Makefile sed -e 's/^X//' > "Makefile" << '//E*O*F Makefile//' X# X# $Header: Makefile,v 1.6 86/07/19 16:53:52 gworek Exp $ X# X# SUN screendump print filter for the QMS X XSRCS = screendump2qms.c XOBJS = screendump2qms.o XHDRS = printer.h XDEST = screendump2qms XINSTALLDIR = /usr/local/bin X XDFLAGS = XCFLAGS = -O -s ${DFLAGS} X X${DEST}: ${OBJS} X cc ${CFLAGS} -o ${DEST} ${OBJS} X X${OBJS}: ${HDRS} X Xinstall: X install ${DEST} ${INSTALLDIR} X Xclean: X /bin/rm -f *.o ${DEST} X Xlint: ${HDRS} ${SRCS} X lint ${DFLAGS} ${SRCS} //E*O*F Makefile// exit 0