[comp.sys.mac.programmer] Color PICT cluts

olson@endor.harvard.edu (Eric K. Olson) (04/11/89)

I am writing some code to display 8-bit color PICT files on a Mac II.
I need to get the color lookup table information from the PICT somehow.
What is the approved way of doing this?  I remember PixelPaint used to
not do this correctly, and someone wrote a program called PictPal that
stripped out the clut and put it into a resource that PixelPaint expected.

I would prefer not to interpret the PICT OpCodes directly.  It seems that
I should be hooking into the StdBits routine or creating a GDevice with
a very maleable pallette. 

Does anyone have any hints for me?

Thanks in advance.

-Eric


          Lexington Software Design:  Tomorrow's Software Yesterday

      Eric K. Olson     olson@endor.harvard.edu     harvard!endor!olson
         (Name)                (Arpanet)                 (Usenet)

liberte@zaphod.ncsa.uiuc.edu (04/13/89)

> I need to get the color lookup table information from the PICT somehow.
> What is the approved way of doing this?  

I am writing PalEdit, which is a color table editor.  One of the
things it can now do is Paste in a PICT resource, in which case it
just grabs the last clut that it finds in the PICT.  It uses a StdBits
function.  Below is the code I use.

I would like to be able to read and write files and clipboards in
whatever formats are expected by various applications that deal with
color tables and palettes.  However, documentation for these
applications does not usually describe these formats.

Dan LaLiberte
National Center for Supercomputing Applications
liberte@ncsa.uiuc.edu
-----------------------
static Boolean clutFound;  /* will be true if a clut is found by ClutGrabber */

/*pascal void StdBits (BitMap *srcBits, 
			Rect *srcRect, 
			Rect *dstRect, 
			short mode, RgnHandle maskRgn);
			*/

pascal ClutGrabber(
    PixMap * srcBits,
    Rect	*srcRect,
    Rect 	*destRect,
    short	mode,
    RgnHandle	maskRgn);
    
/* grab clut from pixMap */
/* This is a temporary replacement for StdBits. */
pascal ClutGrabber(srcBits, srcRect, destRect, mode, maskRgn)
    PixMap * srcBits;
    Rect	*srcRect, *destRect;
    short	mode;
    RgnHandle	maskRgn;
{
    if ((*srcBits).rowBytes & 0x8000)
    { /* its a pixMap */
    	CTab2CTab((*srcBits).pmTable, (**PalPM).pmTable);
    	clutFound = TRUE;
    }
}


void PalEdPaste(void);

void PalEdPaste()
{
    PScrapStuff scrapInfo;
    CTabHandle	tempCTab;
    long	result;
    long	offset;

    scrapInfo = InfoScrap();
    
    if (scrapInfo->scrapSize < 0) return;
    
    /* should check if scrap is on disk, and load it if it is */
    if (scrapInfo->scrapSize == 0) {
    	if (LoadScrap() != noErr) return;
    	}
    
    /* try to get a clut resource */
    tempCTab = (CTabHandle)(AllocHandle(sizeof(FullColorTable)));
    if (tempCTab == nil) 
    	goto nospaceexit;

    result = GetScrap((Handle) tempCTab, (ResType) 'clut', &offset);
    if (result > 0)
    {
/* do something with it... */
    	Changed = TRUE;
    	RecordCTable();
    	CTab2CTab(tempCTab, (**PalPM).pmTable);
    	SetPals(PalEdWindow);
    	PalToAltColors();
    	computePlot();
    	PlotUpdate();
    	PalEdActivate(TRUE);
    	}
    
    else { 
    	PicHandle	pict;
    	Rect		r, srcRect;

    	SetRect(&r, 0, 0, 1, 256);
 
     	/* try to get a PICT resource */
     	result = GetScrap(nil, (ResType)'PICT', &offset);
    	if (result > 0) {
    		CQDProcs	cProcs;	/* standard low-level drawing routines */
    		CGrafPtr	tempPortPtr;	/* for offscreen copybits */
    		CGrafPort	tempPort;
    		PixMapHandle	tempPM;
    		long		numbytes;
    		WindowPtr	savePort;

     		pict = (PicHandle) (AllocHandle(result));
     	
    		result = GetScrap((Handle) pict, (ResType)'PICT', &offset);
    		/* get any clut that the PICT might have in it */
    		
    		GetPort(&savePort);
    
    		/* create offscreen port for drawing in */
    		tempPortPtr = &tempPort;
    		OpenCPort(tempPortPtr);
    		tempPM = NewPixMap();
    		HLock(((Handle)tempPM));
    
    		(**tempPM).rowBytes = 256 + 0x8000; /* pix map */
    		(**tempPM).bounds = r;
    		(**tempPM).pmTable = DefaultCTab;
    
          	/* allocate the new pixelmap space */
    		(**tempPM).baseAddr = AllocPointer(256);
    		if ((**tempPM).baseAddr == nil) 
    			goto errorexit;
    		HUnlock(((Handle)tempPM));
    		tempPort.portPixMap = tempPM;
    
    		/* use alternate bitsProc to grab clut from pixmap */
    		SetStdCProcs(&cProcs);
    		cProcs.bitsProc = (Ptr)&ClutGrabber;
    		tempPort.grafProcs = (QDProcsPtr)&cProcs; /* should be CQDProcsPtr */
    		
    		clutFound = FALSE;
    		
    		RecordCTable();
    		DrawPicture(pict, &r);
    	
    		SetPort(savePort);

    		/* the new clut should be in place now */
    		if (clutFound) {
/* do something with it... */
    			Changed = TRUE;
    		 	EraseOldSelection();
    			SetPals(PalEdWindow);
    			PalToAltColors();
    			computePlot();
    			PlotUpdate();
    			PalEdActivate(TRUE);
    			}

    		DisposPtr((**tempPM).baseAddr);
    		
    	errorexit:
    		CloseCPort(tempPortPtr); /* This disposes the tempPM too */
    		SetPort(savePort);
    	}
    	KillPicture(pict);
    }

    DisposHandle((Handle) tempCTab);
    nospaceexit: ;
}