[fa.info-mac] MacPaint -> bitmap filter, in C

info-mac@uw-beaver (info-mac) (08/03/84)

From: Peterr%toronto.csnet@csnet-relay.arpa
The following program allows printing of MacPaint documents on devices which
accept raw bitmaps as input.  It provides for simple scaling-up of the
images to accomodate the typical 200-300dpi resolutions of electrostatic
plotters and laser printers.  It requires a machine with a 32 bit integer,
but should be very portable otherwise.

------------------------
/*  MacPaint format -> bitmap filter
    P. Rowley, U. Toronto, July 30, 1984.
    peterr%toronto@CSNET-RELAY

    This program reads a standard MacPaint document on the standard input
    and produces a bitmap file on the standard output.  The bitmap is
    some magnification of the MacPaint 576 (horiz) x 720 (vertical) encoded
    image, possibly with horizontal 0 padding.

    The specific bitmap format is determined at compile time,
    for the sake of efficiency.
*/
#include <stdio.h>
/* The manifests define the output bitmap format as follows:
     The bitmap is OUT_HORIZ_SIZE bytes wide and 720*OUT_VERT_MUL tall,
     with each Mac pixel translated into a OUT_HORIZ_MUL x OUT_VERT_MUL
     rectangle.  There are OUT_HORIZ_PAD bytes of left margin on every
     output scan line.

   The following restrictions apply to the manifests:
	OUT_HORIZ_SIZE >= OUT_HORIZ_PAD + 72 * OUT_HORIZ_MUL
	OUT_HORIZ_PAD  >= 0
	OUT_HORIZ_MUL  = 1, 2, 3, or 4
        OUT_VERT_MUL   >= 1
   Sample values (for a Versatec plotter): 264, 24, 3, 3
*/
#define OUT_HORIZ_SIZE			264
#define OUT_HORIZ_PAD			24
#define OUT_HORIZ_MUL			3
#define OUT_VERT_MUL			3

char in_line[72], out_line[OUT_HORIZ_SIZE];
int  xlat[256];
main() {
	int i, j;

	/* initialize tables and buffers */
	init();

	/* read and discard 512 byte header */
	for (i=0; i<512; i++)
		getchar();

	/* read and process each of the 720 scan lines */
	for (i=0; i<720; i++) {
		read_scan();
		write_scan();
	}
}

read_scan() {
	int in_pos, count, data_byte;

	in_pos = 0;
	while (in_pos < 72) {
		count = getchar();
		if (count > 127) count -= 256;

		if (count >= 0) {		/* run of raw bytes */
			count++;		/* # of bytes to read */
			while (count--)
				in_line[in_pos++] = getchar();
		}
		else {				/* run of repeated byte */
			count = -count+1;	/* repetition factor */
			data_byte = getchar();  /* byte to repeat */

			while (count--)
				in_line[in_pos++] = data_byte;
		}
	}
}

write_scan() {
	int i, j, outword;

	/* prepare output scan line:
		OUT_HORIZ_PAD 0's,
		72 * OUT_HORIZ_MUL data bytes,
		enough 0's for a total of OUT_HORIZ_SIZE bytes
	*/

	/*  leading and trailing 0's are in out_line by default */

	j = OUT_HORIZ_PAD;
	for( i=0; i<72; i++ ) {
		outword = xlat[in_line[i] & 255];
#if (OUT_HORIZ_MUL == 4)
		out_line[j++] = (outword >> 24) & 255;
#endif
#if (OUT_HORIZ_MUL >= 3)
		out_line[j++] = (outword >> 16) & 255;
#endif
#if (OUT_HORIZ_MUL >= 2)
		out_line[j++] = (outword >>  8) & 255;
#endif
		out_line[j++] = (outword      ) & 255;

	}

	/* output the scan line, OUT_VERT_MUL times */
	for( i=0; i<OUT_VERT_MUL; i++ )
		for( j=0; j<OUT_HORIZ_SIZE; j++ )
			putchar( out_line[j] );
}

init() {
	int bits[8], i, j;

	/* initialize translation table */
	j = (1<<OUT_HORIZ_MUL) - 1;
	for( i=0; i<8; i++ ) {
		bits[i] = j;
		j *= (1 << OUT_HORIZ_MUL);
	}

	for( i=0; i<256; i++ ) {
		if( i &	  1 )	xlat[i] = bits[0];
		else		xlat[i] = 0;

		if( i &   2 )	xlat[i] += bits[1];
		if( i &   4 )	xlat[i] += bits[2];
		if( i &   8 )   xlat[i] += bits[3];
		if( i &  16 )	xlat[i] += bits[4];
		if( i &  32 )	xlat[i] += bits[5];
		if( i &  64 )	xlat[i] += bits[6];
		if( i & 128 )	xlat[i] += bits[7];
	}
}