[net.sources.mac] Mac => Printronix/Bitmap Conversion

info-mac@uw-beaver (01/24/85)

From: Michael Ardai <UI.MIKE%CU20B@COLUMBIA.ARPA>

Following the dotted line below is a version of Ed Patterman's
MACIMP program modified for Printronix output.  Internally, it
generates a bitmap (a packed array of booleans), so it is easy
to add output routines for any bitmap device.  I did not do 
any conversions for aspect ratio, so the output is slightly
misproportioned.

The code, as written, is restricted to Decsystem-20's, though
it shouln't be too difficult to convert it to run on other 
machines.  

Michael L. Ardai
Columbia University
Center for Computing Activies
User Services

[An FTPable executable is in CU20B::PS:<MACINTOSH>MACPTX.EXE
 and the Pascal source in CU20B::PS:<MACINTOSH>MACPTX.PAS]
-------------------------------------------------------------------------------
Program Macptx ;

    (* This program converts a Macintosh bitmap file into a file
       suitable for printing on a Printronix dot-matrix printer.
       It is based on MACimp (the MAC - IMAGEN program).
       Macptx has been proven to work with
	       o MACPAINT files
	       o Screen dumps (created with COMMAND-SHIFT-3)
       It will not work with MACwrite files at the moment.

       Written by Ed Pattermann (PATTERMANN@SUMEX), SUMEX Computer Project 
       Copyright 1984 @ Stanford University

       Rewritten for the Printronix printer by Michael L. Ardai (ui.mike@CU20B)
       Columbia University, January 1985.
       ***************************************************************

Most of the following comes directly from the original with obvious changes:

       Macptx converts a Macintosh bitmap file into a PRINTRONIX format
       file for printing on a Printronix printer. The crux of this
       program is understanding the format of the Macintosh bitmap file
       and the format of a PRINTRONIX Bitmap file.

       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

       Now, the PRINTRONIX file ; 
       720 lines representing the printed rows of pixels.
       Each line is of the following format:
       ^E <96 bytes of pixel data> crlf
       ^E turns on the graphics mode of the printer; all characters 
       until the crlf are treated as graphics.  Bit 6 of each character
       is set, and the remaining 6 bits (bits 5 thru 0) correspond to the 
       six bits of bitmap in reverse order.  Ex.:
	*..*.* corresponds to 1101001 , Octal 151, ASCII 'i'
       The only exception is 1111111, ASCII del, which gets stripped by our 
       printer spooler.  For this bit pattern the program generates a ?

     *)

    include 'pas:pascmd.pas';
    include 'pas:extern.pas';

CONST 
	haltf = 170b;		{Constants representing JSYS instructions}
	bin = 50b;		{BIN: Binary input, HALTF: Halt fork}
TYPE
    Bitstring = Packed Array [0..35] Of Boolean;
VAR
    (* BITMAP*)
    bitmap   : packed array[0..720,0..576]of Boolean;
    (* VARIABLES *)
    col	     : INTEGER ;
    i,j,k,l  : INTEGER ;
    bytes    : INTEGER ;
    opcode   : INTEGER ;
    databyte : CHAR    ;
    bs       : bitstring;

    (* FOR PARSING TOPS20 FILES *)
    macjfn   : INTEGER ;
    ptxjfn   : INTEGER ;
    inlength : INTEGER ;
    infilename  : PACKED ARRAY [1..80] OF CHAR ;
    outlength : INTEGER ;
    outfilename  : PACKED ARRAY [1..80] OF CHAR ;
    macfile : FILE OF CHAR ;
    Ptxfile : FILE OF CHAR ;


FUNCTION rh(b:integer):integer; 
{Zero the left half of a word.  Used for Job File Numbers}
TYPE rec = RECORD			{Uses variant record to !escape from}
  case flag: boolean of			{Pascal typing!, in order to convert}
    false: (bs: bitstring);		{a bitstring to an integer so it can}
    true: (int: integer)		{be written to the output file.}
  END;
VAR r: rec;
	i:INTEGER;
BEGIN

  r.flag:=true; r.int:=b;		{Put data in as an integer...}
  r.flag:=false;			{Hey presto, it's an bitstring!}
  FOR i := 0 TO 17 DO r.bs[i] := FALSE;
  r.flag := TRUE; rh := r.int;
END; {procedure rh}

PROCEDURE convert(c:CHAR; VAR b:bitstring);
TYPE rec = RECORD			{Same idea as above}
  case flag: boolean of			
    false: (bs: bitstring);		
    true: (ch: CHAR )			
  END;
VAR r: rec;
BEGIN

  r.flag:=true; r.ch := c;		{Put data in as an character...}
  r.flag:=false;			{Presto, it's an bitstring!}
  b := r.bs;
END; {PROCEDURE convert}

FUNCTION pow(i:INTEGER):INTEGER;
{Calculate 2**i, 0 <= i<= 5}
VAR
	k,p:INTEGER;
BEGIN
    p := 1;
    FOR k := 0 TO i DO p := p *2;
    p := p DIV 2;
    pow := p;
END;


BEGIN

Writeln(tty,'Macptx - A Macintosh bitmap file to PRINTRONIX conversion program') ;
cmini('Macintosh filename to be converted > ');
cmhlp('Name of Macintosh file ') ;
cmifi(macfile) ; inlength := cmatom(infilename) ; cmcfm ;
cmini('File for output                    > ');
cmhlp('Name of Printronix file ') ;
cmofi(ptxfile) ; outlength := cmatom(outfilename) ; cmcfm ;


(* INITIALIZE INPUT FILE *)
Reset(macfile,infilename,'/B:08') ;
macjfn := curjfn(macfile) ;
macjfn := rh(macjfn) ;

(* INITIALIZE OUTPUT FILE *)
Rewrite(Ptxfile,outfilename);		{Ask user for name of output file}
ptxjfn := curjfn(Ptxfile) ;
ptxjfn := rh(ptxjfn) ;

(* READ IN HEADER *)
FOR i := 1 TO 512 DO jsys(bin,1; macjfn ; j,databyte) ;

(* READ IN DATA BYTES *)
Write(tty,'Processing ',infilename:inlength,' ') ;
FOR i := 1 TO 720 DO
    BEGIN
	col := 0;
	WHILE bytes < 72 DO
	    BEGIN
		jsys(bin,1; macjfn ; j,opcode) ;
		IF opcode > 127 THEN
		    BEGIN
			opcode := 256-opcode+1 ;
			jsys(bin,1; macjfn ; j,databyte) ;
			convert(databyte,bs);
			FOR l := 1 TO opcode DO
			    BEGIN
				FOR k := 28 to 35 DO 
				    BEGIN
					bitmap[i,col] := bs[k];
					col := col +1;
				    END;
			    END ;
		    END
		ELSE
		    BEGIN
			opcode := opcode + 1 ;
			FOR l := 1 TO opcode DO
			    BEGIN
				jsys(bin,1; macjfn ; j,databyte) ;
				convert(databyte,bs);
				FOR k := 28 to 35 DO
				    BEGIN
					bitmap[i,col] := bs[k];
					col := col +1;
				    END;
			    END ;
		    END;
		bytes := bytes + opcode ;
	    END; (* WHILE BYTES < 72 *)
	IF bytes > 72 THEN
	    BEGIN
		Writeln(tty,'[FAILED]') ;
		Writeln(tty,'Input file is not a macintosh bitmap file') ;
		close(macfile) ; 
		jsys(haltf)  ;
	    END ;
	bytes := 0 ;
    END; (* FOR I := 1 TO 720 *)

{ You now have a pure bitmap.  This should easily be convertible for any}
{ dot-addressable device, or even a vector unit.}

(* CREATE PRINTRONIX FILE*)
    FOR  i := 0 TO 720 DO 
	BEGIN
	    col:= 0;
	    WRITE (Ptxfile,CHR(5));
	    WHILE col <= 575 DO
		BEGIN
		    k := 64;
		    FOR j :=  0 TO 5 DO
			IF bitmap[i, col+ j]=TRUE THEN k := k+pow(j);
		    IF k = 127 THEN k := 63;
		    WRITE(Ptxfile,CHR(k));
		    col := col + 6;
		END;
	    WRITELN(Ptxfile);
	END;

			      
(* WERE DONE *)
close(Ptxfile) ; close(macfile) ;
Writeln(tty,'[OK]')
END.

-------