<<>> <> <> <> <> <<>> DIRECTORY Args, Buttons, Commander, Controls, Convert, CtBasic, CtDispatch, CtMap, CtMisc, CommanderOps, FileNames, FS, G2dBasic, Icons, Imager, IO, ImagerSample, MessageWindow, Real, RealFns, Rope, TEditSelection, TiogaMenuOps, ViewerClasses, ViewerOps, ViewerTools; CtToolCommandsImpl: CEDAR PROGRAM IMPORTS Args, Buttons, Controls, Convert, CtBasic, CtDispatch, CtMap, CtMisc, FileNames, FS, Icons, ImagerSample, Imager, IO, MessageWindow, Real, RealFns, Rope, TEditSelection, TiogaMenuOps, ViewerOps, ViewerTools ~ BEGIN <> CommandProc: TYPE ~ Commander.CommandProc; ButtonList: TYPE ~ Controls.ButtonList; IntegerPair: TYPE ~ CtBasic.IntegerPair; PixelArray: TYPE ~ CtBasic.PixelArray; RGB: TYPE ~ CtBasic.RGB; SampleMaps: TYPE ~ CtBasic.SampleMaps; Cmap: TYPE ~ CtMap.Cmap; Comp: TYPE ~ CtMap.Comp; Mouse: TYPE ~ CtMisc.Mouse; SampleMap: TYPE ~ ImagerSample.SampleMap; SampleBuffer: TYPE ~ ImagerSample.SampleBuffer; ROPE: TYPE ~ Rope.ROPE; Viewer: TYPE ~ ViewerClasses.Viewer; <> awakeWord: ROPE ~ "AWAKE "; asleepWord: ROPE ~ "ASLEEP"; pixelBName: ROPE ~ "Pixel:"; -- name of pixel button mapredBName: ROPE ~ "mR:"; -- name of red cmap button mapgrnBName: ROPE ~ "mG:"; -- name of green cmap button mapbluBName: ROPE ~ "mB:"; -- name of blue cmap button zoomBName: ROPE ~ "Zoom:"; -- name of zoom button <<8-bit buttons>> rawBName: ROPE ~ "Gray:"; -- name of raw pixel value button <<24-bit buttons>> redBName: ROPE ~ "bR:"; -- name of red button grnBName: ROPE ~ "bG:"; -- name of green button bluBName: ROPE ~ "bB:"; -- name of blue button fixed: Imager.Font ~ Imager.FindFontScaled["xerox/pressfonts/Gacha-mrr", 12.0]; boldFixed: Imager.Font ~ Imager.FindFontScaled["xerox/pressfonts/Gacha-brr", 12.0]; arrow: Imager.Font ~ Imager.FindFontScaled["xerox/pressfonts/Arrows-mrr", 12.0]; <> Tool: TYPE ~ REF ToolRep; ToolRep: TYPE ~ RECORD [ <> outer: Viewer ¬ NIL, -- parent viewer outerData: Controls.OuterData ¬ NIL, -- parent viewer <> zoomFactor: NAT ¬ 1, -- current replication sUL: IntegerPair ¬ [], -- screen co-ords of UL pixel pUL: IntegerPair ¬ [], -- pixel co-ords of the UL pixel center: IntegerPair ¬ [], -- center of color display <> poi: IntegerPair ¬ [], -- point of (current) interest raw: INTEGER ¬ 0, -- current rawscale value (8bpp) rawrgb: RGB ¬ [0, 0, 0], -- current rgb value (24bpp) maprgb: RGB ¬ [0, 0, 0], -- colormap entries for poi awake: BOOL ¬ TRUE, -- on/off conditional <> maps: SampleMaps ¬ NIL, -- color display sample maps rMap, gMap: SampleMap ¬ NIL, -- 8 bit red and green maps (copy) paR, paG, paB: PixelArray ¬ NIL, -- working image opaR, opaG, opaB: PixelArray ¬ NIL, -- original image colorMap: Cmap ¬ NIL, -- color display colormap <> cursorLooks: CursorLooks ¬ onesAreBlack -- how to show the cursor ]; <> ToolCmd: CommandProc ~ { GetFBContents: PROC ~ { IO.PutRope[cmd.out, "Getting memory - please wait a moment..."]; d.maps ¬ CtBasic.GetColorDisplayMaps[]; SELECT d.maps.bpp FROM 8 => { d.paR ¬ CtBasic.PixelArrayFromSampleMap[d.maps[0].map]; d.opaR ¬ CtBasic.PixelArrayFromSampleMap[d.maps[0].map]; }; 24 => { [d.rMap, d.gMap] ¬ CtBasic.RedAndGrnFromRG[d.maps[0].map]; d.paR ¬ CtBasic.PixelArrayFromSampleMap[d.rMap]; d.paG ¬ CtBasic.PixelArrayFromSampleMap[d.gMap]; d.paB ¬ CtBasic.PixelArrayFromSampleMap[d.maps[1].map]; d.opaR ¬ CtBasic.PixelArrayFromSampleMap[d.rMap]; d.opaG ¬ CtBasic.PixelArrayFromSampleMap[d.gMap]; d.opaB ¬ CtBasic.PixelArrayFromSampleMap[d.maps[1].map]; }; ENDCASE; d.colorMap ¬ CtMap.Read[]; IO.PutRope[cmd.out, "Ready!\n"]; }; d: Tool ¬ NEW[ToolRep]; grayButtons: ButtonList ¬ LIST[ Controls.TextButton[name: rawBName, text: "0 ", clientData: d, row: 2, proc: TBProc] ]; rgbButtons: ButtonList ¬ LIST[ Controls.TextButton[name: redBName, text: "0 ", clientData: d, row: 2, proc: TBProc], Controls.TextButton[name: grnBName, text: "0 ", clientData: d, row: 2, proc: TBProc], Controls.TextButton[name: bluBName, text: "0 ", clientData: d, row: 2, proc: TBProc] ]; buttons: ButtonList ¬ LIST[ Controls.ClickButton[name: " ", row: 3, clientData: d, font: boldFixed], Controls.ClickButton[name: " L ", row: 3, clientData: d, font: boldFixed], Controls.ClickButton[name: " M ", row: 3, clientData: d, font: boldFixed], Controls.ClickButton[name: " R ", row: 3, clientData: d, font: boldFixed], Controls.ClickButton[name: "P", row: 2, clientData: d, font: boldFixed], Controls.ClickButton[name: "z*2", proc: ZoomTimes2, row: 2, clientData: d, font: fixed], Controls.ClickButton[name: " ? ", proc: Show, row: 2, clientData: d, font: fixed], Controls.ClickButton[name: "z/2", proc: ZoomOver2, row: 2, clientData: d, font: fixed], Controls.ClickButton[name: "S", row: 1, clientData: d, font: boldFixed], Controls.ClickButton[name: "z+1", proc: ZoomPlus1, row: 1, clientData: d, font: fixed], Controls.ClickButton[name: "?+c", proc: ShowCenter, row: 1, clientData: d, font: fixed], Controls.ClickButton[name: "z-1", proc: ZoomMinus1, row: 1, clientData: d, font: fixed], Controls.ClickButton[name: "C", clientData: d, font: boldFixed], Controls.ClickButton[name: "z*8", proc: ZoomTimes8, clientData: d, font: fixed], Controls.ClickButton[name: " ", clientData: d, font: fixed], Controls.ClickButton[name: "z/8", proc: ZoomOver8, clientData: d, font: fixed], Controls.ClickButton[name: " ", row: 3, clientData: d, font: fixed], Controls.ClickButton[name: " ", row: 2, clientData: d, font: fixed], Controls.ClickButton[name: " ", row: 1, clientData: d, font: fixed], Controls.ClickButton[name: " ", row: 0, clientData: d, font: fixed], Controls.ClickButton[name: "x", proc: Left, row: 3, clientData: d, font: arrow, h: 15], Controls.ClickButton[name: "n", proc: Right, row: 2, clientData: d, font: arrow, h: 15], Controls.ClickButton[name: ",", proc: Up, row: 1, clientData: d, font: arrow, h: 15], Controls.ClickButton[name: "v", proc: Down, row: 0, clientData: d, font: arrow, h: 15], Controls.TextButton[name: pixelBName, text: "0 0 ", proc: TBProc, clientData: d, row: 3], Controls.TextButton[name: zoomBName, text: "1 ", proc: TBProc, clientData: d, row: 3], Controls.ClickButton[name: "buf:", row: 2, clientData: d, font: fixed], Controls.ClickButton[name: "map:", row: 1, clientData: d, font: fixed], Controls.TextButton[name: mapredBName, text: "0 ", clientData: d, row: 1, proc: TBProc], Controls.TextButton[name: mapgrnBName, text: "0 ", clientData: d, row: 1, proc: TBProc], Controls.TextButton[name: mapbluBName, text: "0 ", clientData: d, row: 1, proc: TBProc], Controls.ClickButton[name: awakeWord, proc: Awake, clientData: d, row: 0], Controls.ClickButton[name: "InvertCursor", proc: InvertCursor, clientData: d, row: 0], Controls.ClickButton[name: "Redraw", proc: Redraw, clientData: d, guarded: TRUE, row: 0], Controls.ClickButton[name: "Reset", proc: Reset, clientData: d, guarded: TRUE, row: 0], Controls.ClickButton[name: " ", row: 3, clientData: d], Controls.ClickButton[name: "Help", row: 3, clientData: d, proc: HelpProc] ]; <<[] _ Terminal.ModifyColorFrame[Terminal.Current[], GetFBContents];>> d.center ¬ [(d.paR.x+d.paR.w/2)-1, (d.paR.y+d.paR.h/2)-1]; d.poi ¬ AddIntegerPairs[d.center, [1, 0]]; <> FOR l: ButtonList ¬ buttons, l.rest DO -- presumes buttons # NIL IF l.rest # NIL THEN LOOP; l.rest ¬ IF d.maps.bpp = 8 THEN grayButtons ELSE rgbButtons; EXIT; ENDLOOP; d.outerData ¬ Controls.OuterViewer[ name: "CtTool", column: right, buttons: buttons, typescriptHeight: --one line = 18-- 108, destroyProc: Destroy, clientData: d, noOpen: TRUE]; d.outer ¬ d.outerData.parent; d.outer.icon ¬ IF d.maps.bpp = 8 THEN icon8bits ELSE icon24bits; UpdateButtons[d]; ViewerOps.OpenIcon[d.outer]; CtMisc.RegisterWatch[[d, ToolMouse, ToolChange]]; }; <> <> TBProc: Controls.ClickProc ~ { -- called if user types any text box and CR d: Tool ¬ NARROW[clientData]; ReadButtonsAndRespond[d]; }; <> DoMove: PROC [clientData: REF, move: IntegerPair] ~ { d: Tool ¬ NARROW[clientData]; d.poi ¬ AddIntegerPairs[d.poi, move]; SetTextIntegerPair[d, pixelBName, d.poi]; ReadButtonsAndRespond[d]; PrintPixel[d]; }; DoZoom: PROC [d: Tool, scale, offset: REAL] ~ { factor: INTEGER ¬ Real.InlineRoundI[d.zoomFactor*scale+offset]; SetTextInt[d, zoomBName, MAX[1, factor]]; ReadButtonsAndRespond[d]; }; Left: Controls.ClickProc ~ {DoMove[clientData, [-1, 0]]}; Right: Controls.ClickProc ~ {DoMove[clientData, [ 1, 0]]}; Up: Controls.ClickProc ~ {DoMove[clientData, [ 0, -1]]}; Down: Controls.ClickProc ~ {DoMove[clientData, [ 0, 1]]}; ZoomPlus1: Controls.ClickProc ~ {DoZoom[NARROW[clientData], 1.0, 1.0]}; ZoomMinus1: Controls.ClickProc ~ {DoZoom[NARROW[clientData], 1.0, -1.0]}; ZoomTimes2: Controls.ClickProc ~ {DoZoom[NARROW[clientData], 2.0, 0.0]}; ZoomOver2: Controls.ClickProc ~ {DoZoom[NARROW[clientData], 1.0/2.0, 0.0]}; ZoomTimes8: Controls.ClickProc ~ {DoZoom[NARROW[clientData], 8.0, 0.0]}; ZoomOver8: Controls.ClickProc ~ {DoZoom[NARROW[clientData], 1.0/8.0, 0.0]}; <> Awake: Buttons.ButtonProc ~ { d: Tool ¬ NARROW[clientData]; Buttons.ReLabel[parent, IF d.awake ¬ NOT d.awake THEN awakeWord ELSE asleepWord]; Buttons.SetDisplayStyle[parent, IF d.awake THEN $BlackOnWhite ELSE $WhiteOnBlack]; IF d.awake THEN CtMisc.RegisterWatch[[d, ToolMouse, ToolChange]] ELSE CtMisc.UnRegisterWatch[[d, ToolMouse, ToolChange]]; }; InvertCursor: Buttons.ButtonProc ~ { d: Tool ¬ NARROW[clientData]; d.cursorLooks ¬ IF d.cursorLooks = onesAreWhite THEN onesAreBlack ELSE onesAreWhite; Buttons.SetDisplayStyle[parent, IF d.cursorLooks = onesAreWhite THEN $WhiteOnBlack ELSE $BlackOnWhite]; <<[] _ Terminal.SetColorCursorPresentation[Terminal.Current[], d.cursorLooks]>> }; <> Reset: Buttons.ButtonProc ~ { d: Tool ¬ NARROW[clientData]; d.poi ¬ AddIntegerPairs[d.center, [1, 0]]; d.sUL ¬ d.pUL ¬ [0, 0]; d.zoomFactor ¬ 1; d.paR ¬ d.opaR; IF d.maps.bpp = 24 THEN { d.paG ¬ d.opaG; d.paB ¬ d.opaB; }; CtMap.Write[d.colorMap]; UpdateButtons[d]; DoRedraw[d]; }; Redraw: Buttons.ButtonProc ~ { d: Tool ¬ NARROW[clientData]; DoRedraw[d]; }; <> Show: Controls.ClickProc ~ { d: Tool ¬ NARROW[clientData]; ReadButtonsAndRespond[d]; PrintPixel[d]; }; ShowCenter: Controls.ClickProc ~ { d: Tool ¬ NARROW[clientData]; SetTextIntegerPair[d, pixelBName, d.poi]; PrintPixel[d]; DoRedraw[d]; -- don't check poi against pixel, because we just made them the same! }; <> GetTextInt: PROC [d: Tool, buttonName: ROPE] RETURNS [value: INTEGER ¬ 0] ~ { textV: Viewer ¬ Controls.ButtonFind[d.outerData, buttonName].textViewer; contents: ROPE ¬ ViewerTools.GetContents[textV]; IF Rope.IsEmpty[contents] THEN value ¬ 0 ELSE value ¬ Convert.IntFromRope[contents ! Convert.Error => {value ¬ -1; CONTINUE;};]; }; SetTextRope: PROC [d: Tool, buttonName, text: ROPE] ~ { textV: Viewer ¬ Controls.ButtonFind[d.outerData, buttonName].textViewer; ViewerTools.SetContents[textV, text]; }; SetTextInt: PROC [d: Tool, buttonName: ROPE, value: INTEGER] ~ { textV: Viewer ¬ Controls.ButtonFind[d.outerData, buttonName].textViewer; ViewerTools.SetContents[textV, IO.PutFR["%3g", IO.int[value]]]; }; SetTextIntegerPair: PROC [d: Tool, buttonName: ROPE, p: IntegerPair] ~ { textV: Viewer ¬ Controls.ButtonFind[d.outerData, buttonName].textViewer; ViewerTools.SetContents[textV, IO.PutFR["%3g %3g", IO.int[p.x], IO.int[p.y]]]; }; UpdateButtons: PROC [d: Tool] ~ { IF PoiInImage[d] THEN { IF d.maps.bpp = 8 THEN { d.maprgb ¬ CtMap.ReadEntry[d.paR[d.poi.y][d.poi.x]]; SetTextInt[d, rawBName, d.paR[d.poi.y][d.poi.x]]; } ELSE { d.maprgb ¬ CtMap.ReadEntry24[ d.paR[d.poi.y][d.poi.x], d.paG[d.poi.y][d.poi.x], d.paB[d.poi.y][d.poi.x]]; SetTextInt[d, redBName, d.paR[d.poi.y][d.poi.x]]; SetTextInt[d, grnBName, d.paG[d.poi.y][d.poi.x]]; SetTextInt[d, bluBName, d.paB[d.poi.y][d.poi.x]]; }; SetTextInt[d, mapredBName, d.maprgb.r]; SetTextInt[d, mapgrnBName, d.maprgb.g]; SetTextInt[d, mapbluBName, d.maprgb.b]; } ELSE { IF d.maps.bpp = 8 THEN { SetTextRope[d, rawBName, "---"]; } ELSE { SetTextRope[d, redBName, "---"]; SetTextRope[d, grnBName, "---"]; SetTextRope[d, bluBName, "---"]; }; SetTextRope[d, mapredBName, "---"]; SetTextRope[d, mapgrnBName, "---"]; SetTextRope[d, mapbluBName, "---"]; }; SetTextInt[d, zoomBName, d.zoomFactor]; SetTextIntegerPair[d, pixelBName, d.poi]; }; ReadButtonsAndRespond: PROC [d: Tool] ~ { changeZoom: BOOLEAN ¬ FALSE; -- redraw the color display? changeCmap: BOOLEAN ¬ FALSE; -- change the color map? changeFb: BOOLEAN ¬ FALSE; -- change the pixel value? changePoi: BOOLEAN ¬ FALSE; -- change the poi? newP, newZ: INT; newmap, newclr: RGB; <> a1, a2: Args.Arg; [a1, a2] ¬ Args.ArgsGetFromRope[ViewerTools.GetContents[ Controls.ButtonFind[d.outerData, pixelBName].textViewer], "%ii"]; IF d.poi.x # a1.int OR d.poi.y # a2.int THEN { changePoi ¬ TRUE; d.poi ¬ [a1.int, a2.int]; }; <> newZ ¬ ClipInt[GetTextInt[d, zoomBName], 0, 2048]; IF d.zoomFactor # newZ THEN { changeZoom ¬ TRUE; newZ ¬ ClipInt[GetTextInt[d, zoomBName], 0, 2048]; }; <> newmap.r ¬ ClipInt[GetTextInt[d, mapredBName], 0, 255]; newmap.g ¬ ClipInt[GetTextInt[d, mapgrnBName], 0, 255]; newmap.b ¬ ClipInt[GetTextInt[d, mapbluBName], 0, 255]; IF newmap # d.maprgb THEN changeCmap ¬ TRUE; <> IF d.maps.bpp = 8 THEN { newP ¬ ClipInt[GetTextInt[d, rawBName], 0, 255]; IF newP # d.raw THEN { changeFb ¬ TRUE; }; } ELSE { newclr.r ¬ ClipInt[GetTextInt[d, redBName], 0, 255]; newclr.g ¬ ClipInt[GetTextInt[d, grnBName], 0, 255]; newclr.b ¬ ClipInt[GetTextInt[d, bluBName], 0, 255]; IF newclr # d.rawrgb THEN changeFb ¬ TRUE; }; IF NOT PoiInImage[d] THEN changeFb ¬ changeCmap ¬ FALSE; <> <> <> <> <> IF changePoi THEN { DoRedraw[d]; UpdateButtons[d]; RETURN; }; IF changeFb THEN { IF d.maps.bpp = 8 THEN d.raw ¬ newP ELSE d.rawrgb ¬ newclr; ChangeFb[d]; IF NOT changeZoom THEN RedrawPoi[d]; }; IF changeCmap THEN { d.maprgb ¬ newmap; ChangeCmap[d]; }; IF changeZoom THEN { d.zoomFactor ¬ newZ; DoRedraw[d]; }; UpdateButtons[d]; }; <> ToolMouse: CtMisc.MouseProc ~ { d: Tool ¬ NARROW[clientData]; SELECT mouse.state FROM down => { }; held => { }; up => { AdjustMouse[d, mouse.pos]; SELECT mouse.button FROM left => IF mouse.shiftKey THEN DoMouseZoom[d, 1.0, 1.0] ELSE IF mouse.controlKey THEN DoMouseZoom[d, 8.0, 0.0] ELSE DoMouseZoom[d, 2.0, 0.0]; middle => IF mouse.shiftKey AND mouse.controlKey THEN Debug[d] ELSE { PrintPixel[d]; IF mouse.shiftKey THEN DoRedraw[d]; }; right => IF mouse.shiftKey THEN DoMouseZoom[d, 1.0, -1.0] ELSE IF mouse.controlKey THEN DoMouseZoom[d, 1.0/8.0, 0.0] ELSE DoMouseZoom[d, 1.0/2.0, 0.0]; ENDCASE; }; ENDCASE; }; AdjustMouse: PROC [d: Tool, poi: IntegerPair] ~ { <> d.poi.x ¬ d.pUL.x+Real.Floor[(poi.x - d.sUL.x)/Real.Float[d.zoomFactor]]; d.poi.y ¬ d.pUL.y+Real.Floor[(poi.y - d.sUL.y)/Real.Float[d.zoomFactor]]; }; DoMouseZoom: PROC [d: Tool, scale, offset: REAL] ~ { factor: INTEGER ¬ Real.InlineRoundI[d.zoomFactor*scale+offset]; factor ¬ MAX[1, factor]; SetTextInt[d, zoomBName, factor]; SetTextIntegerPair[d, pixelBName, d.poi]; ReadButtonsAndRespond[d]; }; <> PrintPixel: PROC [d: Tool] ~ { poi: IntegerPair ¬ d.poi; rope: ROPE; IF PoiInImage[d] THEN { rgb: RGB; IF d.maps.bpp = 8 THEN { d.raw ¬ d.paR[d.poi.y][d.poi.x]; rgb ¬ CtMap.ReadEntry[d.raw]; rope ¬ IO.PutFR["pixel [%4g %4g] = %3g", IO.int[poi.x], IO.int[poi.y], IO.int[d.raw]]; } ELSE { rgb ¬ CtMap.ReadEntry24[d.paR[poi.y][poi.x], d.paG[poi.y][poi.x], d.paB[poi.y][poi.x]]; rope ¬ IO.PutFR["pixel [%4g %4g] = (%3g %3g %3g)", IO.int[poi.x], IO.int[poi.y], IO.int[d.paR[poi.y][poi.x]], IO.int[d.paG[poi.y][poi.x]], IO.int[d.paB[poi.y][poi.x]]]; }; Controls.TypescriptWrite[d.outerData.typescript, rope]; rope ¬ IO.PutFR[" --- map = { %3g %3g %3g }\n", IO.int[rgb.r], IO.int[rgb.g], IO.int[rgb.b]]; Controls.TypescriptWrite[d.outerData.typescript, rope]; } ELSE { Controls.TypescriptWrite[d.outerData.typescript, IO.PutFR["no image at pixel [%4g %4g]\n", IO.int[poi.x], IO.int[poi.y]]]; }; UpdateButtons[d]; }; ReportMessage: PROC [d: Tool, msg: ROPE] ~ { Controls.TypescriptWrite[d.outerData.typescript, msg]; }; <> ToolChange: CtMisc.ChangeProc ~ { d: Tool ¬ NARROW[clientData]; awakeb: Viewer ¬ Controls.ButtonFind[d.outerData, awakeWord].textViewer; IF awakeb = NIL THEN awakeb ¬ Controls.ButtonFind[d.outerData, asleepWord].textViewer; Buttons.SetDisplayStyle[awakeb, $WhiteOnBlack]; CtMisc.UnRegisterWatch[[d, ToolMouse, ToolChange]]; ViewerOps.CloseViewer[d.outer]; MessageWindow.Append[" CtTool: color display changed; restart me!"]; MessageWindow.Blink[]; }; RedrawPoi: PROC [d: Tool] ~ { <> DoRedraw[d]; }; ChangeFb: PROC [d: Tool] ~ { IF NOT PoiInImage[d] THEN RETURN; IF d.maps.bpp = 8 THEN { d.paR[d.poi.y][d.poi.x] ¬ d.raw; } ELSE { d.paR[d.poi.y][d.poi.x] ¬ d.rawrgb.r; d.paG[d.poi.y][d.poi.x] ¬ d.rawrgb.g; d.paB[d.poi.y][d.poi.x] ¬ d.rawrgb.b; }; }; ChangeCmap: PROC [d: Tool] ~ { IF d.maps.bpp = 8 THEN CtMap.WriteEntry[d.raw, d.maprgb] ELSE CtMap.WriteEntry24[d.rawrgb.r, d.rawrgb.g, d.rawrgb.b, d.maprgb]; }; DoRedraw: PROC [d: Tool] ~ { Action: PROC ~ { InnerOneMap: PROC[map: SampleMap, pa: PixelArray] ~ { xReps, yReps: NAT; leftPixel, thisPixel: IntegerPair ¬ d.pUL; paY: SampleBuffer; scanLine: ImagerSample.SampleBuffer ¬ ImagerSample.ObtainScratchSamples[d.paR.x+d.paR.w]; <> IF thisPixel.y >= 0 AND thisPixel.y < pa.h THEN { paY ¬ pa[thisPixel.y]; xReps ¬ rUL.x; FOR x: NAT IN [pa.x..pa.x+pa.w) DO IF thisPixel.x >= 0 AND thisPixel.x < pa.w THEN scanLine[x] ¬ paY[thisPixel.x] ELSE scanLine[x] ¬ 0; xReps ¬ xReps - 1; IF xReps = 0 THEN { thisPixel.x ¬ thisPixel.x+1; xReps ¬ zoom; }; ENDLOOP; } ELSE FOR x: NAT IN [pa.x..pa.x+pa.w) DO scanLine[x] ¬ 0; ENDLOOP; yReps ¬ 1+rUL.y; FOR y: NAT IN [pa.y..pa.y+pa.h) DO yReps ¬ yReps - 1; IF yReps = 0 THEN { leftPixel.y ¬ leftPixel.y+1; yReps ¬ zoom; IF leftPixel.y >= 0 AND leftPixel.y < pa.h THEN { paY ¬ pa[leftPixel.y]; thisPixel ¬ leftPixel; xReps ¬ 1+rUL.x; FOR x: NAT IN [pa.x..pa.x+pa.w) DO IF thisPixel.x >= 0 AND thisPixel.x < pa.w THEN scanLine[x] ¬ paY[thisPixel.x] ELSE scanLine[x] ¬ 0; xReps ¬ xReps-1; IF xReps = 0 THEN { xReps ¬ zoom; thisPixel.x ¬ thisPixel.x+1; }; ENDLOOP; } ELSE FOR x: NAT IN [pa.x..pa.x+pa.w) DO scanLine[x] ¬ 0; ENDLOOP; }; ImagerSample.PutSamples[map, [y, 0],, scanLine, 0, pa.w]; ENDLOOP; ImagerSample.ReleaseScratchSamples[scanLine]; }; InnerThreeMaps: PROC [rgdstmap, bdstmap: SampleMap, redpa, grnpa, blupa: PixelArray] ~ { xReps, yReps: NAT; leftPixel, thisPixel: IntegerPair ¬ d.pUL; redpaY, grnpaY, blupaY: SampleBuffer; rgdstmap2: SampleMap ¬ CtBasic.GetRedGrn[rgdstmap]; -- 2*dstmap.width in 8bpp. width: NAT ¬ ImagerSample.GetSize[rgdstmap].f; xMin2: NAT ¬ 2*ImagerSample.GetBox[rgdstmap].min.f; redscanLine: ImagerSample.SampleBuffer ¬ ImagerSample.ObtainScratchSamples[d.paR.x+d.paR.w]; grnscanLine: ImagerSample.SampleBuffer ¬ ImagerSample.ObtainScratchSamples[d.paR.x+d.paR.w]; bluscanLine: ImagerSample.SampleBuffer ¬ ImagerSample.ObtainScratchSamples[d.paR.x+d.paR.w]; <> IF thisPixel.y >= 0 AND thisPixel.y < redpa.h THEN { redpaY ¬ redpa[thisPixel.y]; grnpaY ¬ grnpa[thisPixel.y]; blupaY ¬ blupa[thisPixel.y]; xReps ¬ rUL.x; FOR x: NAT IN [redpa.x..redpa.x+redpa.w) DO IF thisPixel.x >= 0 AND thisPixel.x < redpa.w -- check? THEN { redscanLine[x]¬ redpaY[thisPixel.x]; grnscanLine[x]¬ grnpaY[thisPixel.x]; bluscanLine[x]¬ blupaY[thisPixel.x]; } ELSE { redscanLine[x] ¬ 0; grnscanLine[x] ¬ 0; }; xReps ¬ xReps - 1; IF xReps = 0 THEN { thisPixel.x ¬ thisPixel.x+1; xReps ¬ zoom; }; ENDLOOP; } ELSE FOR x: NAT IN [redpa.x..redpa.x+redpa.w) DO redscanLine[x] ¬ 0; grnscanLine[x] ¬ 0; bluscanLine[x] ¬ 0; ENDLOOP; yReps ¬ 1+rUL.y; FOR y: NAT IN [redpa.y..redpa.y+redpa.h) DO yReps ¬ yReps - 1; IF yReps = 0 THEN { leftPixel.y ¬ leftPixel.y+1; yReps ¬ zoom; IF leftPixel.y >= 0 AND leftPixel.y < redpa.h THEN { redpaY ¬ redpa[leftPixel.y]; grnpaY ¬ grnpa[leftPixel.y]; blupaY ¬ blupa[leftPixel.y]; thisPixel ¬ leftPixel; xReps ¬ 1+rUL.x; FOR x: NAT IN [redpa.x..redpa.x+redpa.w) DO IF thisPixel.x >= 0 AND thisPixel.x < redpa.w THEN { redscanLine[x] ¬ redpaY[thisPixel.x]; grnscanLine[x] ¬ grnpaY[thisPixel.x]; bluscanLine[x] ¬ blupaY[thisPixel.x]; } ELSE { redscanLine[x] ¬ 0; grnscanLine[x] ¬ 0; bluscanLine[x] ¬ 0; }; xReps ¬ xReps-1; IF xReps = 0 THEN { xReps ¬ zoom; thisPixel.x ¬ thisPixel.x+1; }; ENDLOOP; } ELSE FOR x: NAT IN [redpa.x..redpa.x+redpa.w) DO redscanLine[x] ¬ 0; grnscanLine[x] ¬ 0; bluscanLine[x] ¬ 0; ENDLOOP; }; <> ImagerSample.PutSamples[rgdstmap2, [y, xMin2], [0, 2], redscanLine, 0, width]; <> ImagerSample.PutSamples[rgdstmap2, [y, 1+xMin2], [0, 2], grnscanLine, 0, width]; <> ImagerSample.PutSamples[bdstmap, [y, 0],, bluscanLine, 0, width]; ENDLOOP; ImagerSample.ReleaseScratchSamples[redscanLine]; ImagerSample.ReleaseScratchSamples[grnscanLine]; ImagerSample.ReleaseScratchSamples[bluscanLine]; }; IF d.maps # NIL THEN SELECT d.maps.bpp FROM 8 => InnerOneMap[d.maps[0].map, d.paR]; 24 => { InnerThreeMaps[d.maps[0].map, d.maps[1].map, d.paR, d.paG, d.paB]; }; ENDCASE; }; <> zoom: INT ¬ d.zoomFactor; center: IntegerPair ¬ d.center; alpha: INTEGER ¬ (d.zoomFactor-1)/2; pc: IntegerPair ¬ AddIntegerPairs[center, [-alpha, -alpha]]; beta: IntegerPair¬[Real.Ceiling[pc.x/REAL[zoom]],Real.Ceiling[pc.y/REAL[zoom]]]; rUL: IntegerPair; d.pUL ¬ AddIntegerPairs[d.poi, [-beta.x, -beta.y]]; d.sUL ¬ AddIntegerPairs[pc, [-beta.x*zoom, -beta.y*zoom]]; rUL ¬ AddIntegerPairs[d.sUL, [zoom, zoom]]; UpdateButtons[d]; <<[] _ Terminal.ModifyColorFrame[Terminal.Current[], Action];>> }; <> <> PoiInImage: PROC [d: Tool] RETURNS [BOOLEAN] ~ { RETURN[d.poi.x>=0 AND d.poi.x=0 AND d.poi.yhi THEN hi ELSE v]; }; AddIntegerPairs: PROC [pair1, pair2: IntegerPair] RETURNS [sum: IntegerPair] ~ { sum ¬ [pair1.x+pair2.x, pair1.y+pair2.y]; }; PowerOfTwoRatchet: PROC [val: REAL] RETURNS [new: INT] ~ { <> exp: INT ¬ Real.Round[RealFns.Ln[val]/RealFns.Ln[2.0]]; -- exp ¬ log2 val RETURN[new ¬ Real.Round[RealFns.Power[2.0, Real.Float[exp]]]]; }; doc: ROPE ¬ FileNames.StripVersionNumber[FS.FileInfo["ColorTrixDoc.tioga"].fullFName]; HelpProc: Buttons.ButtonProc ~ { v: Viewer ¬ TiogaMenuOps.Open[doc,, left]; TEditSelection.FindRope[v, "Ct Tool"]; }; <> Debug: PROC [d: Tool] ~ { rope: ROPE; rope ¬ IO.PutFR["zoomFactor: %g poi: (%g %g)\n", IO.int[d.zoomFactor], IO.int[d.poi.x], IO.int[d.poi.y]]; Controls.TypescriptWrite[d.outerData.typescript, rope]; rope ¬ IO.PutFR["sUL: (%g %g) pUL(%g %g)\n", IO.int[d.sUL.x], IO.int[d.sUL.y], IO.int[d.pUL.y], IO.int[d.pUL.y]]; Controls.TypescriptWrite[d.outerData.typescript, rope]; rope ¬ IO.PutFR["center: (%g %g)\n", IO.int[d.center.x], IO.int[d.center.y]]; Controls.TypescriptWrite[d.outerData.typescript, rope]; }; <> Destroy: Controls.DestroyProc ~ { d: Tool ¬ NARROW[clientData]; <<[] _ Terminal.SetColorCursorPresentation[Terminal.Current[], onesAreBlack];>> CtMisc.UnRegisterWatch[[d, ToolMouse, ToolChange]]; }; <> toolUsage: ROPE ~ "Ct Tool examine image on the monitor"; icon8bits: Icons.IconFlavor ¬ Icons.NewIconFromFile["ColorTrix.icons", 7]; icon24bits: Icons.IconFlavor ¬ Icons.NewIconFromFile["ColorTrix.icons", 6]; CtDispatch.RegisterCtOp["Image Tools:", NIL, NIL]; CtDispatch.RegisterCtOp["Tool", ToolCmd, toolUsage]; END.