Oct 97 - Tips
Volume Number: 13 (1997)
Issue Number: 10
Column Tag: Tips & Tidbits
Tips & Tidbits
By Steve Sisak
Colorizing Pixmaps in PICT Images
In a progect I am working on, I have a set of PICT resources that are used to draw a background for my app's user interface. The PICT's are used to represent modular panels and the the user is allowed to colorize these backing panels. The code to colorize the backing pixmaps is relatively simple, but the Mac OS provides a gotcha.
The basic technique uses CopyBits to colorize the pixel data by setting the foreground and background colors of the destination port. The problem is that if you set the colors in the port before playing back the picture, the DrawPicture routine undoes your work for you and the pixel data from the PICT is not colorized. The following code uses the QuickDraw bottlenecks to circumvent the problem. To use it, call DrawColorizedPicture instead of DrawPicture and add the colorization colors you want as parameters.
For example:
RGBColor red = {0xffff,0,0};
RGBColor black = {0,0,0};
Rect bounds;
// turn a grayscale image into a red-scale image:
bounds = (**aPicHandle).bounds;
DrawColorizedPicture(aPicHandle, &bounds, &black, &red);
Here is the code that implements DrawColorizedPicture:
// Define some global variables to pass the colorization information
RGBColor gFGColor;
RGBColor gBGColor;
// here is the overriden bottleneck (myQDBitsProcPtr).
// it sets up the color environment before actually coping the pixmap
pascal void myQDBitsProcPtr(BitMap *srcBits, Rect *srcRect,
Rect *dstRect, short mode, RgnHandle maskRgn)
{
GrafPtr curPort;
RGBColor saveFG;
RGBColor saveBG;
GetPort(&curPort); // get the context
// save the fore- and background colors
saveFG = ((CGrafPort*)curPort)->rgbFgColor;
saveBG = ((CGrafPort*)curPort)->rgbBkColor;
RGBForeColor(&gFGColor); // set the foreground color
RGBBackColor(&gBGColor); // set the background color
// call the standard routine
StdBits(srcBits, srcRect, dstRect, mode, maskRgn);
RGBForeColor(&saveFG); // restore the foreground color
RGBBackColor(&saveBG); // restore the background color
}
// DrawColorizedPicture works just like DrawPicture, except it colorizes the
// the pixelmap portions of the picture according to the global variables
// gFGColor and gBGColor. It assumes the target port is a color port
pascal void DrawColorizedPicture(PicHandle ph,
Rect *targetBounds, RGBColor *fg, RGBColor *bg)
{
CQDProcs myProcs; // new bottlenecks
CQDProcs *oldProcs; // saved bottlenecks
GrafPtr curPort; // the active GrafPort
static QDBitsUPP theUPP = NULL; // the UPP for our StdBits replacement
if (theUPP == NULL) { // allocate the UPP if it does not exist
theUPP = NewQDBitsProc(myQDBitsProcPtr);
}
gFGColor = *fg; // communicate colorization to the bottleneck
gBGColor = *bg;
GetPort(&curPort); // find the current port
SetStdCProcs(&myProcs); // initialize the bottleneck record
myProcs.bitsProc = theUPP; // insert our StdBits Bottleneck
// save the previous Bottleneck record
oldProcs = ((CGrafPort*)curPort)->grafProcs;
// attach our bottleneck record
((CGrafPort*)curPort)->grafProcs = &myProcs;
DrawPicture(ph, targetBounds); // draw the picture
// restore the bottlneck record
((CGrafPort*)curPort)->grafProcs = oldProcs;
}
B.J. Buchalter
bj@metric-halo.com