Converting a Picture to a PPat
Article by Bill Catambay, Pascal Programmer

If you've ever had an inkling to take a picture (PICT) resource and convert it into a ppat resource (to be used as your desktop background, a background in an application window, or to save into a resource fork), this article discusses the process of making that conversion and provides sample code for implementing it.

A PICT resource is generally a record structure made up of a size field (which is obsolete for version 2 type pictures), the picture frame, and a list of op codes which build the picture. The size field is only useful for version 1 type pictures (B&W) because they are under 32K bytes in size. To determine the size of Version 2 type pictures (which can exceed 32K bytes), use the Memory Manager call GetHandleSize.

The PICT resource is referenced by a handle of type PicHandle. A ppat resource is referenced by a handle of type PixPatHandle. To convert a picture to a desktop pattern (i.e., ppat), we need to perform the following steps:

The following program implements the above steps into a procedure called Pict2PPat. The procedure takes two arguments: the resource name of the PICT resource to be converted, and a handle to the new PixPat. The main program creates a window, calls Pict2PPat to create the PixPat, and then fills the window with the pattern. It then waits for a button press to exit the program.

Note: This code was tested using CodeWarrior 7 Pascal.


Program Pict2PPatSample;

Uses
   PictUtils, QDOffscreen, Resources, Fonts, Dialogs;
	
Var
   pathandle:		PixPatHandle;
   myWindow:		WindowPtr;
   thePict:		PicHandle;
	
Procedure Pict2PPat(resname: str255; var thePixPat: PixPatHandle);

Var
   theGWorld: GWorldPtr;
   thePictInfo: PictInfo;
   savedPort: GrafPtr;
   theRect: Rect;
   numBytes: longint;
   savedGWorld: GWorldPtr;
   savedGDH: GDHandle;
   err: OSErr;

   begin
   GetGWorld(savedGWorld, savedGDH);
   {---------------------------}
   { Load the picture resource }
   {---------------------------}
   thePict := PicHandle(Get1NamedResource('PICT', resName));
   if thePict = NIL then
      begin
      if thePixPat <> NIL then
         DisposePixPat(thePixPat);
      thePixPat := NIL;
      exit(Pict2PPat);
      end;
   SetRect(theRect,0,0,64,64);  { Size it for a 64x64 ppat }
   {-------------------------------}
   { Get the picture's color table }
   {-------------------------------}
   err := GetPictInfo(thePict,thePictInfo,returnColorTable,256,
         popularMethod,0);
   if err <> NoErr then
      begin
      ReleaseResource(Handle(thePict));
      exit(Pict2PPat);
      end;
   {--------------------------------------------------------}
   { Create a GWorld to hold the pixel data and the palette }
   {--------------------------------------------------------}
   if NewGWorld(theGWorld, 8, theRect, thePictInfo.theColorTable, 
                nil, 0) <> NoErr then
      begin
      ReleaseResource(Handle(thePict));
      exit(Pict2PPat);
      end;
   {--------------------------------------}
   { Place the pixel data into the GWorld }
   {--------------------------------------}
   SetGWorld(theGWorld, nil);
   EraseRect(theRect);
   DrawPicture(thePict, theRect);
   SetGWorld(savedGWorld, savedGDH);
   {---------------------}
   { Create a new PixPat }
   {---------------------}
   if thePixPat <> NIL then
      DisposePixPat(thePixPat);
   thePixPat := NewPixPat;
   if thePixPat = NIL then
      begin
      DisposeGWorld(theGWorld);
      ReleaseResource(Handle(thePict));
      exit(Pict2PPat);
      end;
   {-------------------------------------------------------------}
   { Move the pixel and color data from the GWorld to the PixPat }
   {-------------------------------------------------------------}
   CopyPixMap(theGWorld^.portPixMap, thePixPat^^.patMap);
   numBytes := BAnd(theGWorld^.portPixMap^^.rowBytes,$3FFF);
   numBytes := numBytes * (theGWorld^.portRect.bottom - theGWorld^.portRect.top);
   thePixPat^^.patData := NewHandleClear(numBytes);
   BlockMove(GetPixBaseAddr(GetGWorldPixMap(theGWorld)), thePixPat^^.patData^, 
      numBytes);
   PixPatChanged(thePixPat);
   DisposeGWorld(theGWorld);
   ReleaseResource(Handle(thePict));
   end; { of Pict2PPAT }
	
Begin
InitGraf(@qd.thePort);
InitFonts;
InitWindows;
InitMenus;
TEInit;
InitDialogs(NIL);
InitCursor;
MaxApplZone;
pathandle := NIL;
myWindow := GetNewCWindow(128, NIL, WindowPtr(-1));
Pict2PPat('Test pict',pathandle);
SetPort(myWindow);
FillCRect(myWindow^.portrect,pathandle);
repeat
until button;
DisposePixPat(pathandle);
End.




Copyright © 1996 Bill M Catambay. All Rights Reserved.