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:
- Load the picture resource into a handle.
- Obtain the color table for the picture.
- Create a new GWorld with the picture's color table.
- Draw the picture into the new GWorld.
- Create a handle to a new pixel pattern (PixPat).
- Copy the PixMap of the GWorld to the new PixPat map.
- Copy the picture data to the PixPat data.
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.