Macintosh Paint

Also Known As: PNTG, MAC, MacPaint


Type Bitmap
Colors Mono
Compression RLE, uncompressed
Maximum Image Size 576x720 pixels
Multiple Images Per File No
Numerical Format Big-endian
Originator Apple Computer Inc.
Platform Macintosh
Supporting Applications Too numerous to list
See Also Macintosh PICT

Usage
Clip art, screen dumps, monochrome artwork

Comments
A well-defined, well-documented format in use on the Macintosh platform. MacPaint is quick and easy to read and decompress, but it lacks support for more than monochrome images. Numbers in the file are stored in big-endian format.

Vendor specifications are available for this format.

Code fragments are available for this format.

Sample images are available for this format.


Macintosh Paint (MacPaint) is the original and most common graphics file format used on the Apple Macintosh. Most Macintosh applications that use graphics are able to read and write the MacPaint format. MacPaint files on the Macintosh have the file type PNTG, while on the PC they usually have the extension .MAC. The first real image files widely available to PC users were MacPaint files. PC users usually obtained them from BBSs or shareware disks, and a number of programs exist that allow MacPaint files to be displayed and printed using a PC under MS-DOS. Today, extensive black-and-white clip art and graphics are available in the MacPaint format. MacPaint files are also used to store line drawings, text, and scanned images.

Contents:
File Organization
File Details
For Further Information

MacPaint images are always black and white and are a fixed size (576 pixels wide by 720 scan lines high) and fixed resolution (75 dpi). Uncompressed, the image data is always 51,840 bytes in size. Because the Apple Macintosh is based on the Motorola 68000 series of CPUs, most files are stored in big-endian format, and MacPaint files are no exception. They are always read and written in big-endian format, no matter what the host platform. The ENDIANIO library can be used to read and write MacPaint files on non-big-endian systems.

Files are stored differently on the Macintosh than they are on most other systems in common use. Every Macintosh file consists of two parts, called forks. Although a user sees only a single file, data is actually stored as two physical files on disk. The first file is called the data fork, which stores program information. The second file is called the resource fork, and it stores program code. Data associated with a MacPaint file occupies only the data fork of the file pair; its companion resource fork is always empty.

Outside the Macintosh environment a MacPaint file is stored as a single file, with the two forks combined into one file, allowing it to reside on foreign file systems not adhering to the Macintosh conventions. A MacBinary header is prepended to the file. The MacBinary header is a structure which allows a Macintosh file to be copied or otherwise transported between a Macintosh and another system, and which contains the information required to reconstruct the two forks when the file is returned to the Macintosh environment. It is necessary to preserve the MacBinary header only if the file will one day be returned to a Macintosh environment; otherwise, it can be stripped from the file.

There are actually two MacBinary standards, the original MacBinary and MacBinary II. Both standards have a header that is 128 bytes in length. The MacBinary II header contains additional information not found in the original MacBinary header.

File Organization

The structure of a MacBinary II header is shown below:

typedef struct _MacBinaryIIHeader
{
BYTE   Version;               /* Always set to 0 */
BYTE   FileNameLength;        /* Size of file name (0 to 31) */
BYTE   FileName[63];          /* File name */
DWORD  FileType;              /* Type of Macintosh file */
DWORD  FileCreator;           /* ID of program that created file */
BYTE   FileFlags;             /* File attribute flags */
BYTE   Reserved1;             /* Reserved field */
WORD   FileVertPos;           /* File vertical position in window */
WORD   FileHorzPos;           /* File horizontal position in window */
WORD   WindowId;              /* Window or folder ID */
BYTE   Protected;             /* File protection (1 = protected) */
BYTE   Reserved2;             /* Reserved field */
DWORD  SizeOfDataFork;        /* Size of file data fork in bytes */
DWORD  SizeOfResourceFork;    /* Size of file resource fork in bytes */
DWORD  CreationStamp;         /* Time and date file created */
DWORD  ModificationStamp;     /* Time and date file last modified */
WORD   GetInfoLength;         /* GetInfo message length */
/* The following fields were added for MacBinary II */
WORD   FinderFlags;           /* Finder flags */
BYTE   Reserved3[14];         /* Reserved field */
DWORD  UnpackedLength;        /* Total unpacked file length */
WORD   SecondHeadLength;      /* Length of secondary header */
BYTE   UploadVersion;         /* MacBinary version used with uploader */
BYTE   ReadVersion;           /* MacBinary version needed to read */
WORD   CrcValue;              /* CRC value of previous 124 bytes */
BYTE   Reserved4[2];          /* Reserved field */
} MACBIN2HEAD;

Before extracting the image data from a MacPaint file in a non-Macintosh environment, you must determine if a MacBinary header is prepended. This is best done by reading the bytes at offsets 101 through 125 and checking to see if they are all zero. The byte at offset 2 should be in the range of 1 to 63, and the DWORDs at offsets 83 and 87 should be in the range of 0 to 007FFFFFh. If all of these checks are true, then a MacBinary header is present.

It is not necessary for a non-Macintosh application to modify the MacBinary header unless the image data is changed or the MacPaint file has been created outside of the Macintosh environment with the intent of one day being returned to the Mac. However, it is good general practice to assume that your image file will one day return to the originator platform. Because any application reading a MacPaint file must be prepared to decode the MacBinary header anyway, there is no good reason for omitting it or for failing to update its fields when the file is changed.

File Details

Version, the first byte of a MacBinary header, is always zero; MacPaint files with or without a MacBinary header, always start with a zero byte. In fact, if the first byte is not zero, do not treat the file as a MacPaint file.

FileNameLength stores the length of the Macintosh-format filename, which can be from 1 to 63.

FileName stores the actual filename, and only the first "FileNameLength" characters are significant. Note that the filename is not NULL-terminated. Because the Macintosh can accommodate longer filenames than are found on some systems, a certain amount of intelligence is needed when you copy MacPaint files to filesystems that cannot accommodate the full filename. UNIX and Macintosh programmers, in particular, should be wary of copying files to MS-DOS systems and are advised to keep the filenames limited to eight characters or less. Files destined only for UNIX systems should limit names to 14 or fewer characters.

FileType contains up to four ASCII characters indicating the type of file that is attached to the header. A MacPaint file has a type of PNTG; a PICT file (another Macintosh file type) has type PICT; a TIFF file has type TIFF; and so on.

FileCreator also contains a 4-character ASCII identifier that identifies the creator application. The creator identifier is MPNT for MacPaint files created by the MacPaint paint program, for instance.

FileFlags contains file attributes specific to the Macintosh environment; these are represented by the following bits in the field:

Bit 0 Inited
Bit 1 Changed
Bit 2 Busy
Bit 3 Bozo
Bit 4 System
Bit 5 Bundle
Bit 6 Invisible
Bit 7 Locked

FileVertPos and FileHorzPos contain the position of the file on the display screen.

The WindowID and Protected bit flags are specific to the Macintosh environment.

SizeOfDataFork is the size of the MacPaint file minus the size of the MacBinary header.

SizeOfResourceFork is always zero for MacPaint files.

CreationStamp and ModificationStamp contain the time and date the MacPaint file was first created and last modified, respectively. The stamp values are stored as the number of seconds since January 1, 1904.

GetInfoLength contains the length of the Get Info comment and is set to zero in MacPaint files.

The following fields were added by the MacBinary II standard:

FinderFlags contains the first eight bit flags of the Finder. Finder bit flags 8 through 15 are stored in the FileFlags field.

UnpackedLength is the uncompressed size of the file.

SecondHeadLength holds the length of any additional header following the MacBinary header; this value is for future expansion of the MacBinary header and is currently set to zero.

UploadVersion and ReadVersion contain version numbers of the programs required to transmit and read the MacBinary II header.

CrcValue contains a value that may be used to check the validity of the first 124 bytes of the header and needs to be recalculated if the header is changed. If this field is set to zero, ignore it.

There are four fields in the MacBinary II header marked as reserved. They are used for padding and as space for additional fields in future revisions of the MacBinary header. They should be set to zero, as should all unused fields in the header.

The MacBinary header is followed by four bytes of data (00h, 00h, 00h, 02h) signaling the start of the actual MacPaint file. Following these four bytes are 304 bytes of pattern data. This data is used and modified by paint programs such as MacPaint as pattern palette data and is not used for the reconstruction or display of MacPaint images themselves. There is always data for 38 patterns, and each pattern is eight bytes in length.

Following the pattern data are 204 bytes of zero-byte data used for padding. The MacPaint image data follows this padding and always starts at file offset 640 when a MacBinary header is present. Image data in a MacPaint file is always compressed using a simple byte-wise run-length encoding (RLE) scheme. Each scan line is always 72 bytes in length and there are always 720 scan lines per MacPaint image.

A byte is read and used as the run count. If the most significant bit is set to 1, the byte is converted to its two's-complement value, and the next byte is repeated RunCount times. If the most significant bit is zero, then one is added to the count and the next RunCount bytes are read. We can use the steps shown in the following pseudocode to decode a scan line:


Read a byte value
    If high bit is one
        Count is two's complement of byte (count = ~byte value)
        Read a byte
        Write this byte `count' times
    If high bit is zero
        Count is byte value plus one (count = byte value + 1)
        Read and copy the next `count' bytes
If 72 bytes have been written, the scan line is done

Note that the Macintosh displays black characters on a white background, as opposed to the PC and other systems, which display white characters on a black background; for this reason, it may be necessary to flip the bit values of the image data to obtain the proper color orientation.

For Further Information

For further information about the Macintosh Paint format, see the code examples included on the CD-ROM. You can also contact:

Apple Computer Inc.
20525 Mariani Avenue
Cupertino, CA 95104
Voice: 408-996-1010
Voice: 800-538-9696
FAX: 408-974-1725
WWW: http://www.apple.com/

Additional information on this format can be found in:

Apple Computer, Inside Macintosh: Imaging, Volumes I and V, Addison-Wesley, Reading, MA, 1985.

These volumes are also available on the Apple Developer CDs.

Additional references include:

"MacPaint Documents Format," Macintosh Technical Note #86, Apple Computer Developer Technical Support.

Birse, Cameron, Guillermo Ortiz, and Jon Zap. "Things You Wanted to Know About PackBits," Macintosh Technical Note #71, Apple Computer Developer Technical Support.



Copyright © 1996, 1994 O'Reilly & Associates, Inc. All Rights Reserved.