home *** CD-ROM | disk | FTP | other *** search
- /* convert from MacPaint document to a form that can be printed on the
- Printronix printer
-
- This program should work with MacPaint and Screen dump files (made by
- COMMAND-SHIFT-3). However, it does not work with MacWrite files.
-
- This program was written for Berkeley Unix, version 4.2, running on a
- VAX.
-
- Options:
- -h turn off halftoning
- -m <n> where <n> is between 1 and 4. This is an indication
- of how much to magnify (and is called the "magfactor")
-
- Written by Richard Furuta, Computer Science, University of Washington.
- Hacked by Steve Johnson for Printronix, ACC (Oct 16, 1984)
-
- Please report changes and fixes back to me. By Arpanet and CSNet,
- I am Furuta@Washington. By uucp, I am ihnp4!uw-beaver!furuta. I
- prefer the Arpanet/CSNet address.
-
- I benefitted greatly from Ed Pattermann's code for macimp. The
- following description of the MacPaint font format comes from that
- code.
-
- =============
-
- First, the Macintosh file ; This format is the common
- interchange format for full-page bitmap images on the Macintosh.
-
- The first 512 bytes of the file are the header. The first four bytes
- comprise the version number, followed by 38*8 = 304 bytes of
- patterns. The remaining 204 bytes of the header are reserved for
- future expansion. If the version number is zero, the patterns are
- ignored. Hence, programs that wish to create files to be read into
- MACpaint can just write out 512 bytes of zero as the header.
-
- Following the header are 720 compressed scanlines of data which form
- the 576 wide by 720 tall bitmap. The bitmap is compressed as follows ;
- Any run of three or more equal bytes is compressed into a count byte
- and a single data byte. Runs of unequal bytes are passed on literally,
- preceded also by a count byte. i.e.
-
- <count byte> <data byte>
- count = -1..-127 --> replicate byte 2..128 times
- <count byte> <n data bytes>
- count = 0.. 127 --> copy 1..128 bytes uncompressed
- count = -128 ignored for backward compatibility
-
- =============
-
- This program produces a series of DEVICE "Define a Block of Raster Data"
- commands which are used to produce a dump of the screen. You have to be
- careful about the syntax of the arguments to this command. I had a bit of
- trouble caused by forgetting that the byte ordering and bit ordering of the
- raster words given to this command differ from those of the parameters to
- the command. I could have used the "Screen Dump" DEVICE command instead of
- this command to dump the raster. The advantage would have been that the
- resolution of the device would have been halved probably eliminating the
- need to half tone. The disadvantage is that it is harder to support the
- magnification factor of 3 that seems to make the most sense to me.
-
- An arbitrary magnification is used to blow up the figure in both dimensions
- (x and y). This is controlled by "magfactor" which should be at least one.
- If it gets larger than 4, you'll have to expand the amount of storage given
- to "outline" in procedure "makebitmap". I try detect and skip blank scan
- lines to help conserve bandwidth to the printer which is pretty horrid at
- 9600 baud. Maybe one of these days our DR11/C interface will work again and
- bandwidth won't be such a problem!
-
- */
-
- #include <stdio.h>
-
- #define TRUE 1
- #define FALSE 0
-
- /* for command line option processing */
- char *ProgName;
- extern char *optarg;
- extern int optind;
-
- int checkwhite();
- char flipbits();
- int intoout();
-
- /* a macpaint document in the worst case should occupy twice as many bytes
- as a straight screen dump. This pathological case comes when you have
- only count bytes of 1. Since the Mac screen is 576 x 720 bits or
- 72 x 720 bytes == 51840 bytes, this worst case would occupy 103680
- bytes */
- char compressed[200]; /* lookahead storage for input - 152 is enough */
- int nextcompbyte; /* next index into this array */
-
- int whitestateflg; /* TRUE if we last looked at a blank line */
-
- /* The DEVICE washes out large black areas. As an attempt to address this,
- I'm trying to halftone the output */
-
- #define DMASK 0377 /* 11111111 pass everything through */
- #define EMASK 0252 /* 10101010 even bits only */
- #define OMASK 0125 /* 01010101 odd bits only */
-
- char curmask; /* the current one to use */
- int hflg; /* TRUE if we want to halftone */
-
- #define CTRL_E 05 /* control E */
- #define LF 10 /* linefeed */
- #define void int
-
- main(argc, argv)
- int argc;
- char **argv;
- {
- int optch; /* option character */
- int ctr; /* temporary counter */
- int scanctr; /* count the 720 scan lines */
- int byte; /* incoming information */
- int countbyte; /* gives meaning of subsequent input bytes */
- int linebytecount; /* how many bytes seen so far on
- input? 0..71 */
- int magfactor; /* how many times do you want to expand
- this? 1..4 */
- int linestart; /* when collecting a line, recall where it
- all began */
-
- magfactor = 1; /* by default, show at true size */
- curmask = DMASK; /* by default, in case no halftoning is set */
- hflg = FALSE; /* by default, halftoning */
-
- ProgName = *argv;
-
- /* grab some options */
- while ((optch = getopt (argc, argv, "hm:")) != EOF) {
- switch (optch) {
- case 'h': /* want halftoning */
- hflg = TRUE;
- curmask = DMASK; /* unnecessary but for safety... */
- break;
- case 'm': /* magnification factor */
- magfactor = atoi(optarg);
- break;
- case '?':
- fprintf(stderr, "Usage: %s [-m magfactor]\n",
- ProgName);
- (void)fflush(stderr);
- exit(1); /* a bit harsh, but ... */
- }
- }
- if((magfactor < 1) || (magfactor > 4)) {
- fprintf(stderr, "%s: Sorry, magfactor can't be %d, must be between 1 and 4\n",
- ProgName, magfactor);
- exit(1);
- }
-
- /* jump over the 512 bytes of header */
- for(ctr=0; ctr < 512; ctr++)
- byte = getc(stdin);
-
- nextcompbyte = 0;
- whitestateflg = TRUE;
-
- /* for each scan line */
- for(scanctr=0; scanctr < 720; scanctr++) {
- linebytecount = 0;
-
- linestart = nextcompbyte;
-
- /* capture incoming line, producing the output line */
- while(linebytecount < 72) {
- countbyte = getc(stdin) & 0377; /* count byte */
- compressed[nextcompbyte++] = countbyte;
- if(countbyte > 127) {
- /* replicated bytes follow */
- countbyte = 256-countbyte+1;
- byte = getc(stdin) & 0377;
- compressed[nextcompbyte++] = byte;
- }
- else {
- /* unreplicated bytes follow */
- countbyte++;
- for(ctr = 0; ctr < countbyte; ctr++) {
- byte = getc(stdin) & 0377;
- compressed[nextcompbyte++] = byte;
- }
- }
- linebytecount += countbyte;
- }
- /* now see where we are */
- whitestateflg = checkwhite(&compressed[linestart]);
- if(whitestateflg) {
- nextcompbyte = 0;
- put_white(stdout);
- }
- else {
- /* dump bitmap line */
- makebitmap(stdout, compressed, (int) 1,
- magfactor);
- /* and reset for next time */
- nextcompbyte = 0;
- }
- }
-
- /* put out some end of files to make the lgp happier */
- for(ctr=0;ctr<100;ctr++)
- dv_eof(stdout);
- }
-
-
- /* dump out a bitmap */
- makebitmap(outf, compressed, maclines, magfactor)
- FILE *outf; /* where to put it */
- char compressed[]; /* input commands */
- int maclines; /* how many scan lines are represented? */
- int magfactor; /* correspondence between mac lines and lgp lines */
- {
- int hsize; /* expected horizontal size in words */
- int vsize; /* expected vertical size in scan lines */
- int scanctr; /* count the scan lines */
- int linebytecount; /* how many bytes seen so far on
- input? 0..71 */
- int compcnt; /* count into the compressed array */
- int byte; /* incoming information */
- int countbyte; /* gives meaning of subsequent input bytes */
- char outline[288]; /* max one scan line at magfactor 4 (72*4) */
- int outbytecount; /* bytes produced so far on output */
- int mask_line;
- int ctr; /* temporary counter */
-
- compcnt = 0;
- mask_line = 0;
- /* for each scan line */
- for(scanctr=0; scanctr < maclines; scanctr++) {
- linebytecount = 0;
- outbytecount = 0;
-
- /* capture incoming line, producing the output line */
- while(linebytecount < 72) {
- countbyte = compressed[compcnt++] & 0377;
- if(countbyte > 127) {
- /* replicated bytes follow */
- countbyte = 256-countbyte+1;
- byte = compressed[compcnt++] & 0377;
- for(ctr = 0; ctr < countbyte; ctr++)
- outbytecount = intoout(byte,magfactor,
- outline,outbytecount);
- }
- else {
- /* unreplicated bytes follow */
- countbyte++;
- for(ctr = 0; ctr < countbyte; ctr++) {
- byte = compressed[compcnt++] & 0377;
- outbytecount = intoout(byte,magfactor,
- outline,outbytecount);
- }
- }
- linebytecount += countbyte;
- }
-
- /* display the output line */
- for(ctr=0; ctr < magfactor; ctr++) {
- /* if halftoning */
- if(hflg) {
- /* pick proper mask (want to alternate them */
- if(mask_line & 01)
- curmask = OMASK;
- else
- curmask = EMASK;
- mask_line--;
- }
- /* generate output bytes */
- dv_format(outf,outline,outbytecount);
- }
- }
-
- }
-
- /* produce the printronix line */
-
- dv_format(outf,outline,outbytecount)
- FILE *outf;
- char outline[]; /* output buffer */
- int outbytecount;
- {
- register i,j;
- register char *ptr;
- int octr; /* output counter for display */
- char bit_stream[288*8]; /* bit stream */
- char out_byte; /* two-bit header, 6-bits of info ooutput byte */
- char abyte; /* input byte */
-
- if (outbytecount != 72)
- {
- printf(stderr,"dv_format: Byte count not 72\n");
- (void) fflush(stderr);
- exit(1);
- }
- j = 0;
- ptr = outline;
- for (octr=0; octr < outbytecount; octr++) {
- abyte = outline[octr];
- for (i=7; i>=0; i--) /* 8 bits per byte */
- bit_stream[j++] = !!( abyte & (1<<i) );
- }
- putdevbyte(CTRL_E, outf); /* CTRL-E means bitstream following to printronix */
- j = 0;
- for (octr=96; octr > 0; octr--) { /* output 96 bytes */
- out_byte = 0; /* clean start */
- for (i=0; i<=5; i++) /* 6 info bits per byte */
- out_byte |= (bit_stream[j++] << i); /* pick off the bit */
- out_byte = (out_byte | 0x40) & 0x7F; /* fix two high order bits */
- putdevbyte(out_byte&curmask, outf); /* finally! */
- }
- putdevbyte(LF, outf); /* end of bitstream */
- }
-
- /* take the byte and produce an appropriate number of output bytes */
- int intoout(byte, magfactor, outline, outbytecount)
- int byte; /* incoming byte */
- int magfactor; /* how many repitions */
- char outline[]; /* output buffer */
- int outbytecount; /* where are we in outline? */
- {
- int bitctr; /* count the bits in the byte */
- int bit;
- int magctr; /* count down the copies */
- char *cptr; /* current character being stuffed */
- int outbitctr; /* and the bit within the character */
-
- /* optimization */
- if(magfactor == 1) {
- outline[outbytecount] = byte;
- outbytecount++;
- }
- else {
- /* make multiple copies of this bit */
- cptr = &outline[outbytecount];
- *cptr = 0;
- outbitctr = 7;
- for(bitctr = 7; bitctr >= 0; bitctr--) {
- bit = (byte >> bitctr) & 01;
- /* replicate the bit in the output */
- for(magctr=0; magctr < magfactor; magctr++) {
- if(outbitctr < 0) {
- /* to next output byte */
- cptr++;
- *cptr = 0;
- outbitctr = 7;
- }
-
- *cptr |= (bit << outbitctr);
- outbitctr--;
- }
- }
- outbytecount += magfactor;
- }
- return(outbytecount);
- }
-
-
- /* low order, high order */
- putdevword(value, outf)
- int value;
- FILE *outf;
- {
- putc(value & 0377, outf);
- putc((value >> 8) & 0377, outf);
- }
-
- putdevbyte(value, outf)
- int value;
- FILE *outf;
- {
- putc(value & 0377, outf);
- }
-
- dv_eof(outf)
- FILE *outf;
- {
- ;
- }
-
- put_white(outf)
- FILE *outf;
- {
- putc(CTRL_E & 0377, outf);
- putc(LF & 0377, outf);
- }
-
- char flipbits(oldbyte)
- char oldbyte;
- {
- char newbyte;
-
- newbyte = 0;
-
- /* 7 6 5 4 3 2 1 0 */
- newbyte = ((oldbyte & 01) << 7) | /* old 0 to new 7 */
- ((oldbyte & 02) << 5) | /* old 1 to new 6 */
- ((oldbyte & 04) << 3) | /* old 2 to new 5 */
- ((oldbyte & 010) << 1) | /* old 3 to new 4 */
- ((oldbyte & 020) >> 1) | /* old 4 to new 3 */
- ((oldbyte & 040) >> 3) | /* old 5 to new 2 */
- ((oldbyte & 0100) >> 5) | /* old 6 to new 1 */
- ((oldbyte & 0200) >> 7); /* old 7 to new 0 */
- return(newbyte);
- }
-
-
- /* see if this line is all white */
- int checkwhite(bytes)
- char *bytes;
- {
- int countbyte;
- int linebytecount;
- int iswhite;
- int ctr;
-
- iswhite = TRUE;
- linebytecount = 0;
-
- while(iswhite && (linebytecount < 72)) {
- countbyte = *bytes & 0377;
- bytes++;
- if(countbyte > 127) {
- /* replicated byte case */
- countbyte = 256-countbyte+1;
- if(*bytes) {
- iswhite = FALSE;
- break;
- }
- bytes++;
- }
- else {
- /* unreplicated bytes follow */
- countbyte++;
- for(ctr = 0; ctr < countbyte; ctr++) {
- if(*bytes) {
- iswhite = FALSE;
- break;
- }
- bytes++;
- }
- }
- linebytecount += countbyte;
- }
- return(iswhite);
- }
-
-
- /* =================option processing via Chris Torek@Maryland=============*/
- /*
- * getopt - get option letter from argv
- * (From Henry Spencer @ U of Toronto Zoology, slightly modified)
- */
-
- /* #include <stdio.h> */
-
- char *optarg; /* Global argument pointer. */
- int optind; /* Global argv index. */
-
- static char *scan; /* Private scan pointer. */
-
- extern char *index();
-
- int
- getopt (argc, argv, optstring)
- register int argc;
- register char **argv;
- char *optstring;
- {
- register int c;
- register char *place;
-
- optarg = NULL;
-
- if (scan == NULL || *scan == 0) {
- if (optind == 0)
- optind++;
-
- if (optind >= argc || argv[optind][0] != '-' || argv[optind][1] == 0)
- return EOF;
- if (strcmp (argv[optind], "--") == 0) {
- optind++;
- return EOF;
- }
-
- scan = argv[optind] + 1;
- optind++;
- }
-
- c = *scan++;
- place = index (optstring, c);
-
- if (place == NULL || c == ':') {
- fprintf (stderr, "%s: unknown option -%c\n", argv[0], c);
- return '?';
- }
-
- place++;
- if (*place == ':') {
- if (*scan != '\0') {
- optarg = scan;
- scan = NULL;
- }
- else {
- if (optind >= argc) {
- fprintf (stderr, "%s: missing argument after -%c\n",
- argv[0], c);
- return '?';
- }
- optarg = argv[optind];
- optind++;
- }
- }
-
- return c;
- }
-