unit AEPicture; interface uses Memory, QuickDraw, Packages, Menus, Events, Fonts, Scrap, ToolUtils,Resources, Errors, Palettes, LowMem, AppleEvents,AEObjects, AERegistry, Errors,macros1,macros2, globals, Utilities,Analysis,Background,Camera,Edit,Filters,File1, File2,Graphics,LUT,Math,PlugIns,Text, Msc, AEUtility, AEWindow; function PictureEvents(var inAppleEvent, reply:AppleEvent; inToken: TokenPtr; inCommand: OSType):OSerr; function PicturePutData(var inAppleEvent, reply:AppleEvent; inToken: TokenPtr):OSerr; function PictureGetData(var inAppleEvent, reply:AppleEvent; inToken: TokenPtr):OSerr; FUNCTION FindPictureAccessor (desiredClass: DescType; containerToken: AEDesc; containerClass: DescType; keyForm: DescType; keyData: AEDesc; VAR outToken: AEDesc; theRefCon: LongInt): OSErr; implementation type AppleEventPtr = ^AppleEvent; ExtendedPtr = ^Extended; BooleanPtr = ^Boolean; PointPtr = ^Point; var gObjIndex:LongInt; function MakeROI(var inAppleEvent:AppleEvent):OSerr; forward; procedure CopyPictureToAnotherWindow(fromROI:Boolean; dst:TokenPtr; TransferModeDesc: DescType; resize:Boolean; pinColor:RGBColor); forward; function TokenWindow(inToken: TokenPtr):WindowPtr; begin TokenWindow := inToken^.containerWindow; end; function TokenInfo(inToken: TokenPtr):InfoPtr; var theWindow:WindowPtr; begin { theWindow := inToken^.containerWindow; if theWindow = nil then TokenInfo := info else TokenInfo := pointer(WindowPeek(theWindow)^.RefCon); } TokenInfo := inToken^.containerInfo; end; function PictureMath(var inAppleEvent:AppleEvent; inKey:AEKeyword; inToken: TokenPtr):OSErr; var theError,ignoreErr:OSErr; theAEToken : AEDesc; theAEObject : AEDesc; pinColor:RGBColor; argToken:TokenPtr; argInfo,dstInfo:InfoPtr; theRect,srcRect:Rect; dstToken:NewObjectPtr; answer:Boolean; begin theError := -1; theError := AEGetParamDesc(inAppleEvent, inKey, 'obj ', theAEObject); if theError = noErr then begin theError := AEResolve (theAEObject, kAEIDoMinimum , @theAEToken); if theError = noErr then begin argToken := TokenPtr(theAEToken.dataHandle^); argInfo := TokenInfo(argToken); if argToken^.containerType = 'cROI' then srcRect := argInfo^.RoiRect else srcRect := argInfo^.PicRect; if inToken^.containerType = 'cROI' then theRect := info^.RoiRect else theRect := info^.PicRect; answer := SectRect(theRect, srcRect, theRect); MathOffset := 0; MathGain := 1; ignoreErr := GetAEExtended(inAppleEvent, 'kOff', MathOffset); ignoreErr := GetAEExtended(inAppleEvent, 'kSca', MathGain); dstInfo := Info; ignoreErr := AEDisposeDesc(theAEObject); ignoreErr := AEGetParamDesc(inAppleEvent, inKey, 'Dest', theAEObject); if ignoreErr = noErr then begin ignoreErr := AEDisposeDesc(theAEToken); ignoreErr := AEResolve (theAEObject, kAEIDoMinimum , @theAEToken); if ignoreErr = noErr then begin dstToken := NewObjectPtr(theAEToken.dataHandle^); if dstToken^.containerWindow = nil then begin if NewPicWindow(dstToken^.fname, theRect.right-theRect.left, theRect.bottom-theRect.top) then begin dstToken^.containerWindow := PicWindow[nPics]; dstToken^.containerInfo := pointer(WindowPeek(PicWindow[nPics])^.RefCon); end; end else dstInfo := dstToken^.containerInfo; end; end; if (CurrentMathOp = SubMath) or (CurrentMathOp = DivMath) then DoMath(Info^.PicNum, argInfo^.PicNum, dstInfo, theRect) else DoMath(argInfo^.PicNum, Info^.PicNum, dstInfo, theRect); with info^ do begin UpdateScreen(theRect); Info^.changes := true; end; SetupRoiRect; end; ignoreErr := AEDisposeDesc(theAEToken); end; ignoreErr := AEDisposeDesc(theAEObject); PictureMath := theError; end; { UNTESTED! } procedure CalibrationEvent(var inAppleEvent:AppleEvent;inToken: TokenPtr); var theError:OSErr; SaveStandards: StandardsArray; theString:str255; begin SaveStandards := StandardValues; theError := GetAEStr255(inAppleEvent, keyDirectObject, theString); if (theString = '') or (theString = 'Dialog') then begin if not DoCalibrateDialog then StandardValues := SaveStandards; end else Calibrate; end; { *************************************************************************************** Handles AppleEvents sent to a window that holds a picture. *************************************************************************************** } function PictureEvents(var inAppleEvent, reply:AppleEvent; inToken: TokenPtr; inCommand: OSType):OSerr; VAR theError,ignoreErr:OSErr; theWindow:WindowPtr; AutoSelectAll:Boolean; OldPicNum, NewPicNum: integer; theString, theName:str255; theShortValue, sStart, sEnd:integer; theExtendedValue:extended; answer, on:Boolean; theEnum:DescType; lastPt, pt:Point; fwidth, i, pic1, pic2, wn, old: integer; theLongValue:LongInt; xAdd, xMul: extended; theAEToken : AEDesc; theAEObject : AEDesc; pinColor:RGBColor; argToken:TokenPtr; argInfo:InfoPtr; theRect,srcRect:Rect; begin if inToken^.name = 'rang' then begin inToken^.name := '----'; for wn := inToken^.thru downto inToken^.index do begin inToken^.containerWindow := PicWindow[wn]; inToken^.containerInfo := pointer(WindowPeek(PicWindow[wn])^.RefCon); PictureEvents := PictureEvents(inAppleEvent, reply, inToken, inCommand); end; exit(PictureEvents); end; theWindow := inToken^.containerWindow; theError := noErr; PictureEvents := noErr; if theWindow = nil then begin PictureEvents := WindowEvents(inAppleEvent, reply, inToken, inCommand); exit(PictureEvents); end; if inCommand = 'AddC' then { ADD } begin CurrentMathOp := AddMath; if PictureMath(inAppleEvent,keyDirectObject,inToken) <> noErr then begin theError := GetAEExtended(inAppleEvent, 'kVal', theExtendedValue); if theError = noErr then DoArithmetic(AddItem, theExtendedValue); end; end else if inCommand = 'AndC' then { AND } begin CurrentMathOp := AndMath; if PictureMath(inAppleEvent,'kArg',inToken) <> noErr then begin theError := GetAEExtended(inAppleEvent, 'kVal', theExtendedValue); if theError = noErr then DoArithmetic(AndItem2, theExtendedValue); end; end else if inCommand = 'AnlP' then AnalyzeParticles { ANALYZE } else if inCommand = 'ALUT' then ApplyLookupTable { APPLY } else if inCommand = 'AutO' then { AUTOOUTLINE } begin theError := GetAEPoint(inAppleEvent, keyDirectObject, pt); AutoOutline(pt); end else if inCommand = 'BinC' then { BINARY } begin ignoreErr := GetAEShortFromEnum(inAppleEvent, keyDirectObject, 206, theShortValue); if ignoreErr <> noErr then theShortValue := 1; ignoreErr := GetAEShort(inAppleEvent, 'nItr', i); if ignoreErr <> noErr then i := 0; BinaryCommand(theShortValue, i); end else if inCommand = 'CVal' then { CHANGEVALUES } begin theError := GetAEShort(inAppleEvent, 'lowr', sStart); theError := GetAEShort(inAppleEvent, 'uppr', sEnd); theError := GetAEShort(inAppleEvent, 'to ', theShortValue); ChangeValues(sStart, sEnd, theShortValue); end else if inCommand = 'Calb' then CalibrationEvent(inAppleEvent, inToken) { CALIBRATE } else if inCommand = 'Chos' then AEisActive := false { CHOOSE } else if (inCommand = 'cler') or (inCommand = 'Fill') or (inCommand = 'Invt') or (inCommand = 'Fram') then begin OptionKeyWasDown := false; { CLEAR } with info^ do { INVERT } begin AutoSelectAll := not RoiShowing; { FILL } if AutoSelectAll then { FRAME } SelectAll(true); if inCommand = 'cler' then begin DoOperation(EraseOp); end else begin old := ForegroundIndex; theShortValue := ForegroundIndex; ignoreErr := GetAEShort(inAPpleEvent,'Colr',theShortValue); if (theShortValue >= 0) and (theShortValue <= 255) then SetForegroundColor(theShortValue); if inCommand = 'Fill' then DoOperation(PaintOp) else if inCommand = 'Invt' then DoOperation(InvertOp) else if inCommand = 'Fram' then DoOperation(FrameOp); SetForegroundColor(old); end; UpdateScreen(RoiRect); if AutoSelectAll then KillRoi else SetupUndo; { ??? Prevents some sort of undo } end; end else if (inCommand = 'clos') or (inCommand = 'Disp') then { CLOSE, DISPOSE } begin if (inCommand = 'Disp') then MacroCommand := DisposeC else MacroCommand := CloseC; OldPicNum := info^.PicNum; if ActivePic then begin StopDigitizing; SaveRoi; end; ignoreErr := GetAEStr255(inAppleEvent, 'kfil', theString); if ignoreErr = noErr then { Close xxx saving in 'bbbb' } begin ignoreErr := GetAEEnum(inAppleEvent, 'mode', theEnum); SetSaveAs(theEnum); SaveAs(theString, DefaultRefNum); end else begin theError := GetAEBoolean(inAppleEvent, 'savo', answer); if (theError = noErr) and (answer = false) then MacroCommand := DisposeC; theError := CloseAWindow(theWindow); if theError = 0 then theError := 1 else theError := noErr; if ActivePic and (nPics >= 1) then begin NewPicNum := OldPicNum - 1; if NewPicNum < 1 then NewPicNum := 1; SelectWindow(PicWindow[NewPicNum]); info := pointer(WindowPeek(PicWindow[NewPicNum])^.RefCon); sCurInfo := info; ActivateWindow; GenerateValues; LoadLUT(info^.cTable); UpdatePicWindow; end; end; end else if inCommand = 'Conv' then { CONVOLVE } begin ignoreErr := GetAEStr255(inAppleEvent, keyDirectObject, theString); if (ignoreErr <> noErr) then theString := ''; RunNamedConvolution(theString); end else if inCommand = 'copB' then { COPYBITS } begin theError := AEGetParamDesc(inAppleEvent, 'Dest', typeWildCard, theAEObject); if theError = noErr then if theAEObject.descriptorType = typeObjectSpecifier then begin theError := AEResolve (theAEObject, kAEIDoMinimum , @theAEToken); theEnum := 'mCop'; ignoreErr := GetAEEnum(inAppleEvent, 'tMod', theEnum); pinColor.red := 32767; pinColor.blue := 32767; pinColor.green := 32767; answer := false; ignoreErr := GetAERGB(inAppleEvent, 'picC', pinColor); ignoreErr := GetAEBoolean(inAppleEvent, 'Rsiz', answer); CopyPictureToAnotherWindow(inToken^.containerType = 'cROI', TokenPtr(theAEToken.dataHandle^),theEnum,answer,pinColor); ignoreErr := AEDisposeDesc(theAEToken); end; ignoreErr := AEDisposeDesc(theAEObject); end else if inCommand = 'CopC' then { COPY IMAGE } begin CurrentMathOp := CopyMath; theError := PictureMath(inAppleEvent,keyDirectObject,inToken); end else if inCommand = 'DivC' then { DIVIDE } begin CurrentMathOp := DivMath; if PictureMath(inAppleEvent,'kArg',inToken) <> noErr then begin theError := GetAEExtended(inAppleEvent, 'kVal', theExtendedValue); if theError = noErr then DoArithmetic(DivideItem, theExtendedValue); end; end else if inCommand = 'Draw' then { DRAW } begin ignoreErr := GetAEPoint(inAppleEvent,'from',pt); if (ignoreErr = noErr) then begin CurrentX := pt.h; CurrentY := pt.v; InsertionPoint.h := CurrentX; InsertionPoint.v := CurrentY + 4; end; ignoreErr := GetAEBoolean(inAppleEvent,'scal',answer); if (ignoreErr = noErr) and answer then DrawScale; ignoreErr := GetAEPoint(inAppleEvent,'Line',pt); if (ignoreErr = noErr) then begin KillRoi; lastPt.h := CurrentX; lastPt.v := CurrentY; CurrentX := pt.h; CurrentY := pt.v; OffscreenToScreen(lastPt); OffscreenToScreen(pt); DrawObject(LineObj, lastPt, pt); end; ignoreErr := GetAEStr255(inAppleEvent, 'name', theString); if ignoreErr= noErr then DoDrawText(theString, true); ignoreErr := GetAEExtended(inAppleEvent,'num ',theExtendedvalue); if ignoreErr = noErr then begin if theExtendedvalue = trunc(theExtendedvalue) then fwidth := 0 else fwidth := precision; RealToString(theExtendedvalue, 1, fwidth, theString); DoDrawText(theString, true); end; end else if inCommand = 'clon' then { DUPLICATE } begin theString := ''; ignoreErr := GetAEStr255(inAppleEvent, 'name', theString); if Duplicate(theString, false) then UpdatePicWindow; i := Info^.pidnum; ignoreErr := AEPutParamPtr(reply, keyDirectObject, typeShortInteger, Ptr(@i), sizeof(integer)); end else if inCommand = 'EnhC' then EnhanceContrast { ENHANCE CONTRAST } else if inCommand = 'EquH' then EqualizeHistogram { EQUALIZE CONTRAST } else if inCommand = 'Expo' then { EXPORT } begin theError := GetAEStr255(inAppleEvent, 'ExpO', theString); if (theError = noErr) then SetExportOptions(theString); theError := GetAEStr255(inAppleEvent, 'name', theName); if theError = noErr then Export(theName, DefaultRefNum) else begin theError := GetAEStr255(inAppleEvent, 'plug', theString); if theError = noErr then LoadExportPlugIn(theString); end; theError := noErr; end else if inCommand = 'Fltr' then begin { FILTER } theError := GetAEShortFromEnum(inAppleEvent, keyDirectObject, 208, theShortValue); if theError = noErr then begin if theShortValue < 13 then FilterCommand(theShortValue) else begin theError := GetAEStr255(inAppleEvent, 'name', theString); if theError = noErr then begin if theShortValue = 13 then RunNamedFilter(theString) else LoadFilterPlugIn(theString); end; end; end; end else if inCommand = 'Flip' then { FLIP } begin theError := GetAEShortFromEnum(inAppleEvent, keyDirectObject, 203, theShortValue); theError := GetAEStr255(inAppleEvent, 'newW', theString); if theError = noErr then begin RotateToNewWindow(FlipRotateType(theShortValue-1)); if Length(theString) > 0 then begin SetWTitle(info^.wptr, theString); info^.title := theString; if ActivePic then begin UpdateWindowsMenuItem; UpdateTitleBar; end; end; i := Info^.pidnum; end else begin FlipOrRotate(FlipRotateType(theShortValue-1)); i := 0; end; theError := AEPutParamPtr(reply, keyDirectObject, typeShortInteger, Ptr(@i), sizeof(integer)); end else if inCommand = 'Info' then GetInfo { GET INFO } else if inCommand = 'Meas' then Measure { MEASURE } else if inCommand = 'Mark' then MarkSelection(mCount) { MARK SELECTION } { theError := GetAEStr255(inAppleEvent, keyDirectObject, theString); theName := ''; theError := GetAEStr255(inAppleEvent, 'ResS', theName); theError := GetAELong(inAppleEvent, 'Pic1', theLongValue); pic1 := theLongValue; theError := GetAELong(inAppleEvent, 'Pic2', theLongValue); pic2 := theLongValue; theError := GetAELong(inAppleEvent, 'ResN', theLongValue); theError := GetAEExtended(inAppleEvent, 'AddC', xAdd); theError := GetAEExtended(inAppleEvent, 'MulC', xMul); RunImageMath(theString,pic1,pic2,xMul,xAdd, theLongValue,theName); if theName = '' then i := Info^.pidnum else i := 0; theError := AEPutParamPtr(reply, keyDirectObject, typeShortInteger, Ptr(@i), sizeof(integer)); end } else if inCommand = 'MinC' then { MINIMUM } begin CurrentMathOp := MinMath; if PictureMath(inAppleEvent,'kArg',inToken) <> noErr then begin theError := GetAEExtended(inAppleEvent, 'kVal', theExtendedValue); if theError = noErr then DoArithmetic(MultiplyItem, theExtendedValue); end; { theError := GetAEExtended(inAppleEvent, keyDirectObject, theExtendedValue); DoArithmetic(MultiplyItem, theExtendedValue); } end else if inCommand = 'MulC' then { MULTIPLY } begin CurrentMathOp := MulMath; if PictureMath(inAppleEvent,'kArg',inToken) <> noErr then begin theError := GetAEExtended(inAppleEvent, 'kVal', theExtendedValue); if theError = noErr then DoArithmetic(MultiplyItem, theExtendedValue); end; { theError := GetAEExtended(inAppleEvent, keyDirectObject, theExtendedValue); DoArithmetic(MultiplyItem, theExtendedValue); } end else if inCommand = 'OrC ' then { OR } begin CurrentMathOp := OrMath; if PictureMath(inAppleEvent,'kArg',inToken) <> noErr then begin theError := GetAEExtended(inAppleEvent, 'kVal', theExtendedValue); if theError = noErr then DoArithmetic(OrItem2, theExtendedValue); end; end else if inCommand = 'past' then { PASTE } begin on := info^.RoiShowing; answer := false; ignoreErr := GetAEBoolean(inAppleEvent, 'ClpS', answer); if answer then ConvertSystemClipboard; answer := false; ignoreErr := GetAEBoolean(inAppleEvent, 'lCap', answer); if on then SaveROI; if answer then PasteLive else DoPaste; ignoreErr := GetAEEnum(inAppleEvent, 'tMod', theEnum); if ignoreErr = noErr then ApplyPasteMath(theEnum); if on then RestoreROI; end else if inCommand = 'SurP' then PlotSurface { PLOT SURFACE} else if inCommand = 'PltP' then { PLOT PROFILE } begin PlotDensityProfile; if PlotWindow <> nil then UpdatePlotWindow; end else if inCommand = 'rvrt' then RevertToSaved { REVERT } else if inCommand = 'save' then { SAVE } begin if ActivePic then StopDigitizing; with info^ do begin ignoreErr := GetAEEnum(inAppleEvent, 'SavQ', theEnum); SetSaveAs(theEnum); ignoreErr := GetAEStr255(inAppleEvent, 'kfil', theString); if ignoreErr = noErr then SaveAs(theString, DefaultRefNum) else SaveFile; end; theError := noErr; end else if inCommand = 'ScRo' then { SCALE } begin rsHScale := 1; rsVScale := 1; rsAngle := 0; rsMethod := NearestNeighbor; ignoreErr := GetAEStr255(inAppleEvent, 'newW', theString); rsCreateNewWindow := ( ignoreErr = noErr ); ignoreErr := GetAEExtended(inAppleEvent, 'xsc ', rsHScale); if (ignoreErr = noErr) then rsVScale := rsHScale; ignoreErr := GetAEExtended(inAppleEvent, 'ysc ', rsVScale); ignoreErr := GetAEExtended(inAppleEvent, 'angl', rsAngle); ignoreErr := GetAEBoolean(inAppleEvent, 'meth', answer); if (ignoreErr = noErr) and answer then rsMethod := Bilinear; ScaleAndRotate; if rsCreateNewWindow then begin if Length(theString) > 0 then begin SetWTitle(info^.wptr, theString); info^.title := theString; if ActivePic then begin UpdateWindowsMenuItem; UpdateTitleBar; end; end; i := Info^.pidnum; end else i := 0; ignoreErr := AEPutParamPtr(reply, keyDirectObject, typeShortInteger, Ptr(@i), sizeof(integer)); end else if inCommand = 'sAll' then { SELECT ALL } begin StopDigitizing; SelectAll(true); end else if inCommand = 'Shad' then { SHADOW } begin theShortValue := 4; {SouthEast is the default } ignoreErr := GetAEShortFromEnum(inAppleEvent, keyDirectObject, 207, theShortValue); ShadowCommand(theShortValue); end else if inCommand = 'SubC' then { SUBTRACT } begin CurrentMathOp := SubMath; if PictureMath(inAppleEvent,keyDirectObject,inToken) <> noErr then begin ignoreErr := GetAEExtended(inAppleEvent, 'kVal', theExtendedValue); if ignoreErr = noErr then DoArithmetic(SubtractItem, theExtendedValue); ignoreErr := GetAEShortFromEnum(inAppleEvent, 'sBac', 211, fwidth); if ignoreErr = noErr then begin theShortValue := BallRadius; ignoreErr := GetAEShort(inAppleEvent, 'diam', theShortValue); FasterBackgroundSubtraction := false; ignoreErr := GetAEBoolean(inAppleEvent, 'fast', FasterBackgroundSubtraction); BallRadius := theShortValue; if BallRadius < 1 then BallRadius := 1 else if BallRadius > 319 then BallRadius := 319; DoBackgroundMenuEvent(fwidth); end; end; end else if inCommand = 'ThrL' then begin theError := GetAEShortFromEnum(inAppleEvent, keyDirectObject, 206, theShortValue); case theShortValue of 1: begin ignoreErr := GetAELong(inAppleEvent, 'of ', theLongValue); if ignoreErr = noErr then begin if (theLongValue < 0) or (theLongValue > 255) then DisableThresholding else EnableThresholding(theLongValue); end end; 2: AutoThreshold; 3: { Threshold Density SLice } begin theLongValue := 127; theError := GetAELong(inAppleEvent, 'lowr', theLongValue); sStart := theLongValue; theLongValue := sStart + 10; ignoreErr := GetAELong(inAppleEvent, 'uppr', theLongValue); sEnd := theLongValue; DisableDensitySlice; DisableThresholding; if (sEnd < sStart) or ((sStart = 0) and (sEnd = 0)) then begin end else if not ((sStart = 255) and (sEnd = 255)) then begin SliceStart := sStart; SliceEnd := sEnd; if SliceStart < 1 then SliceStart := 1; if SliceEnd > 254 then SliceEnd := 254; end; EnableDensitySlice; end; 4: { Threshold Off } if DensitySlicing then DisableDensitySlice else DisableThresholding; end; { case } end else if inCommand = 'Upda' then UpdatePicWindow { UPDATE } else if inCommand = 'XorC' then { XOR } begin CurrentMathOp := XorMath; if PictureMath(inAppleEvent,'kArg',inToken) <> noErr then begin theError := GetAEExtended(inAppleEvent, 'kVal', theExtendedValue); if theError = noErr then DoArithmetic(XorItem2, theExtendedValue); end; end else theError := WindowEvents(inAppleEvent, reply, inToken, inCommand); PictureEvents := theError; end; FUNCTION FindPictureAccessor (desiredClass: DescType; containerToken: AEDesc; containerClass: DescType; keyForm: DescType; keyData: AEDesc; VAR outToken: AEDesc; theRefCon: LongInt): OSErr; VAR theError: OSErr; theName,theWindowName:Str255; theWindow: WindowPtr; theWindowN: integer; iLoop: LongInt; theID: LongInt; theEnum: DescType; theInfo: InfoPtr; theToken: ObjectToken; xval:extended; BEGIN theWindow := nil; IF keyForm = formName THEN BEGIN if (keyData.descriptorType = 'long') or (keyData.descriptorType = 'shor') then begin theError := LongFromDesc(keyData, theID); theName := StringOf(theID:3); for iLoop := 1 to length(theName) do if theName[iLoop] = ' ' then theName[iLoop] := '0'; end else if keyData.descriptorType = 'doub' then begin theError := ExtendedFromDesc(keyData, xval); RealToString(xval,4,1, theName); for iLoop := 1 to length(theName) do if theName[iLoop] = ' ' then theName[iLoop] := '0'; end else theError := StringFromDesc(keyData, theName); if (theError = noErr) then for iLoop := 1 to nPics do BEGIN theInfo := pointer(WindowPeek(PicWindow[iLoop])^.RefCon); { GetWTitle(PicWindow[iLoop], theWindowName); if IUEqualString(theWindowName, theName) = 0 then } if IUEqualString(theInfo^.title, theName) = 0 then begin theWindow := PicWindow[iLoop]; gObjIndex := iLoop; end END; if theWindow = nil then begin MakeNewTokenDesc(theName, 'Ipic', outToken); FindPictureAccessor := noErr; exit(FindPictureAccessor); end; END ELSE IF keyForm = formAbsolutePosition THEN begin if keyData.descriptorType = typeAbsoluteOrdinal then begin theEnum := DescType( LongIntPtr( keyData.dataHandle^ )^ ); theToken.containerType := 'Ipic'; theToken.name := typeNull; theToken.index := 1; theToken.thru := 0; begin { if theEnum = 'any ' then theToken.index := 1 } if theEnum = 'midd' then theToken.index := (nPics + 1) div 2 else if theEnum = 'all ' then begin theToken.name := 'rang'; theToken.thru := nPics; end; end; gObjIndex := theToken.index; theToken.containerWindow := PicWindow[theToken.index]; theToken.containerInfo := pointer(WindowPeek(PicWindow[gObjIndex])^.RefCon); if theToken.containerInfo^.StackInfo <> nil then begin theToken.containerType := 'Stak'; FindPictureAccessor := AECreateDesc('Stak', @theToken, SizeOf(ObjectToken), outToken); end else FindPictureAccessor := AECreateDesc('Ipic', @theToken, SizeOf(ObjectToken), outToken); exit(FindPictureAccessor); end else begin theError := ShortFromDesc(keyData, theWindowN); IF theError = noErr then if (theWindowN < 1) then {oops, passed an ID rather than index } for iLoop := 1 to nPics do begin theInfo := pointer(WindowPeek(PicWindow[iLoop])^.RefCon); if theInfo^.PidNum = theWindowN then begin theWindow := PicWindow[iLoop]; gObjIndex := iLoop; end; end else if theWindowN <= nPics then begin theWindow := PicWindow[theWindowN]; gObjIndex := theWindowN; end; end end ELSE IF keyForm = formRelativePosition THEN begin theError := EnumFromDesc(keyData, theEnum); if (theError = noErr) then begin iLoop := info^.PicNum; if (theEnum = kAENext) and (iLoop < nPics) then iLoop := iLoop + 1; if (theEnum = kAEPrevious) and (iLoop > 1) then iLoop := iLoop - 1; theWindow := PicWindow[iLoop]; gObjIndex := iLoop; END end ELSE IF keyForm = formPropertyID THEN begin theError := LongFromDesc(keyData, theID); if (theError = noErr) then for iLoop := 1 to nPics do BEGIN theInfo := pointer(WindowPeek(PicWindow[iLoop])^.RefCon); if theInfo^.PidNum = theID then begin theWindow := PicWindow[iLoop]; gObjIndex := iLoop; end; END; end else IF keyForm = formRange THEN begin theToken.containerType := 'Ipic'; theToken.name := 'rang'; theToken.index := 1; theToken.thru := 0; theError := GetRange(keyData, theToken.index, theToken.thru); if theToken.index > nPics then theToken.index := nPics; if theToken.thru > nPics then theToken.thru := nPics; theToken.containerWindow := PicWindow[theToken.index]; theToken.containerInfo := pointer(WindowPeek(PicWindow[theToken.index])^.RefCon); FindPictureAccessor := AECreateDesc('Ipic', @theToken, SizeOf(ObjectToken), outToken); exit(FindPictureAccessor); end; IF theWindow = NIL THEN FindPictureAccessor := errAENoSuchObject ELSE {create outToken that identifies the window} BEGIN theInfo := pointer(WindowPeek(PicWindow[gObjIndex])^.RefCon); if theInfo^.StackInfo <> nil then begin theToken.containerType := 'Stak'; MakeTokenDesc(theWindow, 'Stak', outToken); end else MakeTokenDesc(theWindow, 'Ipic', outToken); FindPictureAccessor := noErr; end END; procedure ChangePictureSize(width, height: integer); var WasDigitizing: boolean; begin with Info^ do begin SetPort(wptr); WasDigitizing := digitizing; StopDigitizing; InvalRect(wrect); if width = 0 then width := wrect.right - wrect.left; if height = 0 then height := wrect.bottom - wrect.top; with trect do begin top := 0; left := 0; right := width; bottom := height; end; if ScaleToFitWindow then begin ScaleImageWindow(trect); wrect := trect; end else begin if trect.right > PicRect.right * magnification then trect.right := trunc(PicRect.right * magnification); if trect.bottom > PicRect.bottom * magnification then trect.bottom := trunc(PicRect.bottom * magnification); wrect := trect; SizeWindow(wptr, wrect.right, wrect.bottom, true); WindowState := NormalWindow; if WasDigitizing then StartDigitizing; end; InvalRect(wrect); end; {with info^} end; function PictureGetData(var inAppleEvent, reply:AppleEvent; inToken: TokenPtr):OSerr; VAR theError:OSErr; theValueL:LongInt; theValueX:extended; theState : boolean; theInfo: InfoPtr; theWindow: WindowPtr; theValue, kind, i,j: integer; theName:str255; theEnum:DescType; theLUT:LutArray; theArray:ShortArray; theList:AEDescList; theRect:Rect; pt1,pt2:Point; begin theError := errAEDescNotFound; PictureGetData := errAEDescNotFound; with inToken^ do begin theWindow := containerWindow; if theWindow = nil then theInfo := info { no window, but can access default tables } else theInfo := containerInfo; if name = 'Cal?' then begin theState := theInfo^.fit <> uncalibrated; theError := AEPutParamPtr(reply, keyDirectObject, typeBoolean, Ptr(@theState), sizeof(Boolean)); end else if name = 'picN' then theError := ReturnShortProperty(reply, theInfo^.PicNum) else if name = 'pidN' then theError := ReturnShortProperty(reply, theInfo^.PidNum) else if name = 'pixS' then { PIXEL SCALE } begin if info^.SpatiallyCalibrated then theError := ReturnExtendedProperty(reply, theInfo^.xScale) else theError := ReturnExtendedProperty(reply, 1.0) end else if name = 'pixU' then { PIXEL UNITS } begin if info^.SpatiallyCalibrated then theName := info^.xUnit else theName := 'pixel'; theError := AEPutParamPtr(reply, keyDirectObject, 'TEXT', Ptr(@theName[1]), length(theName)); end else if name = 'pixA' then { ASPECT RATIO } begin if info^.SpatiallyCalibrated then theError := ReturnExtendedProperty(reply, theInfo^.PixelAspectRatio) else theError := ReturnExtendedProperty(reply, 1.0); end else if name = 'Red ' then { RED } begin CheckIndex(index,1,256); if thru > 0 then begin theError := AECreateList(nil, 0,false,theList); CheckIndex(thru,1,256); for i := index to thru do begin theValue := band(bsr(theInfo^.cTable[i-1].rgb.red,8), 255); theError := AEPutPtr( theList, 0, typeShortInteger, Ptr(@theValue), sizeof(integer) ); end; theError := AEPutParamDesc( reply, keyDirectObject, theList ); end else begin theValue := band(bsr(theInfo^.cTable[index - 1].rgb.red,8), 255); theError := ReturnShortProperty(reply, theValue); end; end else if name = 'Gree' then { GREEN } begin CheckIndex(index,1,256); if thru > 0 then begin theError := AECreateList(nil, 0,false,theList); CheckIndex(thru,1,256); for i := index to thru do begin theValue := band(bsr(theInfo^.cTable[i-1].rgb.green,8), 255); theError := AEPutPtr( theList, 0, typeShortInteger, Ptr(@theValue), sizeof(integer) ); end; theError := AEPutParamDesc( reply, keyDirectObject, theList ); end else begin theValue := band(bsr(theInfo^.cTable[index - 1].rgb.green,8), 255); theError := ReturnShortProperty(reply, theValue); end; end else if name = 'Blue' then { BLUE } begin CheckIndex(index,1,256); if thru > 0 then begin theError := AECreateList(nil, 0,false,theList); CheckIndex(thru,1,256); for i := index to thru do begin theValue := band(bsr(theInfo^.cTable[i-1].rgb.blue,8), 255); theError := AEPutPtr( theList, 0, typeShortInteger, Ptr(@theValue), sizeof(integer) ); end; theError := AEPutParamDesc( reply, keyDirectObject, theList ); end else begin theValue := band(bsr(theInfo^.cTable[index - 1].rgb.blue,8), 255); theError := ReturnShortProperty(reply, theValue); end; end else if name = 'pFGC' then theError := ReturnShortProperty(reply, ForegroundIndex) { FOREGROUND } else if name = 'pBGC' then theError := ReturnShortProperty(reply, BackgroundIndex) { BACKGROUND } else if name = 'pLnW' then theError := ReturnShortProperty(reply, LineWidth) { LINE WIDTH } else if name = 'pale' then begin { PALETTE } theEnum := 'cust'; if info^.LUTMode = GrayScale then theEnum := 'gray' else if info^.LUTMode = CustomGrayScale then theEnum := 'gray' else if info^.LUTMode = ColorLUT then theEnum := 'sys ' else if info^.LUTMode = PseudoColor then case info^.ColorTable of AppleDefault: theEnum := 'sys '; Pseudo20: theEnum := 'ps20'; Pseudo32: theEnum := 'ps32'; Rainbow: theEnum := 'rain'; Fire1: theEnum := 'Fir1'; Fire2: theEnum := 'Fir2'; Ice: theEnum := 'ice '; Grays: theEnum := 'gr8 '; Spectrum: theEnum := 'spec'; end; theError := AEPutParamPtr(reply, keyDirectObject, typeEnumerated, Ptr(@theEnum), sizeof(theEnum)); end else if name = 'cPix' then { PIXEL } begin if thru <> 0 then begin pt1 := Point(index); pt2 := Point(thru); theError := AECreateList(nil, 0,false,theList); for i := pt1.v to pt2.v do for j := pt1.h to pt2.h do begin theValue := MyGetPixel( j, i); theError := AEPutPtr( theList, 0, typeShortInteger, Ptr(@theValue), sizeof(integer) ); end; theError := AEPutParamDesc( reply, keyDirectObject, theList ); end else begin pt1 := Point(index); theValue := MyGetPixel( pt1.h, pt1.v); theError := ReturnShortProperty(reply, theValue); end; end else begin if theWindow <> nil then theError := WindowGetData(inAppleEvent, reply, inToken); { inherit ! } end end; PictureGetData := theError; end; function PicturePutData(var inAppleEvent, reply:AppleEvent; inToken: TokenPtr):OSerr; VAR theError:OSErr; theInfo: InfoPtr; theWindow: WindowPtr; theXVal:extended; theValue, i, k:integer; theAEProp: AEDesc; theName:str255; theRect:Rect; theList:AEDescList; theReturnedType:DescType; theActualSize:Size; typeCode:DescType; itemsInList, n:LongInt; pt1,pt2:Point; begin PicturePutData := noErr; with inToken^ do begin theWindow := containerWindow; if theWindow = nil then theInfo := info { no window, but can access default tables } else theInfo := containerInfo; if name = 'pnam' then begin theError := AEGetParamDesc(inAppleEvent, 'data', 'TEXT', theAEProp); theError := StringFromDesc(theAEProp, theName); SetWTitle(theWindow, theName); theInfo^.title := theName; if theInfo^.PictureType <> FrameGrabberType then theInfo^.PictureType := NewPicture; UpdateWindowsMenuItem; UpdateTitleBar; end else if name = 'pixS' then {PixelScale} else if name = 'pixS' then begin theXVal := GetExtendedProperty(inAppleEvent); with theInfo^ do if theXVal >= 0.0 then begin xScale := theXVal; SpatiallyCalibrated := (xUnit <> '') and (xUnit <> 'pixel') and (xUnit <> 'pixels') and (xScale <> 0.0); UpdateTitleBar; end; end else if name = 'pixU' then begin {ScaleUnits} theError := AEGetParamDesc(inAppleEvent, 'data', 'TEXT', theAEProp); theError := StringFromDesc(theAEProp, theName); if theName = '' then SetScale else with theInfo^ do begin MakeLowerCase(theName); TruncateString(theName, maxUnit); xUnit := theName; SpatiallyCalibrated := (xUnit <> '') and (xUnit <> 'pixel') and (xUnit <> 'pixels') and (xScale <> 0.0); end end else if name = 'pixA' then begin {AspectRatio } theXVal := GetExtendedProperty(inAppleEvent); with theInfo^ do begin if theXVal > 0.0 then begin PixelAspectRatio:= theXVal; yScale := xScale / PixelAspectRatio; end else begin PixelAspectRatio := 1.0; yScale := xScale; {???} end end; end { else if name = 'rTyp' then theError := ReturnEnumProperty(reply,210,integer(info^.RoiType)) } else if name = 'Red ' then begin theError := AEGetParamDesc(inAppleEvent, keyDirectObject, typeAEList, theList); theError := AECountItems(theList, itemsInList); if index< 0 then index := 256 - index + 1; if thru = 0 then thru := index; for i := index to thru do begin theError := AEGetNthPtr( theList, i, typeShortInteger, typeCode, theReturnedType, Ptr(@theValue), Sizeof(integer), theActualSize ); if (i > 0) and (i <= 256) then theInfo^.cTable[i-1].rgb.red := bsl(thevalue,8); end; end else if name = 'Gree' then begin theError := AEGetParamDesc(inAppleEvent, keyDirectObject, typeAEList, theList); theError := AECountItems(theList, itemsInList); if index< 0 then index := 256 - index + 1; if thru = 0 then thru := index; for i := index to thru do begin theError := AEGetNthPtr( theList, i, typeShortInteger, typeCode, theReturnedType, Ptr(@theValue), Sizeof(integer), theActualSize ); if (i > 0) and (i <= 256) then theInfo^.cTable[i-1].rgb.green := bsl(thevalue,8); end; end else if name = 'Blue' then begin theError := AEGetParamDesc(inAppleEvent, keyDirectObject, typeAEList, theList); theError := AECountItems(theList, itemsInList); if index< 0 then index := 256 - index + 1; if thru = 0 then thru := index; for i := index to thru do begin theError := AEGetNthPtr( theList, i, typeShortInteger, typeCode, theReturnedType, Ptr(@theValue), Sizeof(integer), theActualSize ); if (i > 0) and (i <= 256) then theInfo^.cTable[i-1].rgb.blue := bsl(thevalue,8); end; end else if name = 'pale' then begin { PALETTE } theValue := GetEnumProperty(inAppleEvent, 201); if theValue = 0 then ResetGrayMap else SwitchColorTables(theValue, true); end else if name = 'wide' then begin theValue := GetShortProperty(inAppleEvent,10,10000); ChangePictureSize(theValue, 0); end else if name = 'hite' then begin theValue := GetShortProperty(inAppleEvent,10,10000); ChangePictureSize(0,theValue); end else if name = 'pFGC' then begin theValue := GetShortProperty(inAppleEvent,0,255); SetForegroundColor(theValue); end else if name = 'pBGC' then begin theValue := GetShortProperty(inAppleEvent,0,255); SetbackgroundColor(theValue); end else if name = 'pLnW' then begin theValue := GetShortProperty(inAppleEvent,0,10000); if theValue > 0 then begin LineWidth := theValue; ShowLIneWidth; end; end else if name = 'cPix' then if thru = 0 then begin pt1 := Point(index); theValue := GetShortProperty(inAppleEvent,0,255); PutPixel(pt1.h, pt1.v, theValue); end else begin theError := AEGetParamDesc(inAppleEvent, keyDirectObject, typeAEList, theList); theError := AECountItems(theList, itemsInList); if thru <> 0 then begin pt1 := Point(index); pt2 := Point(thru); n := 1; for i := pt1.v to pt2.v do for k := pt1.h to pt2.h do begin if n <= itemsInList then theError := AEGetNthPtr( theList, n, typeShortInteger, typeCode, theReturnedType, Ptr(@theValue), Sizeof(integer), theActualSize ); PutPixel(k, i, theValue); n := n + 1; end; end; end else PicturePutData := WindowPutData(inAppleEvent, reply, inToken); { check inherited stuff } end; end; function WhichPicWindow( inWindow : WindowPtr): integer; var i:integer; begin for i := 1 to nPics do if PicWindow[i] = inWindow then begin WhichPicWindow := i; exit(WhichPicWindow); end; WhichPicWindow := 0; end; { Ref ROI Showing? Source Destination Pict no no copy picture to picture Pict yes no copy ROI to same location Pict no yes copy picture masked by destination region Pict yes yes copy ROI ROI no no no operation ROI yes no copy ROI to top left corner ROI no yes kill roi in destination ROI yes yes copy sqeezing into destination } procedure CopyToAnotherWindow(dstInfo:InfoPtr; SrcRect,DestRect:Rect; inRegion:RgnHandle;TransferMode:integer); var dstPort: cGrafPtr; begin with Info^ do begin if TransferMode = SrcCopy then begin pmForeColor(BlackIndex); pmBackColor(WhiteIndex); end; dstPort := dstInfo^.osPort; CopyBits(BitMapHandle(osPort^.portPixMap)^^, BitMapHandle(dstPort^.PortPixMap)^^, SrcRect, DestRect, TransferMode, inRegion); if TransferMode = SrcCopy then begin pmForeColor(ForegroundIndex); pmBackColor(BackgroundIndex); end; end; end; procedure GetDestination(dst:TokenPtr; var outRect:Rect; var outRegion:RgnHandle); var dstPort: cGrafPtr; begin with TokenInfo(dst)^ do begin if RoiShowing then begin outRect := RoiRect; outRegion := RoiRgn; end else outRect := PicRect; end; end; procedure CopyPictureToAnotherWindow(fromROI:Boolean; dst:TokenPtr; TransferModeDesc: DescType; resize:Boolean; pinColor:RGBColor); var dstPort: cGrafPtr; theRegion:RgnHandle; dstInfo:InfoPtr; srcInfo:InfoPtr; SrcRect,DstRect:Rect; TransferMode:integer; begin TransferMode := 0; if TransferModeDesc = 'mCop' then TransferMode := srcCopy else if TransferModeDesc = 'mOR ' then TransferMode := srcOr else if TransferModeDesc = 'mXOR' then TransferMode := srcXOr else if TransferModeDesc = 'mAND' then TransferMode := NotSrcBic else if TransferModeDesc = 'mRep' then TransferMode := Transparent else if TransferModeDesc = 'mDit' then TransferMode := srcCopy + ditherCopy else if TransferModeDesc = 'mAdO' then TransferMode := addOver else if TransferModeDesc = 'mAd+' then TransferMode := addMax else if TransferModeDesc = 'mAd-' then TransferMode := adMin else if TransferModeDesc = 'mSbO' then TransferMode := subOver else begin if TransferModeDesc = 'mBnd' then TransferMode := Blend else if TransferModeDesc = 'mAdP' then TransferMode := addPin else if TransferModeDesc = 'mSbP' then TransferMode := subPin; OpColor(pinColor); end; theRegion := nil; dstInfo := TokenInfo(dst); DstRect := dstInfo^.PicRect; if dst^.containerType = 'cROI' then DstRect := dstInfo^.RoiRect; with Info^ do begin if fromROI then begin SrcRect := RoiRect; theRegion := RoiRgn; if resize then if dst^.containerType = 'cROI' then begin dstInfo^.RoiType := RectRoi; dstInfo^.RoiRect := SrcRect; DstRect := SrcRect; end; end else begin SrcRect := PicRect; if resize then begin dstInfo^.RoiType := RectRoi; dstInfo^.RoiRect := SrcRect; DstRect := SrcRect; end; end; CopyToAnotherWindow(dstInfo,SrcRect,DstRect, theRegion, TransferMode); end; end; end.