home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac-Source 1994 July
/
Mac-Source_July_1994.iso
/
HyperCard
/
MaskImage
/
MaskImage.mod
< prev
Wrap
Text File
|
1991-12-21
|
7KB
|
274 lines
IMPLEMENTATION MODULE MaskImage;
(*
HyperCard external to combine a foreground and background
image according to an anti-aliased mask. Call this XFCN
from HyperCard as follows:
MaskImage(Foreground, Background, Mask[, Depth])
where Foreground, Background and Mask are picture IDs,
for example created by PictureFromScrap, and Depth is
the pixel depth at which to generate the result image
(default is 16). The function result is a new picture ID
representing the composite image.
Written by LDO 1991 December 15.
Took out automatic centring of images 1991 December 21.
*)
FROM Types IMPORT
noErr,
OSErr,
Rect;
FROM QuickDraw IMPORT
ditherCopy,
srcCopy,
CTabHandle,
GDHandle,
PicHandle,
ClosePicture,
CopyBits,
CopyMask,
DisposeCTable,
DrawPicture,
EraseRect,
GetCTable,
OpenPicture;
IMPORT
QDOffscreen;
FROM QDOffscreen IMPORT
GWorldFlags,
GWorldPtr,
DisposeGWorld,
GetGWorld,
LockPixels,
NewGWorld,
SetGWorld;
FROM ToolUtils IMPORT
FixRatio;
FROM HyperXCmd IMPORT
XCmdPtr;
FROM Useful IMPORT
IgnoreBoolean;
FROM HCUseful IMPORT
GetIntArg,
ReturnError;
FROM MaskImageCommon IMPORT
PictureToZero,
ZeroToPicture;
PROCEDURE TheProc
(
ParamPtr : XCmdPtr
);
(* entry point for the external. *)
VAR
ForegroundPicture, BackgroundPicture, MaskPicture : PicHandle;
PixelDepth : INTEGER;
ResultPicture : PicHandle;
Err : OSErr;
PROCEDURE GetArgs;
BEGIN
ForegroundPicture := ZeroToPicture(ParamPtr, ParamPtr^.params[1]);
BackgroundPicture := ZeroToPicture(ParamPtr, ParamPtr^.params[2]);
MaskPicture := ZeroToPicture(ParamPtr, ParamPtr^.params[3]);
PixelDepth := GetIntArg(ParamPtr, 4, 16)
END GetArgs;
PROCEDURE GenerateResult;
VAR
PreviousGWorld : GWorldPtr;
PreviousGDevice : GDHandle;
LargeMaskGWorld, SmallMaskGWorld : GWorldPtr;
ForegroundGWorld, ResultGWorld : GWorldPtr;
LargeMaskBounds, SmallMaskBounds : Rect;
LargeSrcBounds, SmallSrcBounds : Rect;
ResultBounds : Rect;
PROCEDURE InitStorage;
BEGIN
LargeMaskGWorld := NIL;
SmallMaskGWorld := NIL;
ForegroundGWorld := NIL;
ResultGWorld := NIL
END InitStorage;
PROCEDURE DisposeStorage;
BEGIN
IF LargeMaskGWorld <> NIL THEN
DisposeGWorld(LargeMaskGWorld)
END (*IF*);
IF SmallMaskGWorld <> NIL THEN
DisposeGWorld(SmallMaskGWorld)
END (*IF*);
IF ForegroundGWorld <> NIL THEN
DisposeGWorld(ForegroundGWorld)
END (*IF*);
IF ResultGWorld <> NIL THEN
DisposeGWorld(ResultGWorld)
END (*IF*)
END DisposeStorage;
PROCEDURE MagnifyRect
(
VAR SrcRect : Rect;
VAR ResultRect : Rect
);
(* sets ResultRect to SrcRect magnified 4x. *)
BEGIN
ResultRect.top := SrcRect.top * 4;
ResultRect.left := SrcRect.left * 4;
ResultRect.bottom := SrcRect.bottom * 4;
ResultRect.right := SrcRect.right * 4
END MagnifyRect;
PROCEDURE NewGreyIndexedGWorld
(
VAR Result : GWorldPtr;
PixelDepth : INTEGER; (* 1, 2, 4 or 8 *)
VAR Bounds : Rect
);
(* creates a new GWorld with a colour table
consisting of a uniform grey ramp at the
specified pixel depth. *)
VAR
GreyTable : CTabHandle;
BEGIN
GreyTable := GetCTable(32 + PixelDepth);
Err := NewGWorld
(
(*@offscreenGWorld :=*) Result,
(*PixelDepth :=*) PixelDepth,
(*@boundsRect :=*) Bounds,
(*cTable :=*) GreyTable,
(*aGDevice :=*) NIL,
(*flags :=*) GWorldFlags{QDOffscreen.useTempMem}
);
DisposeCTable(GreyTable)
END NewGreyIndexedGWorld;
BEGIN (*GenerateResult*)
GetGWorld(PreviousGWorld, PreviousGDevice);
InitStorage;
LOOP (*once*)
SmallSrcBounds := ForegroundPicture^^.picFrame;
SmallMaskBounds := MaskPicture^^.picFrame;
MagnifyRect(SmallSrcBounds, LargeSrcBounds);
MagnifyRect(SmallMaskBounds, LargeMaskBounds);
(* draw the black-and-white mask at 4x actual size *)
NewGreyIndexedGWorld(LargeMaskGWorld, 1, LargeSrcBounds);
IF Err <> noErr THEN
EXIT
END (*IF*);
IgnoreBoolean(LockPixels(LargeMaskGWorld^.portPixMap));
SetGWorld(LargeMaskGWorld, NIL);
EraseRect(LargeMaskGWorld^.portRect);
DrawPicture(MaskPicture, LargeMaskBounds);
(* dither the mask down to the right size with anti-aliased edges *)
NewGreyIndexedGWorld(SmallMaskGWorld, 4, SmallSrcBounds);
IF Err <> noErr THEN
EXIT
END (*IF*);
IgnoreBoolean(LockPixels(SmallMaskGWorld^.portPixMap));
SetGWorld(SmallMaskGWorld, NIL);
CopyBits
(
(*@srcBits :=*) LargeMaskGWorld^.portBits,
(*@dstBits :=*) SmallMaskGWorld^.portBits,
(*@srcRect :=*) LargeMaskGWorld^.portRect,
(*@dstRect :=*) SmallMaskGWorld^.portRect,
(*mode :=*) srcCopy + ditherCopy,
(*maskRgn :=*) NIL
);
(* free up some unneeded memory *)
DisposeGWorld(LargeMaskGWorld);
LargeMaskGWorld := NIL;
(* image the foreground picture into a gworld the same size as the mask *)
Err := NewGWorld
(
(*@offscreenGWorld :=*) ForegroundGWorld,
(*PixelDepth :=*) PixelDepth,
(*@boundsRect :=*) SmallSrcBounds,
(*cTable :=*) NIL,
(*aGDevice :=*) NIL,
(*flags :=*) GWorldFlags{QDOffscreen.useTempMem}
);
IF Err <> noErr THEN
EXIT
END (*IF*);
IgnoreBoolean(LockPixels(ForegroundGWorld^.portPixMap));
SetGWorld(ForegroundGWorld, NIL);
EraseRect(ForegroundGWorld^.portRect);
DrawPicture(ForegroundPicture, SmallSrcBounds);
(* now to combine everything *)
ResultBounds := BackgroundPicture^^.picFrame;
Err := NewGWorld
(
(*@offscreenGWorld :=*) ResultGWorld,
(*PixelDepth :=*) PixelDepth,
(*@boundsRect :=*) ResultBounds,
(*cTable :=*) NIL,
(*aGDevice :=*) NIL,
(*flags :=*) GWorldFlags{QDOffscreen.useTempMem}
);
IF Err <> noErr THEN
EXIT
END (*IF*);
IgnoreBoolean(LockPixels(ResultGWorld^.portPixMap));
SetGWorld(ResultGWorld, NIL);
EraseRect(ResultGWorld^.portRect);
DrawPicture(BackgroundPicture, ResultBounds);
CopyMask
(
(*@srcBits :=*) ForegroundGWorld^.portBits,
(*@maskBits :=*) SmallMaskGWorld^.portBits,
(*@dstBits :=*) ResultGWorld^.portBits,
(*@srcRect :=*) ForegroundGWorld^.portRect,
(*@maskRect :=*) SmallMaskGWorld^.portRect,
(*@dstRect :=*) SmallSrcBounds
);
(* free up more unneeded memory *)
DisposeGWorld(SmallMaskGWorld);
SmallMaskGWorld := NIL;
DisposeGWorld(ForegroundGWorld);
ForegroundGWorld := NIL;
(* now to build the result into a picture *)
ResultPicture := OpenPicture(ResultGWorld^.portRect);
CopyBits
(
(*@srcBits :=*) ResultGWorld^.portBits,
(*@dstBits :=*) ResultGWorld^.portBits,
(*@srcRect :=*) ResultGWorld^.portRect,
(*@dstRect :=*) ResultGWorld^.portRect,
(*mode :=*) srcCopy + ditherCopy,
(*maskRgn :=*) NIL
);
ClosePicture;
(* all done *)
EXIT
END (*LOOP*);
DisposeStorage;
SetGWorld(PreviousGWorld, PreviousGDevice)
END GenerateResult;
BEGIN (*TheProc*)
GetArgs;
GenerateResult;
IF Err = noErr THEN
ParamPtr^.returnValue := PictureToZero(ParamPtr, ResultPicture)
ELSE
ReturnError(ParamPtr, Err)
END (*IF*)
END TheProc;
END MaskImage.