FatBits
Volume Number: 3
Issue Number: 9
Column Tag: Bit Map Graphics
A FatBits Editor & Clipboard Viewer in C 
By Tom Saxton, University of Utah, Salt Lake City, UT
Editing BitMaps
At the heart of high-speed graphics on the Macintosh is the bitMap structure.
Data stored in bitMaps and pushed around with CopyBits form the basis for much of the
drawing that occurs on the Macintosh screen. Being able to create bitMaps for
inclusion into a program and being able to eidt such things is of great importance in
many applications. MacPaint, and offspring, offer a way of doing this which is less than
ideal for small bitMaps. The following program sets up a bitMap, allows the user to
edit the bitMap in a manner similar to FatBits in MacPaint, then writes out the bitMap
data in hexadecimal in a format suitable for RMaker.
Fig. 1 Our bit map editor at work
There are numerous variations possible. With a call to SFGetFile(), followed by
some Resource Manager calls, the user could open up any resource file and then open
up any of several types of resource based on bitMaps, such as ICONs, and PATs and edit
them. It would also be possible to edit objects such as ICN#’s and CURS’s, which
consists of slightly more complicated data structures. With some modification, this
program could also form the basis for a FatBits feature in a bit-mapped graphics
program. One could also give the user a dialog box with which to set the size of the
desired bitMap, initialize a data structure to hold the requested bitMap, then let the
user edit it. When done, the program would then dump the bitMap out in hex, which
could then be put into a program as data for a CopyBits call to draw figures on the
screen. Instead of writing the bitMap to a disk file, the edited bitMap could be added to a
resource file in an appropriate format. It wouldn’t take much work (in principle at
least!) to reproduce the ICON, ICN#, PAT, and CURS editing functions of ResEdit in a
much smaller program. Be careful when fiddling around with resource files, Scott
Knaster’s “How to Write Macintosh Software,” (Hayden Books) has some invaluable
tips and hints. This program was originally written over a year ago with that in mind,
but I kept crashing the system with my Resouce manager calls. I’m almost brave
enough to give it another try after reading Knaster’s book.
The Bit Map Object
In what follows, we will be working with a bitMap whose number of rows and
columns are ‘nRows’ and ‘nCols’ respectively. In C we represent the BitMap structure
as
QDPtr baseAddr;
short rowBytes;
Rect bounds;
“baseAddr” is a pointer to the BitMap’s raw data. “rowBytes” is the number of
bytes in each row of the bitMap. There must be an even number of bytes in each row,
so we have to pad BitMaps whose width is not a multiple of 16 bits. To calculate
rowBytes from the number of columns in a BitMap, we use the following formula:
rowBytes = ( (nCols-1)/16 + 1 ) * 2;
The size needed to store the data for the BitMap is then rowBytes*nRows.
“bounds” is a rectangle which determines the QuickDraw coordinates put onto the
BitMap. The coordinates of the upper left corner of bounds become the coordinates of
the upper left corner of the BitMap. Also,
bounds.bottom = bounds.top + nRows;
bounds.right = bounds.left + nCols;
For simplicity, I assign bounds.top = bounds.left = 0.
Once we know the size of the desired BitMap in terms of nRows and nCols, we
know how much memory to allocate and how to fill in the BitMap data structure. The
routine getMap() does these things. To alter the size of the BitMap, and/or its initial
contents alter getMap(). For this example, I build a 32 x 32 bitMap, then load in ICON
#1 (from the System file), which is the ‘NoteIcon’ used in the NoteAlert. Since I call
DetachResource() on the handle I get, any editing done on the ICON will have no effect
on the actual resource. In a real-life situation, you would probably want to make a
copy of the ICON, so as to not clobber something which might be in use by a desk
accessory.
Editing the Bit Map
After the BitMap is called, we call editMap() which sets up a window for editing
the BitMap then goes into an event loop. Mouse clicks are passed to editBits(), which is
the heart of the program. Activate events are handled in a very simplistic way which
would need to be beefed up to support multiple windows. Update events for the window
are processed by doUpdate(), the other routine of interest. Since there are no other
windows with which to generate update events (after the first one), if the user hits the
backspace key, an update event is generated, just to make sure doUpdate() works
correctly after the bitMap has been edited.
editBits() takes a BitMap and a window pointer. It assumes that the BitMap is
currently displayed in the window and that the mouse has just been pressed within the
window. It then calculates where the mouse was pressed and what bit of the BitMap is
represented by the location of the mouse click. It then accesses the BitMap through
GetPixel() to determine if that bit is on or off. If it was off, the routine tracks the
mouse and turns on every bit it runs across until the mouse is released. If the first bit
was already on, it turns contacted bits off. As the mouse moves around, the routine
constantly calculates what bit in the BitMap is being hit. If the current bit needs to be
changed, it is changed as is the rectangle that represents it in the window.
When the close box on the window is clicked, the program calls SFPutFile() to
get a destination file, then outputs the contents of the bit map in an RMaker format
which could then be used to generate a resource with the BitMap data. The resource
format is one that I made up. It consists of two two-byte integers representing the the
number of rows and columns, followed by the (possibly padded) BitMap data, one row
on each line. It would be quite easy to modify this code to put out data for an ICON, or
ICN#, or other existing resource type. As mentioned earlier, the edited bitMap could
also be put directly into a resource file.
The FatBitsFeature
To implement a FatBits feature into a graphics program, it would probably be
easiest to copy the selected bits to a fresh BitMap, let the user edit them, then copy
them back into the document. Alternatively, one could edit the larger BitMap directly,
but modify editBits() to edit only some sub-rectangle of the BitMap and to deal with