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