DIRECTORY Args, Commander, CommanderOps, CtBasic, CtDispatch, CtFile, CtMap, CtMisc, CtMod, CtPix, Convert, FileNames, Imager, ImagerBackdoor, ImagerPath, ImagerSample, IO, Process, Real, RealFns, Rope; CtSimpleCommandsImpl: CEDAR PROGRAM IMPORTS Args, CommanderOps, Convert, CtBasic, CtDispatch, CtFile, CtMap, CtMisc, CtMod, CtPix, FileNames, Imager, ImagerBackdoor, ImagerPath, ImagerSample, IO, Process, Real, RealFns, Rope ~ BEGIN SampleMap: TYPE ~ CtBasic.SampleMap; SampleMaps: TYPE ~ CtBasic.SampleMaps; PixelArray: TYPE ~ CtBasic.PixelArray; ValueProc: TYPE ~ CtBasic.ValueProc; RGB: TYPE ~ CtBasic.RGB; CtProc: TYPE ~ CtDispatch.CtProc; Cmap: TYPE ~ CtMap.Cmap; Table: TYPE ~ CtMod.Table; Box: TYPE ~ ImagerSample.Box; SampleBuffer: TYPE ~ ImagerSample.SampleBuffer; Vec: TYPE ~ ImagerSample.Vec; ROPE: TYPE ~ Rope.ROPE; ctClearUsage: ROPE ~ "Ct Clear [r[gb]] [-wi] [-w]: clear the color display."; CtClear: CtProc ~ { rVal, gVal, bVal: CARDINAL; rArg, gArg, bArg: Args.Arg; [rArg, gArg, bArg] ¬ Args.ArgsGet[cmd, "[iii" ! Args.Error => {error ¬ reason; CONTINUE}]; IF error # NIL THEN RETURN; rVal ¬ MIN[255, IF rArg.ok THEN INTEGER[rArg.int] ELSE 255]; gVal ¬ MIN[255, IF gArg.ok THEN INTEGER[gArg.int] ELSE rVal]; bVal ¬ MIN[255, IF bArg.ok THEN INTEGER[bArg.int] ELSE gVal]; CtBasic.FillMaps[maps, rVal, rVal, gVal, bVal]; affect ¬ maps.box; }; ctLineUsage: ROPE ~ "Ct Line x0 y0 x1 y1 r[gb] [-wi] [-w]: draw a line."; CtLine: CtProc ~ { x0, y0, x1, y1, r, g, b: Args.Arg; [x0, y0, x1, y1, r, g, b] ¬ Args.ArgsGet[cmd, "[iiiiiii" ! Args.Error => {error ¬ reason; CONTINUE}]; IF NOT (error = NIL AND x0.ok AND y0.ok AND x1.ok AND y1.ok AND r.ok) THEN RETURN; IF maps.bpp = 24 THEN { IF NOT (g.ok AND b.ok) THEN RETURN[error: "bad arguments"]; CtBasic.PutRGBLine[maps, x0.int, y0.int, x1.int, y1.int, [r.int, g.int, b.int]]; } ELSE CtBasic.PutBWLine[maps[0].map, x0.int, y0.int, x1.int, y1.int, r.int]; affect ¬ [[y0.int, x0.int], [y1.int, x1.int]]; }; ctColorBarsUsage: ROPE ~ "Ct ColorBars [-SMPTE] [-EIA] (default is SMPTE)."; CtColorBars: CtProc ~ { PutBox: PROC [x0, y0, x1, y1: INTEGER, rgb: RGB] ~ { CtBasic.PutRGBBox[maps, maps.x+x0, maps.y+y0, maps.x+x1, maps.y+y1, rgb]; }; smpte, eia: Args.Arg; [smpte, eia] ¬ Args.ArgsGet[cmd, "-smpte%b-eia%b" ! Args.Error => {error ¬ reason; CONTINUE}]; IF error # NIL THEN RETURN; IF maps.bpp # 24 THEN RETURN[error: "only works for 24 bpp"]; CtMap.Mono[]; CtBasic.FillMaps[maps]; -- Start with black PutBox[0*91, 0, 1*91, 360, [191, 191, 191]]; -- Gray PutBox[1*91, 0, 2*91, 360, [191, 191, 000]]; -- Yellow PutBox[2*91, 0, 3*91, 360, [000, 191, 191]]; -- Cyan PutBox[3*91, 0, 4*91, 360, [000, 191, 000]]; -- Green PutBox[4*91, 0, 5*91, 360, [191, 000, 191]]; -- Magenta PutBox[5*91, 0, 6*91, 360, [191, 000, 000]]; -- Red PutBox[6*91, 0, 7*91, 360, [000, 000, 191]]; -- Blue PutBox[0*114, 360, 1*114, 480, [0, 76, 127]]; -- NTSC -I PutBox[1*114, 360, 2*114, 480, [255, 255, 255]]; -- White PutBox[2*114, 360, 3*114, 480, [75, 0, 139]]; -- NTSC +Q IF NOT eia.ok THEN { PutBox[0*91, 322, 7*91, 360, [000, 000, 000]]; -- Black for split PutBox[0*91, 322, 1*91, 360, [000, 000, 191]]; -- Blue PutBox[2*91, 322, 3*91, 360, [191, 000, 191]]; -- Magenta PutBox[4*91, 322, 5*91, 360, [000, 191, 191]]; -- Cyan PutBox[6*91, 322, 7*91, 360, [191, 191, 191]]; -- Gray PutBox[5*91, 360, 5*91+30, 480, [11, 11, 11]]; -- Black+4 for PLUGE }; affect ¬ [[0, 0], [480, 7*91]]; }; ctRampUsage: ROPE ~ "Ct Ramp [-h|-v] [-wi] [-w]: draw horiz | vert ramp."; CtRamp: CtProc ~ { v, h: Args.Arg; [v, h] ¬ Args.ArgsGet[cmd, "-v%b-h%b" ! Args.Error => {error ¬ reason; CONTINUE}]; IF error # NIL THEN RETURN; FOR n: NAT IN [0..maps.nChannels) DO IF h.bool THEN CtPix.RampH[maps[n].map] ELSE CtPix.RampV[maps[n].map]; ENDLOOP; affect ¬ maps.box; }; ctPieUsage: ROPE ~ "Ct Pie [-wi] [-w]: draw a circular ramp."; CtPie: CtProc ~ { FOR i: INT IN [0..maps.nChannels) DO CtPix.Pie[maps[i].map, [0, 0], 0]; ENDLOOP; affect ¬ maps.box; }; ctDitherUsage: ROPE ~ "Ct Dither [pixel-value] [-wi] [-w]: dither the picture. If no value specified, dither the existing image; otherwise, create a dithered flat field of intensity ."; CtDither: CtProc ~ { value: CARDINAL ¬ 0; value ¬ Args.ArgInt[cmd ! Args.Error => CONTINUE].int; FOR n: NAT IN [0..maps.nChannels) DO CtPix.Dither[maps[n].map, value]; ENDLOOP; affect ¬ maps.box; }; ctGridUsage: ROPE ~ "[-pVal][-space][-width][-wi][-w]."; CtGrid: CtProc ~ { InnerGrid: PROC [map: SampleMap] ~ { FOR i: NAT ¬ maps.box.min.f, i+space WHILE i < maps.box.max.f DO FOR j: NAT ¬ maps.box.min.s, j+1 WHILE j < maps.box.max.s DO ImagerSample.Fill[map, [[j, i], [j+width, i+width]], pVal]; ENDLOOP; ENDLOOP; FOR j: NAT ¬ maps.box.min.s, j+space WHILE j < maps.box.max.s DO FOR i: NAT ¬ maps.box.min.f, i+1 WHILE i < maps.box.max.f DO ImagerSample.Fill[map, [[j, i], [j+width, i+width]], pVal]; ENDLOOP; ENDLOOP; }; pVal, space, width: CARDINAL; pValArg, spaceArg, widthArg: Args.Arg; [pValArg, spaceArg, widthArg] ¬ Args.ArgsGet[cmd, "-pVal%i-space%i-width%i" ! Args.Error => {error ¬ reason; CONTINUE}]; IF error # NIL THEN RETURN; pVal ¬ IF pValArg.ok THEN pValArg.int ELSE 0; pVal ¬ 256*pVal+pVal; space ¬ IF spaceArg.ok THEN spaceArg.int ELSE 40; width ¬ IF widthArg.ok THEN widthArg.int ELSE 1; FOR n: NAT IN [0..maps.nChannels) DO InnerGrid[maps[n].map]; ENDLOOP; affect ¬ maps.box; }; ctCheckUsage: ROPE ~ "Ct Check [-pVal] [-space] [-wi] [-w]."; CtCheck: CtProc ~ { InnerCheck: PROC [map: SampleMap] ~ { ySense: BOOL ¬ TRUE; FOR y: NAT ¬ maps.box.min.s, y+space WHILE y < maps.box.max.s DO xSense: BOOL ¬ (ySense ¬ NOT ySense); FOR x: NAT ¬ maps.box.min.f, x+space WHILE x < maps.box.max.f DO Process.CheckForAbort[]; IF xSense THEN ImagerSample.Fill[map, [[y, x], [y+space, x+space]], pVal]; xSense ¬ NOT xSense; ENDLOOP; ENDLOOP; }; pVal, space: CARDINAL; pValArg, spaceArg: Args.Arg; [pValArg, spaceArg] ¬ Args.ArgsGet[cmd, "-pVal%i-space%i" ! Args.Error => {error ¬ reason; CONTINUE}]; IF error # NIL THEN RETURN; pVal ¬ IF pValArg.ok THEN pValArg.int ELSE 0; space ¬ IF spaceArg.ok THEN spaceArg.int ELSE 40; FOR n: NAT IN [0..maps.nChannels) DO InnerCheck[maps[n].map]; ENDLOOP; affect ¬ maps.box; }; ctSinesUsage: ROPE ~ "Ct Sines -minF -maxF [-hOnly] [-wi] [-w]: sine pattern, F is freq."; CtSines: CtProc ~ { Sines: PROC [map: SampleMap, minF, maxF: INT] ~ { Action: PROC [samples: ImagerSample.SampleBuffer] ~ TRUSTED { IF hOnly.bool THEN FOR x: INTEGER IN [0..maps.size.f) DO dt: REAL ¬ inc*(x*mul+minF); ival: CARDINAL ¬ Real.Round[127*RealFns.Sin[x*dt]+127.5]; samples[x] ¬ ival; ENDLOOP; FOR y: INTEGER IN [maps.box.min.s..maps.box.max.s) DO dt: REAL ¬ inc*((y-maps.box.min.s)*mul+minF); Process.CheckForAbort[]; IF NOT hOnly.bool THEN FOR x: INTEGER IN [0..maps.size.f) DO ival: CARDINAL ¬ Real.Round[127*RealFns.Sin[x*dt]+127.5]; samples[x] ¬ ival; ENDLOOP; FOR n: NAT IN [0..maps.nChannels) DO ImagerSample.PutSamples[maps[n].map, [y, maps.x],, samples, 0, maps.size.f]; ENDLOOP; ENDLOOP; }; mul: REAL ¬ (maxF-minF)/REAL[maps.size.s]; ImagerSample.DoWithScratchSamples[maps.size.f, Action]; }; minF, maxF, hOnly: Args.Arg; inc: REAL ¬ 2.0*3.14159265358979/REAL[maps.size.f]; [minF, maxF, hOnly] ¬ Args.ArgsGet[cmd, "-minF%i-maxF%i-hOnly%b" ! Args.Error => {error ¬ reason; CONTINUE}]; FOR n: NAT IN [0..maps.nChannels) DO Sines[maps[n].map, IF minF.ok THEN minF.int ELSE 0, IF maxF.ok THEN maxF.int ELSE 10]; ENDLOOP; affect ¬ maps.box; }; ctPalUsage: ROPE ~ "Ct Pal [INT: nrows] [-smooth]: display palette."; CtPal: CtProc ~ { n, smooth: Args.Arg; [n, smooth] ¬ Args.ArgsGet[cmd, "[i-smooth%b" ! Args.Error => {error ¬ reason; CONTINUE}]; IF error = NIL THEN affect ¬ CtMod.Palette[maps, IF n.ok THEN n.int ELSE 5, smooth.bool]; }; ctSafeUsage: ROPE ~ "Ct Safe: outline the SMPTE safe action and safe title areas."; CtSafe: CtProc ~ { Outline: PROC [x, y, w, h, r: REAL] ~ { sinCos45: REAL ~ 0.7071067811; rcos: REAL ¬ r*sinCos45; rsin: REAL ¬ r*sinCos45; t: Imager.Trajectory ¬ ImagerPath.MoveTo[[x+r, y]]; t ¬ ImagerPath.ArcTo[t, [x+r-rcos, y+r-rsin], [x, y+r]]; t ¬ ImagerPath.LineTo[t, [x, y+h-r]]; t ¬ ImagerPath.ArcTo[t, [x+r-rcos, y+h-r+rsin], [x+r, y+h]]; t ¬ ImagerPath.LineTo[t, [x+w-r, y+h]]; t ¬ ImagerPath.ArcTo[t, [x+w-r+rcos, y+h-r+rsin], [x+w, y+h-r]]; t ¬ ImagerPath.LineTo[t, [x+w, y+r]]; t ¬ ImagerPath.ArcTo[t, [x+w-r+rcos, y+r-rsin], [x+w-r, y]]; Imager.MaskStrokeTrajectory[context, t, TRUE]; }; Imager.SetColor[context, ImagerBackdoor.invert]; Outline[32, 24, 576, 432, 115]; -- SMPTE recommended safe action area Outline[65, 48, 510, 384, 101]; -- SMPTE recommended safe title area }; GammaSwitch: PROC [cmd: Commander.Handle] RETURNS [gamma: BOOL ¬ FALSE] ~ { FOR n: NAT IN [0..Args.NArgs[cmd]) DO IF Eq["-gamma", Args.GetRope[cmd, n]] THEN RETURN[TRUE]; ENDLOOP; }; ctLumUsage: ROPE ~ "Ct Lum [-gamma] [-wi] [-w]: process image into luminance; if 8 bit image, the color map will be set to mono or (if -gamma) gamma of 2.2."; CtLum: CtProc ~ { cm: Cmap ¬ CtMap.Read[]; gamma: BOOL ¬ GammaSwitch[cmd]; IF gamma THEN CtMap.DeGamma[2.2, cm]; IF gamma THEN CtMap.Gamma[2.2] ELSE CtMap.Mono[]; IF maps.bpp = 24 THEN CtMod.Lum24[maps, cm] ELSE CtMod.Indirect[maps[0].map, CtMap.GetLuminanceTable[cm], maps.box]; affect ¬ maps.box; }; ctPseudoToRGBUsage: ROPE ~ "Ct PsuedoToRGB [-gamma] [-wi] [-w]: creates name-red, -grn, -blu.ais from pseudo color image -gamma: create for viewing with gamma map (mono otherwise)."; CtPseudoToRGB: CtProc ~ { name: ROPE ~ Args.GetRope[cmd]; IF name = NIL THEN RETURN[error: ctPseudoToRGBUsage] ELSE { gamma: BOOL _ GammaSwitch[cmd]; map: SampleMap _ IF maps.bpp = 8 THEN maps[0].map ELSE maps[1].map; cmap: Cmap _ CtMap.Read[]; base: ROPE ~ FileNames.ResolveRelativePath[name]; tmp: SampleMap _ ImagerSample.NewSampleMap[maps.box, 8]; SaveOneFile: PROC [color: ROPE, i: NAT] ~ { IO.PutF1[cmd.out, "%g . . . ", IO.rope[color]]; ImagerSample.Transfer[tmp, maps[0].map]; CtMod.Indirect[tmp, CtMap.GetTable[cmap, i], maps.box]; CtFile.SaveSampleMapToFile[tmp, Rope.Cat[base, "-", color, ".ais"]]; }; IF maps.bpp = 24 THEN RETURN[error: "this command for 8 bpp only"]; IF gamma THEN CtMap.DeGamma[2.2, cmap]; IO.PutRope[cmd.out, "writing "]; SaveOneFile["red", 0]; SaveOneFile["grn", 1]; SaveOneFile["blu", 2]; IO.PutRope[cmd.out, "done!\n"]; }; affect _ maps.box; }; ctIndirectUsage: ROPE ~ "Ct Indirect [-gamma] [-wi] [-w]: process 24 bit image by indirecting through the color map. -gamma: create for viewing with gamma map (mono otherwise)."; CtIndirect: CtProc ~ { cmap: Cmap ¬ CtMap.Read[]; IF GammaSwitch[cmd] THEN CtMap.DeGamma[2.2, cmap]; IF maps.nChannels # 3 THEN RETURN[error: "color display must be at 24 bits per pixel."]; FOR n: NAT IN [0..3) DO CtMod.Indirect[maps[n].map, CtMap.GetTable[cmap, n], maps.box]; ENDLOOP; affect ¬ maps.box; }; ctDifUsage: ROPE ~ "Ct Dif Display |dif| of boxes."; CtDif: CtProc ~ { x0, y0, x1, y1, x2, y2, w, h: Args.Arg; [x0, y0, x1, y1, x2, y2, w, h] ¬ Args.ArgsGet[cmd, "%iiiiiiii" ! Args.Error => {error ¬ reason; CONTINUE}]; IF error # NIL THEN RETURN; FOR n: NAT IN [0..maps.nChannels) DO CtMod.Dif[maps[n].map, x0.int, y0.int, x1.int, y1.int, x2.int, y2.int, w.int, h.int]; ENDLOOP; affect ¬ [[y2.int, x2.int], [y2.int+h.int, x2.int+w.int]]; }; ctPValUsage: ROPE ~ "Ct PVal [oldVal] . . . [-wi] [-w]."; CtPVal: CtProc ~ { ENABLE Convert.Error => GOTO Bad; argv: CommanderOps.ArgumentVector ¬ CommanderOps.Parse[cmd]; IF argv.argc < 3 THEN RETURN[error: "bad arguments"] ELSE { l: LIST OF NAT ¬ NIL; new: INTEGER ¬ Convert.IntFromRope[argv[1]]; FOR i: NAT IN [2..argv.argc) DO l ¬ CONS[Convert.IntFromRope[argv[i]], l]; ENDLOOP; FOR n: NAT IN [0..maps.nChannels) DO CtMod.PVal[maps[n].map, new, l]; ENDLOOP; affect ¬ maps.box; }; EXITS Bad => RETURN[error: "conversion error"]; }; ctBlurUsage: ROPE ~ "Ct Blur [blur-radius, default = 1] [-wi] [-w]."; CtBlur: CtProc ~ { radius: NAT ~ IF Args.NArgs[cmd] = 1 THEN Args.ArgInt[cmd].int ELSE 1; denom: NAT ~ (2*radius+1)*(2*radius+1); x0: INTEGER ~ maps.x+radius; y0: INTEGER ~ maps.y+radius; x1: INTEGER ~ maps.x+maps.w-1-radius; y1: INTEGER ~ maps.y+maps.h-1-radius; IO.PutRope[cmd.out, "Getting pixel array(s) . . . "]; IF maps.bpp = 24 THEN { Blur: CtBasic.RGBProc ~ { r, g, b: SampleBuffer; rr, gg, bb: CARDINAL ¬ 0; IF x IN [x0..x1] AND y IN [y0..y1] THEN { FOR yy: INTEGER IN [y-radius..y+radius] DO r ¬ red[yy]; g ¬ grn[yy]; b ¬ blu[yy]; FOR xx: INTEGER IN [x-radius..x+radius] DO rr ¬ rr + r[xx]; gg ¬ gg + g[xx]; bb ¬ bb + b[xx]; ENDLOOP ENDLOOP; rgb ¬ [rr/denom, gg/denom, bb/denom]; } ELSE { n: CARDINAL ¬ 0; FOR yy: INTEGER IN [y-radius..y+radius] DO IF yy NOT IN [y0..y1] THEN LOOP; r ¬ red[yy]; g ¬ grn[yy]; b ¬ blu[yy]; FOR xx: INTEGER IN [x-radius..x+radius] DO IF xx NOT IN [x0..x1] THEN LOOP; rr ¬ rr + r[xx]; gg ¬ gg + g[xx]; bb ¬ bb + b[xx]; n ¬ n+1; ENDLOOP; ENDLOOP; rgb ¬ IF n # 0 THEN [rr/n, gg/n, bb/n] ELSE [0, 0, 0]; }; }; red, grn, blu: PixelArray; red ¬ CtBasic.PixelArrayFromSampleMap[maps[0].map]; grn ¬ CtBasic.PixelArrayFromSampleMap[maps[1].map]; blu ¬ CtBasic.PixelArrayFromSampleMap[maps[2].map]; IO.PutRope[cmd.out, "blurring . . .\n"]; CtBasic.PutRGBFrame[maps, Blur]; } ELSE { Blur: CtBasic.ValueProc ~ { vv: CARDINAL ¬ 0; IF x IN [x0..x1] AND y IN [y0..y1] THEN { FOR yy: INTEGER IN [y-radius..y+radius] DO sb: SampleBuffer ¬ bw[yy]; FOR xx: INTEGER IN [x-radius..x+radius] DO vv ¬ vv+sb[xx]; ENDLOOP; ENDLOOP; value ¬ vv/denom; } ELSE { n: CARDINAL ¬ 0; FOR yy: INTEGER IN [y-radius..y+radius] DO IF yy IN [y0..y1] THEN { sb: SampleBuffer ¬ bw[yy]; FOR xx: INTEGER IN [x-radius..x+radius] DO IF xx IN [x0..x1] THEN {vv ¬ vv+sb[xx]; n ¬ n+1} ENDLOOP; }; ENDLOOP; value ¬ IF n # 0 THEN vv/n ELSE 0; }; }; bw: PixelArray ¬ CtBasic.PixelArrayFromSampleMap[maps[0].map]; IO.PutRope[cmd.out, "blurring . . .\n"]; CtBasic.PutBWFrame[maps[0].map, Blur]; }; affect ¬ maps.box; }; ctGammasUsage: ROPE ~ " Ct Gammas [gamma0] [gamma1] apply varying gamma to the screen"; CtGammas: CtProc ~ { width, height, gamma0, gamma1: Args.Arg; [width, height, gamma0, gamma1] ¬ Args.ArgsGet[cmd, "%ii[rr" ! Args.Error => GOTO Bad]; IF width.ok AND width.int > 0 AND height.ok AND height.int > 0 THEN { context: Imager.Context ¬ CtBasic.ContextFromSampleMaps[maps]; i: NAT ¬ 0; w: NAT ¬ width.int; h: NAT ¬ height.int; g0: REAL ¬ IF gamma0.ok THEN gamma0.real ELSE 0.5; g1: REAL ¬ IF gamma1.ok THEN gamma1.real ELSE 3.0; nTiles: NAT ¬ MAX[1, (maps.h/h)*(maps.w/w)]; FOR yy: NAT ¬ maps.y, yy+h WHILE yy+h <= maps.y+maps.h DO FOR xx: NAT ¬ maps.x, xx+w WHILE xx+w <= maps.x+maps.w DO g: REAL ¬ g0+(IF nTiles = 1 THEN 0.5 ELSE REAL[i]/REAL[nTiles-1])*(g1-g0); CtMod.Gammatize[maps, g, xx, yy, w, h]; Imager.SetGray[context, IF i > nTiles/2 THEN 1 ELSE 0]; CtMisc.PrintRope[Convert.RopeFromReal[g, 4], [xx, yy+h],,,, context]; i ¬ i+1; ENDLOOP; ENDLOOP; } ELSE RETURN[error: "bad arguments"]; affect ¬ maps.box; EXITS Bad => NULL; }; ctReplicateUsage: ROPE ~ "Ct Replicate \nreplicate the rectangle as much as possible"; CtReplicate: CtProc ~ { ENABLE {Convert.Error => GOTO Bad}; x, y, w, h: INT; argv: CommanderOps.ArgumentVector ¬ CommanderOps.Parse[cmd]; IF argv.argc # 5 THEN RETURN[error: "bad arguments"]; x ¬ Convert.IntFromRope[argv[1]]; y ¬ Convert.IntFromRope[argv[2]]; w ¬ Convert.IntFromRope[argv[3]]; h ¬ Convert.IntFromRope[argv[4]]; IF x>=0 AND y>=0 AND w>=0 AND h>=0 AND NOT (x=0 AND y=0 AND w=0 AND h=0) THEN { srcBox: Box ¬ [[maps.y, maps.x], [maps.y+h, maps.x+w]]; CtBasic.MoveMaps[maps, [y, x], [maps.y, maps.x], [h, w]]; FOR yy: NAT ¬ maps.y, yy+h WHILE yy < maps.y+maps.h DO FOR xx: NAT ¬ maps.x, xx+w WHILE xx < maps.x+maps.w DO dstBox: Box ¬ [[yy, xx], [yy+h, xx+w]]; CtBasic.CopyClippedMaps[maps, maps, srcBox, dstBox]; ENDLOOP; ENDLOOP; } ELSE RETURN[error: "bad arguments"]; affect ¬ maps.box; EXITS Bad => RETURN[error: "bad arguments"]; }; ctMedialUsage: ROPE ~ "Ct Medial [-wi] [-w]: incr values to region centers."; CtMedial: CtProc ~ { v0, v1, count: CARDINAL; SetUp: PROC [x, y: CARDINAL] ~ { Process.CheckForAbort[]; v0 ¬ in[y][x]; count ¬ 0; }; Test: PROC [x, y, xx, yy: CARDINAL, noCompare: BOOL] ~ INLINE { val: CARDINAL; v1 ¬ in[y][x]; IF v0 # v1 THEN {count ¬ 0; v0 ¬ v1} ELSE IF count < 255 THEN count ¬ count+1; val ¬ MIN[count, out[yy][xx]+1]; IF noCompare THEN out[y][x] ¬ val ELSE IF val < out[y][x] THEN out[y][x] ¬ val; }; map: SampleMap ¬ maps[0].map; box: Box ~ ImagerSample.GetBox[map]; in: PixelArray ~ CtBasic.PixelArrayFromSampleMap[map]; out: PixelArray ~ CtBasic.AllocatePixelArray[box]; x0: CARDINAL ~ box.min.f; y0: CARDINAL ~ box.min.s; x1: CARDINAL ~ box.max.f-1; y1: CARDINAL ~ box.max.s-1; FOR x: NAT IN [x0..x1] DO out[y0][x] ¬ out[y1][x] ¬ 0; ENDLOOP; FOR y: NAT IN [y0..y1] DO out[y][x0] ¬ out[y][x1] ¬ 0; ENDLOOP; IO.PutRope[cmd.out, "Doing left to right, "]; FOR y: NAT IN (y0..y1) DO -- downwards, left to right SetUp[x0, y]; FOR x: NAT IN (x0..x1) DO Test[x, y, x, y-1, TRUE]; ENDLOOP; ENDLOOP; IO.PutRope[cmd.out, "right to left, "]; FOR y: NAT DECREASING IN (y0..y1) DO -- upwards, right to left SetUp[x1, y]; FOR x: NAT DECREASING IN (x0..x1) DO Test[x, y, x, y+1, FALSE]; ENDLOOP; ENDLOOP; IO.PutRope[cmd.out, "up to down, "]; FOR x: NAT IN (x0..x1) DO -- rightwards, up to down SetUp[x, y0]; FOR y: NAT IN (y0..y1) DO Test[x, y, x-1, y, FALSE]; ENDLOOP; ENDLOOP; IO.PutRope[cmd.out, "and down to up\n"]; FOR x: NAT DECREASING IN (x0..x1) DO -- leftwards, down to up SetUp[x, y1]; FOR y: NAT DECREASING IN (y0..y1) DO Test[x, y, x+1, y, FALSE]; ENDLOOP; ENDLOOP; CtBasic.TransferPixelArrayToMap[out, map]; affect ¬ maps.box; }; aveNonBlackUsage: ROPE ~ "Ct AveNonBlack \taverage all non-black parts of the screen"; AveNonBlackCmd: CtProc ~ { radius: NAT ~ IF Args.NArgs[cmd] = 1 THEN Args.ArgInt[cmd].int ELSE 1; denom: NAT ~ (2*radius+1)*(2*radius+1); x0: INTEGER ~ maps.x+radius; y0: INTEGER ~ maps.y+radius; x1: INTEGER ~ maps.x+maps.w-1-radius; y1: INTEGER ~ maps.y+maps.h-1-radius; affect ¬ maps.box; IO.PutRope[cmd.out, "Getting pixel array(s) . . . "]; IF maps.bpp<= 8 THEN { Ave: CtBasic.ValueProc ~ { val: CARDINAL ¬ bw[y][x]; IF val # 0 THEN RETURN[val] ELSE { vv, count: CARDINAL ¬ 0; FOR yy: INTEGER IN [y-radius..y+radius] DO IF yy IN [y0..y1] THEN { sb: SampleBuffer ¬ bw[yy]; FOR xx: INTEGER IN [x-radius..x+radius] DO IF xx IN [x0..x1] AND (val ¬ sb[xx]) # 0 THEN {vv ¬ vv+val; count ¬ count+1} ENDLOOP; }; ENDLOOP; IF count # 0 THEN value ¬ vv/count ELSE value ¬ 0; }; }; bw: PixelArray ¬ CtBasic.PixelArrayFromSampleMap[maps[0].map]; IO.PutRope[cmd.out, "averaging . . .\n"]; CtBasic.PutBWFrame[maps[0].map, Ave]; } ELSE RETURN[error: "must be < 8 bpp"]; }; ctLeftUsage: ROPE ~ "Ct Left [-wi] [-w]: shift image left."; ctRightUsage: ROPE ~ "Ct Right [-wi] [-w]: shift image right."; ctUpUsage: ROPE ~ "Ct Up [-wi] [-w]: shift image up."; ctDownUsage: ROPE ~ "Ct Down [-wi] [-w]: shift image down."; CtLeft, CtRight, CtUp, CtDown: CtProc ~ { arg: Args.Arg; [arg] ¬ Args.ArgsGet[cmd, "%i" ! Args.Error => {error ¬ reason; CONTINUE}]; IF error # NIL THEN RETURN; FOR n: NAT IN [0..maps.nChannels) DO SELECT TRUE FROM Eq[cmd.command, "left"] => CtMod.Left[maps[n].map, arg.int]; Eq[cmd.command, "right"] => CtMod.Left[maps[n].map, -arg.int]; Eq[cmd.command, "up"] => CtMod.Up[maps[n].map, arg.int]; Eq[cmd.command, "down"] => CtMod.Up[maps[n].map, -arg.int]; ENDCASE; ENDLOOP; }; ctNegateUsage: ROPE ~ "Ct Negate [-wi] [-w]: negate the image."; CtNegate: CtProc ~ { FOR n: NAT IN [0..maps.nChannels) DO CtMod.Negate[maps[n].map]; ENDLOOP; affect ¬ maps.box; }; ctReflectUsage: ROPE ~ "Ct Reflect <-h|-v> [-wi] [-w]: reflect the image."; CtReflect: CtProc ~ { v, h: Args.Arg; [v, h] ¬ Args.ArgsGet[cmd, "-v%b-h%b" ! Args.Error => {error ¬ reason; CONTINUE}]; IF error # NIL THEN RETURN; FOR n: NAT IN [0..maps.nChannels) DO m: SampleMap ¬ maps[n].map; IF h.bool THEN CtMod.ReflectH[m] ELSE CtMod.ReflectV[m]; ENDLOOP; affect ¬ maps.box; }; ctMirrorUsage: ROPE ~ "Ct Mirror <-l|-r|-t|-b> [-wi] [-w]: mirror the image."; CtMirror: CtProc ~ { MirrorH: PROC [maps: SampleMaps, topToBottom: BOOL] ~ { FOR n: NAT IN [0..maps.nChannels) DO CtMod.MirrorH[maps[n].map, topToBottom]; ENDLOOP; }; MirrorV: PROC [maps: SampleMaps, leftToRight: BOOL] ~ { FOR n: NAT IN [0..maps.nChannels) DO CtMod.MirrorV[maps[n].map, leftToRight]; ENDLOOP; }; l, r, t, b: Args.Arg; [l, r, t, b] ¬ Args.ArgsGet[cmd, "-l%b-r%b-t%b-b%b" ! Args.Error => {error ¬ reason; CONTINUE}]; IF error # NIL THEN RETURN; SELECT TRUE FROM l.bool => MirrorV[maps, TRUE]; r.bool => MirrorV[maps, FALSE]; t.bool => MirrorH[maps, TRUE]; b.bool => MirrorH[maps, FALSE]; ENDCASE => MirrorH[maps, FALSE]; affect ¬ maps.box; }; ctTransposeUsage: ROPE ~ "Ct Transpose [-wi] [-w]: transpose the image."; CtTranspose: CtProc ~ { FOR n: NAT IN [0..maps.nChannels) DO CtMod.Transpose[maps[n].map]; ENDLOOP; affect ¬ maps.box; }; ctRotateUsage: ROPE ~ "Ct Rotate [-radians] [-wi] [-w] rotate the image (positive rotation is counter-clockwise)."; CtRotate: CtProc ~ { degrees: REAL; angleA, inRadiansA: Args.Arg; [angleA, inRadiansA] ¬ Args.ArgsGet[cmd, "%r-radians%b"]; degrees ¬ IF inRadiansA.bool THEN (180.0/3.1415926535)*angleA.real ELSE angleA.real; FOR i: INTEGER IN [0..maps.nChannels) DO CtMod.Rotate[maps[i].map, degrees]; ENDLOOP; affect ¬ maps.box; }; Eq: PROC [r1, r2: ROPE] RETURNS [BOOL] ~ {RETURN[Rope.Equal[r1, r2, FALSE]]}; CtDispatch.RegisterCtOp["Clearing/Drawing:", NIL, NIL]; CtDispatch.RegisterCtOp["Clear", CtClear, ctClearUsage]; CtDispatch.RegisterCtOp["Line", CtLine, ctLineUsage]; CtDispatch.RegisterCtOp["ColorBars", CtColorBars, ctColorBarsUsage]; CtDispatch.RegisterCtOp["Ramp", CtRamp, ctRampUsage]; CtDispatch.RegisterCtOp["Pie", CtPie, ctPieUsage]; CtDispatch.RegisterCtOp["Grid", CtGrid, ctGridUsage]; CtDispatch.RegisterCtOp["Check", CtCheck, ctCheckUsage]; CtDispatch.RegisterCtOp["Sines", CtSines, ctSinesUsage]; CtDispatch.RegisterCtOp["Dither", CtDither, ctDitherUsage]; CtDispatch.RegisterCtOp["Palette/Safety:", NIL, NIL]; CtDispatch.RegisterCtOp["Pal", CtPal, ctPalUsage]; CtDispatch.RegisterCtOp["Safe", CtSafe, ctSafeUsage]; CtDispatch.RegisterCtOp["Processing:", NIL, NIL]; CtDispatch.RegisterCtOp["PseudoToRGB", CtPseudoToRGB, ctPseudoToRGBUsage]; CtDispatch.RegisterCtOp["Indirect", CtIndirect, ctIndirectUsage]; CtDispatch.RegisterCtOp["Lum", CtLum, ctLumUsage]; CtDispatch.RegisterCtOp["PVal", CtPVal, ctPValUsage]; CtDispatch.RegisterCtOp["Blur", CtBlur, ctBlurUsage]; CtDispatch.RegisterCtOp["Dif", CtDif, ctDifUsage]; CtDispatch.RegisterCtOp["Medial", CtMedial, ctMedialUsage]; CtDispatch.RegisterCtOp["Replicate", CtReplicate, ctReplicateUsage]; CtDispatch.RegisterCtOp["Gammas", CtGammas, ctGammasUsage]; CtDispatch.RegisterCtOp["AveNonBlack", AveNonBlackCmd, aveNonBlackUsage]; CtDispatch.RegisterCtOp["Left", CtLeft, ctLeftUsage]; CtDispatch.RegisterCtOp["Right", CtRight, ctRightUsage]; CtDispatch.RegisterCtOp["Up", CtUp, ctUpUsage]; CtDispatch.RegisterCtOp["Down", CtDown, ctDownUsage]; CtDispatch.RegisterCtOp["Negate", CtNegate, ctNegateUsage]; CtDispatch.RegisterCtOp["Reflect", CtReflect, ctReflectUsage]; CtDispatch.RegisterCtOp["Mirror", CtMirror, ctMirrorUsage]; CtDispatch.RegisterCtOp["Transpose", CtTranspose, ctTransposeUsage]; CtDispatch.RegisterCtOp["Rotate", CtRotate, ctRotateUsage]; END. z CtSimpleCommandsImpl.mesa Copyright Σ 1985, 1992 by Xerox Corporation. All rights reserved. Bloomenthal, December 7, 1992 4:22 pm PST Heckbert, June 1, 1988 0:08:05 am PDT Shoemake, June 19, 1989 2:40:08 am PDT Glassner, November 14, 1990 2:57 pm PST Clearing/Drawing Commands For EIA color bars: For SMPTE split color bars, with PLUGE black: Safe Image/Title and Palette Commands context: Imager.Context ¬ CtBasic.ContextFromSampleMaps[maps]; Processing Commands Replicate and Gammas Command: Image Processing Commands: Other Manipulation Commands Support Start Code Clearing/Drawing Palette/Safety Processing Manipulation Κo–"cedarcode" style•NewlineDelimiter ™™Jšœ Οeœ6™BJ™)J™%J™&J™'—J˜JšΟk œ žœ˜ΚJ˜šΠblœžœž˜#Jšžœ•žœ˜Ό—J˜šœž˜J˜Jšœ žœ˜&Jšœ žœ˜(Jšœžœ˜(Jšœ žœ˜&Jšžœžœ žœ˜Jšœ žœ˜$Jšœ žœ˜Jšœ žœ˜Jšœž œ˜!Jšœžœ˜0Jšœž œ˜!Jšžœž œžœ˜—headšΟl™šœžœΟsœ ‘œ˜TJ˜—šΠbnœ ˜Jšœžœ˜J˜JšœOžœ˜ZJšžœ žœžœžœ˜Jš œžœžœ žœžœ žœ˜˜OJ˜—š’œ ˜J˜"˜8Jšœ!žœ˜,—Jšžœžœ žœžœžœžœžœžœžœžœ˜Ršžœ˜šžœ˜Jš žœžœžœžœžœ˜;J˜PJ˜—JšžœG˜K—J˜.J˜J˜—šœžœ6˜LJ˜—š’ œ ˜šΟnœžœžœžœ˜4JšœI˜IJšœ˜—Jšœ˜˜1Jšœ!žœ˜,—Jšžœ žœžœžœ˜Jšžœžœžœ!˜=J™Jšœ ˜ JšœΟc˜+Jšœ/€˜6Jšœ/€ ˜8Jšœ/€˜6Jšœ/€˜7Jšœ/€ ˜9Jšœ/€˜5Jšœ/€˜6Jšœ0€ ˜:Jšœ2€˜:Jšœ/€ ˜:J™-šžœžœžœ˜Jšœ/€˜AJšœ/€˜6Jšœ/€ ˜9Jšœ/€˜6Jšœ/€˜6Jšœ/€˜CJ˜—J˜˜J˜——šœ žœ?˜PJ˜—š’œ ˜J˜JšœGžœ˜RJšžœ žœžœžœ˜šžœžœžœž˜$šžœ˜ Jšžœ˜Jšžœ˜—Jšžœ˜—J˜˜J˜——šœ žœ4˜DJ˜—š’œ ˜Jš žœžœžœžœ$žœ˜PJ˜Jšœ˜J˜—šœžœ˜˜²J˜——š’œ ˜Jšœžœ˜Jšœ(žœ˜6šžœžœžœž˜$J˜!Jšžœ˜—J˜J˜J˜—š œ žœ ‘œ ‘œ ‘œ˜MJ˜—š’œ ˜š£ œžœ˜$šžœžœžœž˜@šžœžœžœž˜J˜0Jšœ €%˜EJšœ €$˜DJ˜——š ™š £ œžœžœ žœžœ˜Kšžœžœžœž˜%Jšžœ$žœžœžœ˜8Jšžœ˜—J˜J˜—šœ žœ˜J˜“J˜—š’œ ˜J˜Jšœžœ˜Jšžœžœ˜%Jšžœžœžœ˜1šžœ˜Jšžœ˜JšžœD˜H—J˜J˜J˜—šœžœ˜J˜ͺJ˜—š’ œ ˜Jšœžœ˜šžœž˜ Jšžœžœ˜&šžœ˜Jšœžœ˜Jšœžœžœ žœ ˜CJ˜Jšœžœ'˜1J˜8š£ œžœ žœžœ˜+Jšžœžœ˜/J˜(J˜7J˜DJ˜—Jšžœžœžœ'˜CJšžœžœ˜'Jšžœ˜ J˜J˜J˜Jšžœ˜J˜——J˜J˜J˜—šœžœ˜J˜’J˜—š’ œ ˜J˜Jšžœžœ˜2Jšžœžœžœ7˜Xšžœžœžœž˜Jšœ?˜?Jšžœ˜—J˜J˜J˜—šœ žœ<˜LJ˜—š’œ ˜J˜'˜ Jšœ?žœ˜J—Jšžœ žœžœžœ˜šžœžœžœž˜$Jšœ‘œ‘œ‘œ‘œ‘œ‘œ‘œ‘œ˜UJšžœ˜—J˜:J˜J˜—šœ žœ@˜QJ˜—š’œ ˜Jšžœžœ˜!J˜<šžœ˜Jšžœžœ˜#šžœ˜Jš œžœžœžœžœ˜Jšœžœ ˜,Jš žœžœžœžœžœ"žœ˜SJš žœžœžœžœ!žœ˜NJ˜—J˜—Jšžœžœ˜/J˜J˜—šœ žœ:˜KJ˜—š’œ ˜Jš œžœžœžœžœ˜FJšœžœ˜'Jšœžœ˜Jšœžœ˜Jšœžœ˜%Jšœžœ˜%Jšžœ3˜5šžœ˜šžœ˜š£œ˜J˜Jšœ žœ˜šžœžœ žœžœ ˜"šžœ˜šžœžœžœž˜*J˜ J˜ J˜ šžœžœžœž˜*J˜J˜J˜Jšž˜—Jšžœ˜—J˜%J˜—šžœ˜Jšœžœ˜šžœžœžœž˜*Jš žœžœžœ žœžœ˜ J˜ J˜ J˜ šžœžœžœž˜*Jš žœžœžœ žœžœ˜ J˜J˜J˜J˜Jšžœ˜—Jšžœ˜—Jšœžœžœžœ ˜6J˜——J˜—J˜J˜3J˜3J˜3Jšžœ&˜(J˜ J˜—šžœ˜š£œ˜Jšœžœ˜šžœžœ žœžœ ˜"šžœ˜šžœžœžœž˜*J˜Jšž‘œ‘ž‘ž‘œ‘ž‘œ‘œ‘œ ‘žœ˜CJšžœ˜—J˜J˜—šžœ˜Jšœžœ˜šžœžœžœž˜*šžœžœ žœ˜J˜šžœžœžœž˜*Jšžœžœ žœ˜0Jšžœ˜—J˜—Jšžœ˜—Jšœžœžœžœ˜"J˜——J˜—J˜>Jšžœ&˜(J˜&J˜——J˜J˜——š ™šœžœI˜]J˜—š’œ ˜J˜(JšœMžœ˜Wšžœ žœžœ žœ˜>šžœ˜J˜>Jšœžœ˜ Jšœžœ ˜Jšœžœ˜Jš œžœžœ žœ žœ˜2Jš œžœžœ žœ žœ˜2Jšœžœžœ˜,šžœžœžœž˜9šžœžœžœž˜9Jš œžœžœ žœžœžœžœ˜JJ˜'Jšœžœžœžœ˜7J˜EJ˜Jšžœ˜—Jšžœ˜—J˜—Jšžœžœ˜$—J˜Jšžœžœ˜J˜J˜—šœžœF˜\J˜—š’ œ ˜Jšžœžœ˜#Jšœ žœ˜J˜J˜ šžœžœžœ ž˜$Jšœžœ˜Jšžœ˜—Jšžœ˜—Jšžœ"˜$š žœžœžœ žœ€˜4J˜ šžœžœžœ ž˜Jšœžœ˜Jšžœ˜—Jšžœ˜—Jšžœ&˜(š žœžœžœ žœ€˜=J˜ šžœžœžœ ž˜$Jšœžœ˜Jšžœ˜—Jšžœ˜—Jšœ*˜*J˜J˜——š ™šœžœ˜Jšœ=˜=J˜—š’œ ˜Jš œžœžœžœžœ˜FJšœžœ˜'Jšœžœ˜Jšœžœ˜Jšœžœ˜%Jšœžœ˜%J˜Jšžœ3˜5šžœ ˜šžœ˜š£œ˜Jšœžœ ˜šžœ˜ Jšžœžœ˜šžœ˜Jšœ žœ˜šžœžœžœž˜*šžœžœ žœ˜J˜šžœžœžœž˜*šžœžœ žœ˜(Jšžœ˜#—Jšžœ˜—J˜—Jšžœ˜—Jšžœ žœžœ ˜2J˜——J˜—J˜>Jšžœ'˜)J˜%J˜—Jšžœžœ˜&—J˜——š ™Jšœ žœ ‘œ'˜IJšœ žœ‘œ(˜KJšœ žœ ‘œ%˜Cšœ žœ ‘œ'˜HJ˜—š’œ ˜)J˜Jšœ@žœ˜KJšžœ žœžœžœ˜šžœžœžœž˜$šžœžœž˜Jšœ<˜˜>Jšœ8˜8Jšœ;˜;Jšžœ˜—Jšžœ˜—J˜J˜—šœžœ3˜FJ˜—š’œ ˜Jš žœžœžœžœžœ˜HJ˜J˜J˜—šœžœ=˜QJ˜—š’ œ ˜J˜JšœGžœ˜RJšžœ žœžœžœ˜šžœžœžœž˜$J˜Jšžœžœžœ˜8Jšžœ˜—J˜J˜J˜—šœžœA˜TJ˜—š’œ ˜š£œžœ!žœ˜7šžœžœžœž˜$J˜(Jšžœ˜—J˜—š£œžœ!žœ˜7šžœžœžœž˜$J˜(Jšžœ˜—J˜—J˜˜3Jšœ!žœ˜,—Jšžœ žœžœžœ˜šžœžœž˜Jšœžœ˜Jšœžœ˜ Jšœžœ˜Jšœžœ˜ Jšžœžœ˜ —J˜J˜J˜—šœžœ9˜OJ˜—š’ œ ˜Jš žœžœžœžœžœ˜KJ˜J˜J˜—šœžœ˜Jšœl˜lJ˜—š’œ ˜Jšœ žœ˜J˜J˜9Jšœ žœžœ"žœ ˜TJš žœžœžœžœ%žœ˜UJ˜J˜——š ™Jš£œžœ žœžœžœžœžœ˜M—š  ™ ™Jšœ-žœžœ˜:J˜>J˜;J˜HJ˜;J˜:J˜;J˜>J˜>J˜A—™Jšœ,žœžœ˜9J˜:J˜;—™ Jšœ(žœžœ˜6J˜LJ˜EJ˜8J˜;J˜;J˜:J˜AJ˜HJ˜?JšœK˜K—™ J˜;J˜>J˜7J˜;J˜AJ˜DJ˜AJ˜HJ˜A—J˜—Jšž˜J™J™—…—]yύ