<> <> <> DIRECTORY Args, ColorTrixBasics, ColorTrixDispatch, ColorTrixMap, ColorTrixMisc, Commander, ImagerPixelMap, IO, Process, Rope, Terminal, TiogaExtraOps, TiogaOps, TypeScript, ViewerClasses, ViewerIO, ViewerOps; ColorTrixInfoCommandImpl: CEDAR PROGRAM IMPORTS Args, ColorTrixBasics, ColorTrixDispatch, ColorTrixMap, ColorTrixMisc, ImagerPixelMap, IO, Process, Rope, Terminal, TiogaExtraOps, TiogaOps, TypeScript, ViewerIO, ViewerOps ~ BEGIN Viewer: TYPE ~ ViewerClasses.Viewer; PixelMapMisc: TYPE ~ ColorTrixBasics.PixelMapMisc; Cmap: TYPE ~ ColorTrixMap.Cmap; Info: TYPE ~ REF InfoRec; InfoRec: TYPE ~ RECORD [ts: Viewer, out: IO.STREAM]; PixelInfo: TYPE ~ RECORD [pval, red, grn, blu: CARDINAL]; Mouse: ColorTrixMisc.MouseProc ~ { info: Info ~ NARROW[data]; SELECT mouse.button FROM left => APixel[info.out, mouse.pm, mouse.cmap, mouse.x, mouse.y]; middle => ManyPixels[info.out, mouse.pm, mouse.cmap, mouse.x, mouse.y, info.ts]; ENDCASE; }; Destroy: ViewerClasses.DestroyProc ~ { ColorTrixMisc.UnRegisterClient[[Mouse, NIL, self.data]]; }; CtInfo: PUBLIC Commander.CommandProc ~ { nArgs: INTEGER _ Args.NArgs[cmd]; IF nArgs # 0 AND nArgs # 2 THEN RETURN[$Failure, Rope.Concat["Bad argument(s); usage: ", NIL]] ELSE SELECT nArgs FROM 0 => { r: Rope.ROPE ~ "0 pt restIndent"; info: Info _ NEW[InfoRec]; v: Viewer _ ViewerOps.CreateViewer[ flavor: $CtInfo, info: [openHeight: 400, name: "Ct Info", data: info, scrollable: TRUE, column: right, iconic: TRUE]]; ViewerOps.OpenIcon[v]; info.ts _ TypeScript.Create[[parent: v, ww: v.cw, wh: v.ch, border: FALSE]]; TiogaExtraOps.PutProp[TiogaOps.LastWithin[TiogaOps.ViewerDoc[info.ts]], $Postfix, r]; info.out _ ViewerIO.CreateViewerStreams[NIL, info.ts].out; ColorTrixMisc.RegisterClient[[Mouse, NIL, info]]; }; 2 => { x: Args.Arg _ Args.ArgInt[cmd, 0]; y: Args.Arg _ Args.ArgInt[cmd, 1]; pm: PixelMapMisc _ ColorTrixBasics.GetColorDisplayPmMisc[]; cmap: Cmap _ IF pm.bpp = 8 THEN ColorTrixMap.Read[] ELSE NIL; IF NOT x.ok OR NOT y.ok THEN RETURN[$Failure, "Bad argument(s)."]; IF NOT CoordinatesOK[pm, x.int, y.int] THEN RETURN[ $Failure, IO.PutFR["(x, y) must be ([0..%g), [0..%g))", IO.int[pm.w], IO.int[pm.h]]]; APixel[cmd.out, pm, cmap, x.int, y.int]; }; ENDCASE; }; APixel: PROC [out: IO.STREAM, pm: PixelMapMisc, cmap: Cmap, x, y: NAT] ~ { pix: PixelInfo _ GetPixelInfo[pm, cmap, x, y]; SELECT pm.bpp FROM 8 => IO.PutRope[out, Rope.Concat[ IO.PutFR["8 bit pixel at (%g, %g): %g ", IO.int[x], IO.int[y], IO.card[pix.pval]], IO.PutFR["(r: %g, g: %g, b: %g)\n", IO.int[cmap[0][pix.pval]], IO.int[cmap[1][pix.pval]], IO.int[cmap[2][pix.pval]]]]]; 24 => IO.PutRope[out, IO.PutFR["24 bit pixel at (%g, %g), r: %g, g: %g, b: %g\n", IO.int[x], IO.int[y], IO.card[pix.red], IO.card[pix.grn], IO.card[pix.blu]]]; ENDCASE; }; ManyPixels: PROC [out: IO.STREAM, pm: PixelMapMisc, cmap: Cmap, x, y: NAT, v: Viewer] ~ { pixs: ARRAY [0..5) OF ARRAY [0..5) OF PixelInfo; Bar: PROC ~ { IF pm.bpp = 8 THEN IO.PutF[out, "\n"] ELSE IO.PutF[out, "\n"] }; PrintLine: PROC [j: INTEGER, proc: PROC [i, j: INTEGER], report: BOOL _ FALSE] ~ { IF proc # PrintX THEN IO.PutRope[out, "| "]; FOR i: NAT IN [0..5) DO proc[i, j]; ENDLOOP; IF report THEN IO.PutF[out, " %g", IO.int[y-2+j]]; IO.PutRope[out, "\n"]; }; PrintX: PROC [i, j: INTEGER] ~ { IF pm.bpp = 8 THEN IO.PutF[out, " %3g\t", IO.int[x-2+i]] ELSE IO.PutF[out, " %3g\t", IO.int[x-2+i]]; }; PrintPval: PROC [i, j: INTEGER] ~ { IO.PutF[out, " %-3g\t\t|", IO.card[pixs[i][j].pval]]; }; PrintRed: PROC [i, j: INTEGER] ~ {PrintCard["r", pixs[i][j].red]}; PrintGrn: PROC [i, j: INTEGER] ~ {PrintCard["g", pixs[i][j].grn]}; PrintBlu: PROC [i, j: INTEGER] ~ {PrintCard["b", pixs[i][j].blu]}; PrintCard: PROC [rope: Rope.ROPE, card: CARDINAL] ~ { IF pm.bpp = 8 THEN IO.PutF[out, " %g: %3g\t|", IO.rope[rope], IO.card[card]] ELSE IO.PutF[out, " %3g\t|", IO.card[card]]; }; FOR j: NAT IN [0..5) DO yy: INTEGER _ y-2+j; FOR i: NAT IN [0..5) DO pixs[i][j] _ GetPixelInfo[pm, cmap, x-2+i, yy]; ENDLOOP; ENDLOOP; IO.PutF[out, "\n%g bit pixels centered at (%g, %g):\n", IO.int[pm.bpp], IO.int[x], IO.int[y]]; Process.Pause[Process.MsecToTicks[100]]; [] _ v.class.scroll[v, thumb, 100]; PrintLine[0, PrintX]; Bar[]; FOR line: NAT IN [0..5) DO IF pm.bpp = 8 THEN PrintLine[line, PrintPval]; PrintLine[line, PrintRed]; PrintLine[line, PrintGrn, TRUE]; PrintLine[line, PrintBlu]; Bar[]; ENDLOOP }; CoordinatesOK: PROC [pm: PixelMapMisc, x, y: INTEGER] RETURNS [BOOL] ~ { RETURN[x IN [0..pm.w) AND y IN [0..pm.h)]; }; GetPixelInfo: PROC [pm: PixelMapMisc, cmap: Cmap, x, y: INTEGER] RETURNS [PixelInfo] ~ { pix: PixelInfo; GetInner: PROC ~ { SELECT pm.bpp FROM 8 => { pix.pval _ ImagerPixelMap.GetPixel[pm.bw, y, x]; pix.red _ cmap[0][pix.pval]; pix.grn _ cmap[1][pix.pval]; pix.blu _ cmap[2][pix.pval]; }; 24 => [pix.red, pix.grn, pix.blu] _ ColorTrixBasics.GetRGBPixel[pm, x, y]; ENDCASE => NULL; }; IF CoordinatesOK[pm, x, y] THEN Terminal.ModifyColorFrame[Terminal.Current[], GetInner, x, y, x+1, y+1]; RETURN[pix]; }; <> ViewerOps.RegisterViewerClass[ $CtInfo, NEW[ViewerClasses.ViewerClassRec _ [destroy: Destroy]]]; ColorTrixDispatch.RegisterCtOp[ "Info", CtInfo, "Ct Info [x, y: INT]: Print the pixel value at (x, y)."]; END.