[net.micro.mac] MacPaint Format?

mjk@tty3b.UUCP (Mike Kelly) (03/18/85)

Anyone with information on MacPaint document format, please post it
or mail to me.  Thanks.

Mike Kelly
AT&T Teletype

P.S. Was there a Brown program a little while ago that printed MacPaint
	documents  on the Imagen?

jwp@utah-cs.UUCP (John W Peterson) (03/20/85)

Here it is.  (This came out on INFO-MAC several months ago).
-----------

For those interested, here is a description of the format of MACpaint files.
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

That's it. A nice simple scheme. Thanks to Bill Atkinson for providing this
info.

ix408@sdcc6.UUCP (Cris Rys) (03/21/85)

Here is the information requested on Macpaint documents.
I got this information from Inside Macintosh.

Macpaint documents use only the data fork of the file system; the
resource fork is not used and may be ignored. The data fork contains
a 512 byte header and then the compressed data representing a single
bitmap of 576 pixels wide by 720 pixels tall. At 72 pixels per inch,
this bitmap occupies the full 8 by 10 inch printable area of the
imagewriter printer page.

Header:

The first 512 bytes of the document form a header with a 4 byte
version number (default = 2), then 38*8 = 304 bytes of patterns,
then 204 unused bytes reserved for future expansion. If the version
number is zero, the rest of the header block is ignored and the
default patterns are used, so programs generating Macpaint documents
can simply write out 512 bytes of zero as the document header. Most
programs which read Macpaint documents can simply skip over the
header when reading.

Bitmap:

Following the header are 720 compressed scanlines of data which form
the 576 wide by 720 tall bitmap. Without compression, this bitmap
would occupy 51840 bytes and chew up disk space pretty fast; typical
Macpaint documents compress to about 10k using PackBits procedure in
the Macintosh ROM to compress runs of equal bytes within each
scanline. The bitmap part of a Macpaint document is simply 720 times
the output of PackBits with 72 bytes input.

READING SAMPLE:
program convert_pic;
{ I am not sure what libraries this program uses.}
{ UnPackBits IS in ROM, I'm not sure about ReadData}
 const
  srcBlocks = 2;  {At least 2, bigger makes it faster}
  srcSize = 1024; {512 *srcBlocks}
 type
  diskBlock = packed array[1..512] of QDByte;
 var
  srcBuf : array[1..srcBlocks] of diskBlock;
  srcptr, dstptr : QDPtr;
begin
 { skip the header }
 ReadData(srcfile, @srcBuf, 512);
 { prime srcBuf }
 ReadData(srcFile, @srcBuf, srcSize);

 { unpack each scanline into dstBits, reading more source as needed}
 srcPtr := @srcBuf;
 dstptr := dstBits.baseAddr;
 for scanline := 1 to 720 do
  begin
   Unpackbits(srcptr, desptr, 72);         { bumps both ptrs }
   { time to read next chunk of packed source ? }
   if ord(srcptr) > ord(@srcbuf) + size - 512 then
    begin
     srcbuf[1] := srcBuf[srcblocks];       { move up last block }
     Readdata(srcfile, @srcbuf[2], srcsize - 512);
     srcptr := pointer(ord(srcptr) - srcsize + 512);
    end;
  end;
end.

WRITING SAMPLE:

To write out a 576 by 720 bitmap which is contained in memory, the
following fragment of code could be used:

program write_pic;
 type
  diskBlock = packed array[1..512] of QDByte;
 var
  dstBuf         : diskBlock;
  srcptr, dstptr : QDPtr;
  dstbytes       : integer;
begin
 {write header, all zeros}
 for i:= 1 to 512 do dstBuf[i]:=0;
 writedata(dstfile, @dstBuf, 512);
 
 {Compress each scanline and write it}
 srcptr := srcBits.baseAddr;
 for scanline := 1 to 720 do
  begin
   dstPtr:=@dstBuf;
   packbits(srcptr, desptr, 72);	 {bumps both ptrs}
   dstBytes:=ORD(dstPtr)-ORD(@dstBuf);   {calc packed size}
   WriteData(dstFile,@dstbuf,dstBytes);  {write packed data}
  end;
end.


Both of the two previous programs are only skeletons, but should
work with minimal additions.

Cris Rys

adm@cbneb.UUCP (03/22/85)

How can Macpaint tell the difference between a count byte and a data byte?
Wayne Pollock,	...!{ihnp4}!cbnap!whp