TweetFollow Us on Twitter

MacPaint files
Volume Number:1
Issue Number:7
Column Tag:C Workshop

MacPaint file format

By Keith McGreggor

The MacPaint file format is rapidly becoming the standard for transferring graphic information from one application to another. This article will explain that format and show you how to transfer your own images into MacPaint files.

A Little Bit of QuickDraw

The Macintosh’s screen is a bit image. That is, what appears on the screen is actually a collection of consecutive bits in memory that the hardware in the Mac interprets as screen dots (or pixels). If the value of one of these bits is 1, then the pixel corresponding to it will be black. If the bit is 0, then the pixel will be white.

Figure #1. Bits represent pixels

The Mac screen is 512 pixels wide by 342 pixels tall. The bit image in memory takes up 175,104 bits (or 21,888 bytes with 8 bits per byte). We can consider the screen bit image as being 342 rows with 64 bytes per row. Due to the 68000 microprocessor in the Macintosh, every bit image must have an even number of bytes per row, and the rows must begin and end on word boundaries.

In C, the easiest way to define a bit image is with an array of characters. For example, if we wanted to define the Macintosh screen’s bit image, the definition would be:

Figure #2. C definition of a bit image

Bit images are manipulated by Quick- Draw through the use of bitmaps. A bit- map is a structure which points to a bit image and associates a coordinate system with it. The definition of a bitmap is:

Figure #3. C definition of a bitmap

The baseAddr field points to the first byte (character) in the bit image. The rowBytes field contains the number of bytes per row in the bit image. The rectangle bounds provides the coordinate system for the bits. The top left corner of the rectangle is aligned with the first bit of the bit image.

Since we can treat bit images in C as arrays of characters, we don’t always have to display them immediately. You can easily create a picture in a bit image off-screen, and later in your program “stamp” it onto the Mac’s screen.

The Macintosh’s ROM contains several QuickDraw calls that allow you to manipulate bitmaps (on- or off-screen). We’ll look at two of these later in the program.

MacPaint images are kept in the data fork of a MacPaint file. The file is essentially a 512 byte header followed by a bit image that is 576 pixels wide by 720 pixels tall (or 72 bytes by 720 rows).

Figure #4. The MacPaint File Format

The 512 bytes of header contain version information, pattern definitions, and an unused area for future expansion. If you change the contents of this section with care, you can set up your own patterns. If the version number is zero, the default patterns are used. If the number is not zero, then the patterns in the header are used.

Fig.#5.The Paint File Header Format

The MacPaint file bit image is considerably larger than the Macintosh screen’s bit image. In fact, if you were to store a bit image 72 bytes by 720 rows directly onto disk, each MacPaint file would take a minimum of 52K bytes! To make these files smaller, each row of pixels has been compressed using the PackBits routine in the Macintosh ROM. Using PackBits, the typical MacPaint file compresses down to around 10K bytes.

Dipping in the Bit Bucket

To make your program transfer an image into a MacPaint file, you need only to copy the bitmap containing the image into the compressed MacPaint file format. To be able to do this, you need to use two ROM routines, CopyBits and PackBits.

CopyBits transfers the contents of one bitmap into another. If you want, you can specify a mask region in the destination bitmap to prevent CopyBits from destroying the entire image. CopyBits will shrink or expand the contents of the source bitmap to fit the destination bitmap’s rectangle. To call CopyBits from C, use this format:

Figure #6. Calling CopyBits from C

where “copymode” is one of the source transfer modes:

Figure #7. Source Transfer Modes

PackBits compacts a string of bytes by compressing runs of equal bytes. You call PackBits from C like so:

Figure #8. Calling PackBits from C

where “numbytes” is the number of bytes pointed to by “srcPtr.”

Initially, “dstPtr” should point to the first destination byte. The PackBits routine will move “dstPtr” to point to the next available byte. To find out how much space the original bytes were compacted into, you need to subtract the original location of “dstPtr” from its current location.

Fig. #9 How PackBits moves “dstPtr”

About the Program

This program will demonstrate how to “cut” a part of an image into a MacPaint file. It is written for the Consulair Mac C system and Toolkit. You’ll probably need to change things a bit to make it work with other versions of C.

The program opens a single window and draws a few inverted rectangles in it. Then, a gray flashing rectangle will appear and follow the position of the cursor. Use the mouse to position this rectangle where you want, and then press the mouse button. The image inside the rectangle will be cut from the screen (using CopyBits) and transferred into a MacPaint file called “DummyFileName” (using repeated calls to PackBits).

The key routine, MakePaintFile, takes as input a C string containing a filename, and a pointer to a bitmap of arbitrary size. It then creates that file (if possible) on the active disk drive, sets the file signature and type to a MacPaint file type, and compresses that bitmap into the file using PackBits. If the bitmap is smaller than 576 by 720 (as will usually be the case), the bitmap is padded with white space. If the bitmap is larger than 576 by 720, the bitmap is clipped to 576 by 720.

/*
 * MakePaint.h
 *        a C routine to create a MacPaint file
 *        from a given bitmap
 *
 * (c) 1985 by Keith McGreggor for MacTutor
 *       
 */

#define WRITEONLY 7

MakePaintFile( myfilename, mybitmap )
char myfilename[63];
struct ABitMap *mybitmap;
{
 char dstbuf[511],srcbuf[511];
 char *srcPtr;
 char *dstPtr;
 char *mypointer;
 short i,j,dstBytes;
 FILE myfile;
 short t,b,vsize,hsize;
 
// attempt to create the file
 
 myfile = creat( myfilename, WRITEONLY );
 if (myfile != 0) {

// turn the file into a MacPaint file
// and write out a 512 byte header
// full of zeros (we’re not using any of
// our own patterns)

    SetFileSignature(myfilename,’MPNT’); 
    SetFileType(myfilename,’PNTG’);
    for (i = 0; i < 512; i++) fputc(0,myfile);

// figure out how big the bitmap is and set up
// a general pointer to the bit image

    mypointer = mybitmap->baseAddr;
    hsize = mybitmap->rowBytes;
    vsize = (mybitmap->bounds.bottom)
                        - (mybitmap->bounds.top);

// now, write out 720 rows of bytes

    for (j = 1; j <= 720; j++) {

// reinitialize source and destination pointers

 srcPtr = &srcbuf[0];
 dstPtr = &dstbuf[0];

// copy the next row of bytes into srcbuf[],
// clipping or expanding where necessary

 for (i = 0; i < 72; i++) {
        if ((i < hsize) && (j <= vsize)) {
      srcbuf[i] = *mypointer;
           mypointer++;
           }
            else srcbuf[i] = 0;  // 8 white bits
 }

// compress srcbuf[] into dstbuf[]

 #PackBits(&srcPtr,&dstPtr,72);

// figure out how much compression occurred 
// and write those bytes out to the file

 dstBytes= (short)(dstPtr-&dstbuf[0]);
 for (i = 0; i < dstBytes; i++)
                   fputc(dstbuf[i],myfile);
    }

// all 720 lines have been written, so
// close up everything and return

    close(myfile);
 }
}




 /*    CutToPaint.C
  *      A sample program to illustrate
  *      the use of PackBits and CopyBits
  *
  * (c) 1985 by Keith McGreggor for MacTutor
  */
  #Options -N
  #include “Stdio.h”
  #include “MacCdefs.h”
  #include “Window.h”
  #define TRUE 0xFF
  _#define BUTTONNOTPRESSED !#Button()
  #define GRAY &(QD->gray)
  
  // allocate the application’s window
  
  WindowPtr mywindow;
  Rect mywindowrect = { 40, 5, 300, 507 };
  
  // allocate the tracking variables
  
  Rect trackingrect{0,0,100,100};
  short globx,globy,incx,incy;
  
  // allocate a bitmap and bit image to
  // hold the cut bits
  
  struct ABitMap{
   char *baseAddr;
 short  rowbytes;
 Rect bounds;
 };
 
  struct ABitMap targetmap;
  char theactualbits[14][100];
  
  #include “MakePaint.h”
  /* ------------------------------------*/
  // draw some inverted rectangles
  // just to have something to “cut”
  
  DrawSomeStuff()
  {
  Rect temprect;
  short i;
  
  #MoveTo(10,240);
  #DrawString(“\020Press the button!”);
  for (i=0;i<200;i += 10) {
   #SetRect(&temprect,i+20,i+20,i+100,i+40);
 #InvertRect(&temprect);
 }
  }
  
  /*------------------------------------*/
  // Open a window for drawing
  // and do general housekeeping
  
  InitializeOurSystem()
  {
  #InitDialogs(0);
  mywindow = (WindowPtr)#NewWindow(0,  &mywindowrect,”\021A Window for 
bits”,  TRUE,0,-1,TRUE,0);
  #SetPort(mywindow);
  DrawSomeStuff();
  #FlushEvents(-1,0);
  #InitCursor();
  #PenSize(2,2);   // set up pen for
  #PenMode(patXor);  // drawing the
  #PenPat(GRAY);   // ghost rectange
  }

  /*------------------------------------*/
  // Draw the ghost rectangle
  
  DrawCurrentPosition()
  {
  #FrameRect(&trackingrect);
  }

  /*--------------------------------------*/
  // Find out where the mouse is and
  // update global variables
  
  GetNewMouse()
  {
  Point mypoint;
  
  #GetMouse(&mypoint);
  #GlobalToLocal(&mypoint);
  incx = mypoint.h-globx;
  incy = mypoint.v-globy;
  globx = mypoint.h;
  globy = mypoint.v;
  }

  /*------------------------------------*/
  // move the ghost rectange to track
  // the motion of the mouse
  
  UpdatePostion()
  {
  #OffsetRect(&trackingrect,incx,incy);
  }
  
  /*------------------------------------*/
  // First, move around a ghost rectange
  // until the button is pressed.
  // Then, create a bitmap and copy
  // whatever is inside the rectange to
  // the bitmap.
  
  CutARectangle()
  {
  globx = 0;
  globy = 0;
  while (BUTTONNOTPRESSED) {
   DrawCurrentPosition();
 GetNewMouse();
 DrawCurrentPosition();
 UpdatePosition();
  }
  #FlushEvents(-1,0);
  #LocalToGlobal(&trackingrect.topleft);
  #LocalToGlobal(&trackingrect.botRight);
  targetmap.baseAddr = &theactualbits[0][0];
  targetmap.rowBytes = 14;
  targetmap.bounds.left = 0;
  targetmap.bounds.top = 0;
  targetmap.bounds.right = trackingrect.right-trackingrect.left;
  targetmap.bounds.bottom = trackingrect.bottom-   trackingrect.top;
  
  // mywindow -> portBits is the Macintosh screen bit image
  
  #CopyBits(&(mywindow->portBits), &targetmap,
   &trackingrect,
 &(targetmap.bounds),
 srcCopy,
 0);
  }
  
  /*------------------------------------*/
  // call makepaintfile to save the
  // bitmap away as a macpaint file
  // named “dummyfilename”
  // (note: see MakePaint.h listing)
  
  SaveItAway()
  {
  MakePaintFile(“DummyFileName”,&targetmap);
  }
  
  /*----------------------------------*/
  // Our main program
  
  main()
  {
   InitializeOurSystem();
 CutARectangle();
 SaveItAway();
 #ExitToShell();
  }
 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Dash 4.0.1 - Instant search and offline...
Dash is an API documentation browser and code snippet manager. Dash helps you store snippets of code, as well as instantly search and browse documentation for almost any API you might use (for a full... Read more
Tinderbox 7.0.0 - Store and organize you...
Tinderbox is a personal content management assistant. It stores your notes, ideas, and plans. It can help you organize and understand them. And Tinderbox helps you share ideas through Web journals... Read more
Apple Remote Desktop Client 3.9 - Client...
Apple Remote Desktop Client is the best way to manage the Mac computers on your network. Distribute software, provide real-time online help to end users, create detailed software and hardware reports... Read more
Sparkle 2.1.1 - $79.99
Sparkle will change your mind if you thought building websites wasn't for you. Sparkle is the intuitive site builder that lets you create sites for your online portfolio, team or band pages, or... Read more
1Password 6.5.5 - Powerful password mana...
1Password is a password manager that uniquely brings you both security and convenience. It is the only program that provides anti-phishing protection and goes beyond password management by adding Web... Read more
WhatRoute 2.0.15 - Geographically trace...
WhatRoute is designed to find the names of all the routers an IP packet passes through on its way from your Mac to a destination host. It also measures the round-trip time from your Mac to the router... Read more
Art Text 3.2.2 - $49.99
Art Text is graphic design software specifically tuned for lettering, typography, text mockups and various artistic text effects. Supplied with a great variety of ready to use styles and materials,... Read more
Tinderbox 7.0.0 - Store and organize you...
Tinderbox is a personal content management assistant. It stores your notes, ideas, and plans. It can help you organize and understand them. And Tinderbox helps you share ideas through Web journals... Read more
1Password 6.5.5 - Powerful password mana...
1Password is a password manager that uniquely brings you both security and convenience. It is the only program that provides anti-phishing protection and goes beyond password management by adding Web... Read more
Apple Remote Desktop Client 3.9 - Client...
Apple Remote Desktop Client is the best way to manage the Mac computers on your network. Distribute software, provide real-time online help to end users, create detailed software and hardware reports... Read more

Tiny Striker: World Football Guide - How...
| Read more »
Good news everyone! Futurama: Worlds of...
Futurama is finding a new home on mobile in TinyCo and Fox Interactive's new game, Futurama: Worlds of Tomorrow. They're really doing it up, bringing on board Futurama creator Matt Groening along with the original cast and writers. TinyCo wants... | Read more »
MUL.MASH.TAB.BA.GAL.GAL (Games)
MUL.MASH.TAB.BA.GAL.GAL 1.0 Device: iOS Universal Category: Games Price: $2.99, Version: 1.0 (iTunes) Description: ENDLESS UPGRADES. CONSTANT DANGER. ANCIENT WISDOM. BOUNCY BALLS. Launch Sale, 40% OFF for a very limited time!!! MUL.... | Read more »
Dungeon Rushers (Games)
Dungeon Rushers 1.0 Device: iOS Universal Category: Games Price: $4.99, Version: 1.0 (iTunes) Description: Dungeon Rushers is a 2D tactical RPG combining dungeon crawler’s gameplay and turn based fights. Manage your team, loot dusty... | Read more »
Blasty Bubs is a colorful Pinball and Br...
QuickByte Games has another arcade treat in the works -- this time it's a mishmash of brick breaking and Pinball mechanics. It's called Blasty Bubs, and it's a top down brickbreaker that has you slinging balls around a board. [Read more] | Read more »
Corsola and Heracross are the new region...
Generation 2 finally launched in Pokémon GO, unleashing a brand new batch of Pokémon into the wild. Even before the update went live people were speculating on how to catch elusive Pokémon like the legendary "dogs", Unknown, and whether or not... | Read more »
The Warlock of Firetop Mountain (Games)
The Warlock of Firetop Mountain 1.0 Device: iOS Universal Category: Games Price: $4.99, Version: 1.0 (iTunes) Description: An epic adventure through a mysterious mountain filled with monsters, magic and mayhem! “...it looks downright... | Read more »
Fantasy MMORPG MU Origin’s receives a hu...
Developer Webzen are looking to take their highly popular fantasy battler MU Origin to the next level this month, with its most ambitious overhaul yet. The latest update introduces the long sought after Server Arena, new treasure dungeons, and much... | Read more »
RPG Djinn Caster (Games)
RPG Djinn Caster 1.0.0 Device: iOS Universal Category: Games Price: $4.99, Version: 1.0.0 (iTunes) Description: SPECIAL PRICE 38% OFF(USD 7.99 -> USD 4.99)!!!A Fantasy Action RPG of far foreign lands! Summon the Djinns and rise to... | Read more »
Alto's Odyssey gets its first trail...
There's finally video evidence of Alto's Odyssey, the follow up to the 2015 App Store hit, Alto's Adventure. It looks just as soothing and atmospheric as Alto's last outing, but this time players will be journeying to the desert. Whereas Alto's... | Read more »

Price Scanner via MacPrices.net

Apple’s New iPad Ads Don’t Address Pro Users’...
Apple launched a new tranche of iPad Pro TV ads last week addressing actual queries and challenges from the Twitterverse, albeit using actors for the visuals. That’s great. As an iPad fan and heavy... Read more
Free Verbum Catholic Bible Study App For iOS
The Verbum mobile app runs on Logos’ powerful Bible software and is an advanced resource for mobile Catholic study. The Verbum app surrounds the Bible with the Tradition. Verbum comes with 15 free... Read more
27-inch Apple iMacs on sale for up to $200 of...
B&H Photo has 27″ Apple iMacs on sale for up to $200 off MSRP, each including free shipping plus NY sales tax only: - 27″ 3.3GHz iMac 5K: $2099.99 $200 off MSRP - 27″ 3.2GHz/1TB Fusion iMac 5K: $... Read more
15-inch 2.2GHz Retina MacBook Pro on sale for...
Amazon has 2015 15″ 2.2GHz Retina MacBook Pros (MJLQ2LL/A) available for $1849.99 including free shipping. Apple charges $1999 for this model, so Amazon’s price is represents a $150 savings. Read more
Apple refurbished iPad Air 2s available start...
Apple has Certified Refurbished iPad Air 2 WiFis available for starting at $319 including free shipping. A standard Apple one-year warranty is included: - 16GB iPad Air 2 WiFi: $319 $60 off original... Read more
Apple refurbished iPad Pros available for up...
Apple has Certified Refurbished 9″ and 12″ Apple iPad Pros available for up to $160 off the cost of new iPads. An Apple one-year warranty is included with each model, and shipping is free: - 32GB 9″... Read more
Apple restocks refurbished 2015 and 2016 13-i...
Apple has Certified Refurbished 2015 and 2016 13″ MacBook Airs available starting at $759. An Apple one-year warranty is included with each MacBook, and shipping is free: - 2016 13″ 1.6GHz/8GB/128GB... Read more
13-inch 2.5GHz MacBook Pro (Apple refurbished...
Apple has Certified Refurbished 13″ 2.5GHz MacBook Pros (MD101LL/A) available for $829, or $270 off original MSRP. Apple’s one-year warranty is standard, and shipping is free: - 13″ 2.5GHz MacBook... Read more
QuickerTek Announces 5TB Apple AC AirPort Tim...
QuickerTek Inc. has announced their new 5TB hard drive upgrade for Apple’s AC AirPort Time Capsule. By customer request, this upgrade also features six external antennas and offers the highest... Read more
Apple Certified Refurbished iMacs available f...
Apple has Certified Refurbished 2015 21″ & 27″ iMacs available for up to $350 off MSRP. Apple’s one-year warranty is standard, and shipping is free. The following models are available: - 21″ 3.... Read more

Jobs Board

*Apple* Retail - Multiple Positions - Apple,...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
Manager *Apple* Systems Administration - Pu...
Req ID 3315BR Position Title Manager, Apple Systems Administration Job Description The Manager of Apple Systems Administration oversees the administration and Read more
*Apple* Retail - Multiple Positions - Apple,...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
Manager *Apple* Systems Administration - Pu...
Req ID 3315BR Position Title Manager, Apple Systems Administration Job Description The Manager of Apple Systems Administration oversees the administration and Read more
*Apple* Technician - nfrastructure (United S...
Let’s Work Together Apple Technician This position is based in Portland, ME Life at nfrastructure At nfrastructure, we understand that our success results from our Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.