ColorTrixInfoImpl:
CEDAR
PROGRAM
IMPORTS Args, CedarProcess, ClassIncreek, ColorDisplay, ColorTrixBasics, ColorTrixMap, Commander, ImagerPixelMap, IO, Process, Rope, Terminal, TypeScript, ViewerIO, ViewerOps
~
BEGIN
ROPE: TYPE ~ Rope.ROPE;
STREAM: TYPE ~ IO.STREAM;
Viewer: TYPE ~ ViewerClasses.Viewer;
PixelMap: TYPE ~ ColorTrixBasics.PixelMap;
PixelMapMisc: TYPE ~ ColorTrixBasics.PixelMapMisc;
Cmap: TYPE ~ ColorTrixMap.Cmap;
CtInfoData: TYPE ~ REF CtInfoDataRec;
CtInfoDataRec:
TYPE ~
RECORD [
viewer: Viewer ← NIL,
colorDisplayChanged: BOOL ← FALSE,
out: STREAM ← NIL,
pm: PixelMapMisc,
cmap: Cmap ← NIL,
x, y: INTEGER ← 0
];
PixelInfo:
TYPE ~
RECORD [
pval: CARDINAL,
red: CARDINAL,
grn: CARDINAL,
blu: CARDINAL
];
SeColorDisplayInfo:
PROC [info: CtInfoData] ~ {
info.pm ← ColorTrixBasics.GetColorDisplayPmMisc[];
info.cmap ← IF info.pm.bpp = 8 THEN ColorTrixMap.Read[] ELSE NIL;
};
CtInfo: Commander.CommandProc ~ {
nArgs: INTEGER ← Args.NArgs[cmd];
IF nArgs # 0
AND nArgs # 2
THEN RETURN[$Failure, Rope.Concat["Bad argument(s); usage: ", ctInfoUsage]]
ELSE
SELECT nArgs
FROM
0 => {
info: CtInfoData ← NEW[CtInfoDataRec];
SeColorDisplayInfo[info];
info.viewer ← TypeScript.Create[info: [openHeight: 400, name: "CtInfo", data: info, scrollable: TRUE, column: right, iconic: TRUE]];
ViewerOps.OpenIcon[info.viewer];
info.out ← ViewerIO.CreateViewerStreams[NIL, info.viewer].out;
TRUSTED {Process.Detach[FORK Informer[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 => NULL;
};
CDNotifyProc: ColorDisplay.CDNotifyProc ~ {
IF old # new THEN NARROW[clientData, CtInfoData].colorDisplayChanged ← TRUE;
};
Informer:
PROC [info: CtInfoData] ~
TRUSTED {
report: BOOL ← FALSE;
key: TerminalDefs.KeyName;
action: ClassIncreek.ActionBody;
increek: ClassIncreek.Increek ← ClassIncreek.NewStdIncreek[];
viewPosition: ClassIncreek.ViewPosition ← ClassIncreek.GetPositionFrom[increek];
cdReg: ColorDisplay.CDRegistration ← ColorDisplay.RegisterCDNotifyProc[CDNotifyProc, info];
CedarProcess.SetPriority[background];
IO.PutRope[info.out, "\n"];
WHILE
NOT info.viewer.destroyed
DO
IF info.colorDisplayChanged
THEN {
SeColorDisplayInfo[info];
info.colorDisplayChanged ← FALSE;
};
action ← ClassIncreek.GetAction[self: increek, acceptance: clicksAndMotion];
IF viewPosition.mousePosition.color
THEN {
WITH ac: action
SELECT
FROM
keyDown => IF ac.value IN [Red..Yellow] THEN {key ← ac.value; report ← TRUE};
keyUp => IF ac.value IN [Red..Yellow] THEN {key ← ac.value; report ← FALSE};
ENDCASE;
IF report
THEN {
WITH ac: action
SELECT
FROM
keyDown, deltaMouse => {
info.x ← viewPosition.mousePosition.mouseX;
info.y ← info.pm.h-viewPosition.mousePosition.mouseY;
};
ENDCASE;
IF key = Blue
THEN
WITH ac: action
SELECT
FROM
keyDown => ManyPixels[info];
ENDCASE
ELSE
WITH ac: action
SELECT
FROM
keyDown, deltaMouse => APixel[info.out, info.pm, info.cmap, info.x, info.y];
ENDCASE;
};
};
ENDLOOP;
ColorDisplay.UnregisterCDNotifyProc[cdReg];
};
APixel:
PROC [out:
STREAM, pm: PixelMapMisc, cmap: Cmap, x, y:
INTEGER] ~ {
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 => NULL;
};
ManyPixels:
PROC [info: CtInfoData] ~ {
pixs: ARRAY [0..5) OF ARRAY [0..5) OF PixelInfo;
Bar:
PROC ~ {
IF info.pm.bpp = 8
THEN IO.PutF[info.out, "——————————————————————————————————\n"]
ELSE IO.PutF[info.out, "——————————————————————\n"]
};
PrintLine:
PROC [j:
INTEGER, proc:
PROC [i, j:
INTEGER], report:
BOOL ←
FALSE] ~ {
IF proc # PrintX THEN IO.PutRope[info.out, "| "];
FOR i: NAT IN [0..5) DO proc[i, j]; ENDLOOP;
IF report THEN IO.PutF[info.out, " %g", IO.int[info.y-2+j]];
IO.PutRope[info.out, "\n"];
};
PrintX:
PROC [i, j:
INTEGER] ~ {
IF info.pm.bpp = 8
THEN IO.PutF[info.out, " %3g\t", IO.int[info.x-2+i]]
ELSE IO.PutF[info.out, " %3g\t", IO.int[info.x-2+i]];
};
PrintPval:
PROC [i, j:
INTEGER] ~ {
IO.PutF[info.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, card:
CARDINAL] ~ {
IF info.pm.bpp = 8
THEN IO.PutF[info.out, " %g: %3g\t|", IO.rope[rope], IO.card[card]]
ELSE IO.PutF[info.out, " %3g\t|", IO.card[card]];
};
FOR j:
NAT
IN [0..5)
DO
y: INTEGER ← info.y-2+j;
FOR i:
NAT
IN [0..5)
DO
pixs[i][j] ← GetPixelInfo[info.pm, info.cmap, info.x-2+i, y];
ENDLOOP;
ENDLOOP;
IO.PutF[
info.out, "\n%g bit pixels centered at (%g, %g):\n",
IO.int[info.pm.bpp], IO.int[info.x], IO.int[info.y]];
Process.Pause[Process.MsecToTicks[100]];
[] ← info.viewer.class.scroll[info.viewer, thumb, 100];
PrintLine[0, PrintX];
Bar[];
FOR line:
NAT
IN [0..5)
DO
IF info.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 ~ {
IF CoordinatesOK[pm, x, y]
THEN
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;
};
Terminal.ModifyColorFrame[Terminal.Current[], GetInner, x, y, x+1, y+1];
RETURN[pix];
};
ctInfoUsage: ROPE ~ "\nctInfo [<x: INTEGER> <y: INTEGER>] -- Print the pixel value at (x, y).";
ViewerOps.RegisterViewerClass[$Info,
NEW[ViewerClasses.ViewerClassRec]];
Commander.Register["///Commands/CtInfo", CtInfo, ctInfoUsage];