Path: utzoo!attcan!uunet!cs.utexas.edu!usc!elroy.jpl.nasa.gov!mipl3!dfs059
From: dfs059@ipl.jpl.nasa.gov (Dan Stanfill)
Newsgroups: comp.sys.mac.programmer
Subject: Re: Color QuickDraw, PICT2's and the Clipboard
Message-ID: <6577@ipl.jpl.nasa.gov>
Date: 10 Aug 89 09:51:27 GMT
Organization: Jet Propulsion Laboratory, Image Processing Lab
Lines: 86

hpoppe@bierstadt.ucar.edu (Herb Poppe) asks how to get the palette for
a PICT before drawing it with DrawPicture.

I also struggled with this problem for a while, before I came up with
the following (very ugly) solution.  I thought my solution was pretty
weird, but I was quite happy when I found out that the folks at NCSA
use the exact same technique.  If anyone knows a better technique,
please post it!

This technique applies to disk files, but could be extended to the
clipboard as well.

The secret is to use SetStdCProcs() to intercept calls to CopyBits().  I 
use the spooling technique described in IM-V as well, so my code looks
like the following:

  SetStdCProcs(&myProcs);
  dstPort->grafProcs = (QDProcsPtr) &myProcs;
  myProcs.getPicProc = (Ptr)ReadPictData;
  if (srcPort == dstPort)
    myProcs.bitsProc = (Ptr)MyCopyBits;	   /* only for screen updates	*/


srcPort and dstPort are a bit of weirdness I use to check whether or not
I am printing.  Note that if you spool from disk you should use a buffering
scheme to read in the pict file in a big chunk in ReadPictData(), otherwise
it will be excruciatingly slow.  You can then write MyCopyBits() to look
something like the following:

/************************************************************************/
pascal void MyCopyBits(srcBits, srcRect, dstRect, mode, maskRgn)
  PixMapPtr	srcBits;
  Rect		*srcRect, *dstRect;
  short		mode;
  RgnHandle	maskRgn;
{
  PaletteHandle	pal;
  CGrafPtr	dstPort;
  CTabHandle	ctab;

  GetPort(&dstPort);
  pal = GetPalette(dstPort);      /* check to see if palette already exists */
  if (pal == NIL)
  {
    ctab = srcBits->pmTable;
    if (ctab != NIL)
    {
      pal = NewPalette(256, ctab, pmTolerant, 0);
      FreeSomeColors(pal);
      SetPalette(dstPort, pal, TRUE);
      ActivatePalette(dstPort);
    }
  }
  StdBits(srcBits, srcRect, dstRect, mode, maskRgn);
  return;
}
/************************************************************************/

FreeSomeColors() is my own routine to keep any window from sucking up all
256 colors (this allows color menus, desktops, etc., to still look ok).

Finally, after your call to DrawPicture(), be sure to reset the std procs:

  dstPort->grafProcs = NIL;


The code above has a flaw; if a picture has more than one CopyBits call
with more than one palette, only the first one is used.  I find that
most of the time that is ok, though.  The only problem I have had is with
the output from some scanner software, which, being pre-32-bit-quickdraw,
draw 24 bit data as a series of three CopyBits with red, green, and blue
ramps, respectively.  If your pict file is a 32 bit pict, you won't get
a color table, so you ought to handle that as well.  The default palette
works reasonably when you don't have any knowledge of the color content of
an image.

Good luck!

Dan Stanfill
Visualization and Earth Sciences Applications Group
Image Processing and Applications and Development Section
Jet Propulsion Laboratory

dfs@flower.jpl.nasa.gov
dan@dial.jpl.nasa.gov
dfs059@ipl.jpl.nasa.gov