BitTunerCmds:
CEDAR PROGRAM
IMPORTS AIS, Graphics, GraphicsOps, CGScreen, Inline, JaMOps, Rope, Real, TJaMGraphics, TJaMGraphicsContexts, Runtime
= BEGIN
ROPE: TYPE = Rope.ROPE;
Frame: TYPE = JaMInternal.Frame;
PopRope:
PROCEDURE [f: Frame]
RETURNS [rope:
ROPE] = {
s: string JaMBasic.Object ← JaMOps.PopString[f.opstk];
C:
PROC[c:
CHAR]
RETURNS [
BOOLEAN] =
{t[t.length]𡤌 t.length ← t.length+1; RETURN[FALSE]};
t: REF TEXT ← NEW[TEXT[s.length]];
t.length ← 0;
JaMOps.StringForAll[s, C];
rope ← Rope.FromRefText[t];
};
PushRope:
PROCEDURE [f: Frame, rope:
ROPE] = {
JaMOps.Push[
f.opstk,
JaMOps.MakeString[LOOPHOLE[rope.ToRefText[], LONG STRING]]
];
};
AllocateBitmap:
PROCEDURE [f: Frame] = {
-- allocates storage of the requested size.
side: NAT;
side ← JaMOps.PopInteger[f.opstk];
bitImage ← GraphicsOps.NewBitmap[side, side];
bitImageDescriptor ← DescriptorFor[bitImage];
};
DrawBitmap:
PROCEDURE [f: Frame] = {
Paint:
PROCEDURE [context: Graphics.Context] = {
GraphicsOps.DrawBitmap[self: context, bitmap: bitImage, w: bitImage.width, h: bitImage.height, x: 0, y: 0, xorigin: 0, yorigin: bitImage.height];
};
TJaMGraphics.Painter[Paint];
};
image: Graphics.ImageRef ← NIL;
AISName: Rope.Text ← "AISTemp$";
otherAISName: Rope.Text ← "AISTemp$$";
PingPongNames:
PROCEDURE = {
temp: Rope.Text ← AISName;
AISName ← otherAISName;
otherAISName ← temp;
};
StoreAIS:
PROCEDURE [f: Frame] = {
mapNumber: NAT ← JaMOps.PopInteger[f.opstk];
fileName: ROPE ← PopRope[f];
map: Wordmap ← wordmap[mapNumber];
aisFile: AIS.FRef;
aisWindow: AIS.WRef;
raster: AIS.RasterPart;
raster.scanCount ← map.side;
raster.scanLength ← map.side;
raster.scanMode ← rd;
raster.bitsPerPixel ← 8;
raster.linesPerBlock ← -1;
raster.paddingPerBlock ← 0;
aisFile ← AIS.CreateFile[name: LOOPHOLE[fileName], raster: @raster, overwrite: TRUE];
aisWindow ← AIS.OpenWindow[aisFile];
FOR i: NAT IN [0..map.side)
DO
FOR j: NAT
IN [0..map.side)
DO
sample: INT ← map[i*map.side+j];
sample ← MAX[0, MIN[map.unit, sample]];
AIS.WriteSample[aisWindow, 255 - 255*sample/map.unit, i, j];
ENDLOOP
ENDLOOP;
AIS.CloseWindow[aisWindow];
AIS.CloseFile[aisFile];
};
DrawMap:
PROCEDURE [f: Frame] = {
mapNumber: NAT ← JaMOps.PopInteger[f.opstk];
map: Wordmap ← wordmap[mapNumber];
aisFile: AIS.FRef;
aisWindow: AIS.WRef;
raster: AIS.RasterPart;
raster.scanCount ← map.side;
raster.scanLength ← map.side;
raster.scanMode ← rd;
raster.bitsPerPixel ← 8;
raster.linesPerBlock ← -1;
raster.paddingPerBlock ← 0;
aisFile ← AIS.CreateFile[name: LOOPHOLE[AISName], raster: @raster, overwrite: TRUE];
aisWindow ← AIS.OpenWindow[aisFile];
FOR i: NAT IN [0..map.side)
DO
FOR j: NAT
IN [0..map.side)
DO
sample: INT ← map[i*map.side+j];
sample ← MAX[0, MIN[map.unit, sample]];
AIS.WriteSample[aisWindow, 255 - 255*sample/map.unit, i, j];
ENDLOOP
ENDLOOP;
AIS.CloseWindow[aisWindow];
AIS.CloseFile[aisFile];
image ← GraphicsOps.NewAisImage[LOOPHOLE[AISName]];
PingPongNames[]; -- to fool the cache in CGAISImageImpl.
ReDrawMap[f];
};
ReDrawMap:
PROCEDURE [f: Frame] = {
Paint:
PROCEDURE [context: Graphics.Context] = {
Graphics.DrawImage[self: context, image: image];
};
TJaMGraphics.Painter[Paint];
};
BitImageContext:
PROCEDURE
RETURNS[Graphics.Context] = {
bitImageContext ← GraphicsOps.NewContextFromBitmap[bitImage];
RETURN [bitImageContext];
};
UseBitmap:
PROCEDURE [f: Frame] = {
TJaMGraphicsContexts.AddContext[f, BitImageContext, $BitTunerCmds, TRUE, TRUE];
TJaMGraphicsContexts.DisableViewer[f];
};
UseScreen:
PROCEDURE [f: Frame] = {
TJaMGraphicsContexts.DisableContext[f, $BitTunerCmds];
TJaMGraphicsContexts.EnableViewer[f];
};
GetBit:
PROCEDURE [f: Frame] = {ENABLE Runtime.BoundsFault => CONTINUE;
x, y: NAT;
bit: NAT ← 0;
y ← JaMOps.PopInteger[f.opstk];
x ← JaMOps.PopInteger[f.opstk];
bit ← bitImageDescriptor[bitImage.height-1-y][x];
JaMOps.PushInteger[f.opstk, bit];
};
PutBit:
PROCEDURE [f: Frame] = {ENABLE Runtime.BoundsFault => CONTINUE;
x, y: NAT;
bit: NAT ← JaMOps.PopInteger[f.opstk];
y ← JaMOps.PopInteger[f.opstk];
x ← JaMOps.PopInteger[f.opstk];
bitImageDescriptor[bitImage.height-1-y][x] ← bit;
};
LoadFromBitmap:
PROCEDURE [f: Frame] = {
mapNumber: NAT ← JaMOps.PopInteger[f.opstk];
map: Wordmap;
index: NAT ← 0;
IF wordmap[mapNumber] = NIL OR wordmap[mapNumber].side # bitImage.width THEN wordmap[mapNumber] ← NewWordmap[bitImage.width];
map ← wordmap[mapNumber];
map.unit ← 65536;
FOR i:
NAT
IN [0..map.side)
DO
FOR j:
NAT
IN [0..map.side)
DO
map[index] ← bitImageDescriptor[i][j]*map.unit;
index ← index + 1;
ENDLOOP
ENDLOOP
};
Div2:
PROCEDURE [a:
INT]
RETURNS [b:
INT] = INLINE {
b ← LOOPHOLE[LongNumberDiv2[LOOPHOLE[a]]]
};
LongNumberDiv2:
PROCEDURE [a: Inline.LongNumber]
RETURNS [b: Inline.LongNumber] = INLINE {
b.highbits ← Inline.BITSHIFT[a.highbits, -1] + Inline.BITAND[a.highbits, 100000B];
b.lowbits ← Inline.BITSHIFT[a.lowbits, -1] + Inline.BITSHIFT[a.highbits, 15];
};
ConvolveLeft:
PROCEDURE [f: Frame] = {
mapNumber: NAT ← JaMOps.PopInteger[f.opstk];
map: Wordmap ← wordmap[mapNumber];
index: NAT ← 0;
side: NAT ← map.side;
limit: NAT ← side-1;
FOR i:
NAT
IN [0..side)
DO
p: LONG POINTER TO INT ← @map[index];
FOR j:
NAT
IN [0..limit)
DO
p^ ← Div2[p^ + (p+SIZE[INT])^];
p ← p+SIZE[INT];
ENDLOOP;
index ← index + side;
ENDLOOP;
};
ConvolveUp:
PROCEDURE [f: Frame] = {
mapNumber: NAT ← JaMOps.PopInteger[f.opstk];
map: Wordmap ← wordmap[mapNumber];
index: NAT ← 0;
side: NAT ← map.side;
delta: NAT ← SIZE[INT]*side;
FOR i:
NAT
IN [0..side-1)
DO
p: LONG POINTER TO INT ← @map[index];
FOR j:
NAT
IN [0..side)
DO
p^ ← Div2[p^ + (p+delta)^];
p ← p+SIZE[INT];
ENDLOOP;
index ← index + side;
ENDLOOP;
};
ConvolveRight:
PROCEDURE [f: Frame] = {
mapNumber: NAT ← JaMOps.PopInteger[f.opstk];
map: Wordmap ← wordmap[mapNumber];
index: NAT ← map.length;
side: NAT ← map.side;
FOR i:
NAT
DECREASING
IN [0..side)
DO
p: LONG POINTER TO INT ← @map[index-1];
FOR j:
NAT
DECREASING IN [1..side)
DO
p^ ← Div2[p^ + (p-SIZE[INT])^];
p ← p-SIZE[INT];
ENDLOOP;
index ← index - side;
ENDLOOP;
};
ConvolveDown:
PROCEDURE [f: Frame] = {
mapNumber: NAT ← JaMOps.PopInteger[f.opstk];
map: Wordmap ← wordmap[mapNumber];
index: NAT ← map.length;
side: NAT ← map.side;
delta: NAT ← SIZE[INT]*side;
FOR i:
NAT
DECREASING
IN [1..side)
DO
p: LONG POINTER TO INT ← @map[index-1];
FOR j:
NAT
DECREASING IN [1..side)
DO
p^ ← Div2[p^ + (p-delta)^];
p ← p-SIZE[INT];
ENDLOOP;
index ← index - side;
ENDLOOP;
};
Copy:
PROCEDURE [f: Frame] = {
source: NAT ← JaMOps.PopInteger[f.opstk];
dest: NAT ← JaMOps.PopInteger[f.opstk];
destMap: Wordmap ← wordmap[dest];
sourceMap: Wordmap ← wordmap[source];
IF destMap = NIL OR destMap.side # sourceMap.side THEN destMap ← wordmap[dest] ← NewWordmap[sourceMap.side];
destMap.unit ← sourceMap.unit;
FOR index:
NAT
IN [0..sourceMap.length)
DO
destMap[index] ← sourceMap[index];
ENDLOOP;
};
Add:
PROCEDURE [f: Frame] = {
source: NAT ← JaMOps.PopInteger[f.opstk];
dest: NAT ← JaMOps.PopInteger[f.opstk];
destMap: Wordmap ← wordmap[dest];
sourceMap: Wordmap ← wordmap[source];
IF destMap.unit # sourceMap.unit OR destMap.side # sourceMap.side THEN ERROR;
FOR index:
NAT
IN [0..sourceMap.length)
DO
destMap[index] ← destMap[index] + sourceMap[index];
ENDLOOP;
};
Subtract:
PROCEDURE [f: Frame] = {
source: NAT ← JaMOps.PopInteger[f.opstk];
dest: NAT ← JaMOps.PopInteger[f.opstk];
destMap: Wordmap ← wordmap[dest];
sourceMap: Wordmap ← wordmap[source];
IF destMap.unit # sourceMap.unit OR destMap.side # sourceMap.side THEN ERROR;
FOR index:
NAT
IN [0..sourceMap.length)
DO
destMap[index] ← destMap[index] - sourceMap[index];
ENDLOOP;
};
AddShifted:
PROCEDURE [f: Frame] = {
scale: REAL ← JaMOps.PopReal[f.opstk];
deltaY: INTEGER ← JaMOps.PopInteger[f.opstk];
deltaX: INTEGER ← JaMOps.PopInteger[f.opstk];
source: NAT ← JaMOps.PopInteger[f.opstk];
dest: NAT ← JaMOps.PopInteger[f.opstk];
destMap: Wordmap ← wordmap[dest];
sourceMap: Wordmap ← wordmap[source];
index: NAT ← 0;
IF destMap.unit # sourceMap.unit THEN ERROR;
FOR i:
NAT
IN [0..sourceMap.side)
DO IF i-deltaY
IN [0..destMap.side)
THEN {
row: NAT ← (i-deltaY)*destMap.side;
FOR j:
NAT
IN [0..sourceMap.side)
DO
IF j+deltaX IN [0..destMap.side) THEN destMap[row+j+deltaX] ← destMap[row+j+deltaX] + Real.RoundLI[sourceMap[index]*scale];
index ← index + 1;
ENDLOOP;
} ENDLOOP;
};
SubSample:
PROCEDURE [f: Frame] = {
scaleDownFactor: NAT ← JaMOps.PopInteger[f.opstk];
source: NAT ← JaMOps.PopInteger[f.opstk];
dest: NAT ← JaMOps.PopInteger[f.opstk];
sourceMap: Wordmap ← wordmap[source];
destMap: Wordmap ← NewWordmap[sourceMap.side/scaleDownFactor];
destMap.unit ← sourceMap.unit;
FOR i:
NAT
IN [0..destMap.side)
DO
FOR j:
NAT
IN [0..destMap.side)
DO
destMap[destMap.side*i+j] ← sourceMap[(sourceMap.side*i+j)*scaleDownFactor];
ENDLOOP;
ENDLOOP;
};
Biggest:
PROCEDURE [f: Frame] = {
mapno: NAT ← JaMOps.PopInteger[f.opstk];
map: Wordmap ← wordmap[mapno];
max: INT ← FIRST[INT];
besti, bestj: NAT;
index: NAT ← 0;
FOR i:
NAT
IN [0..map.side)
DO
FOR j:
NAT
IN [0..map.side)
DO
IF map[index] > max THEN {max ← map[index]; besti ← i; bestj ← j};
index ← index + 1;
ENDLOOP;
ENDLOOP;
JaMOps.PushInteger[f.opstk, bestj];
JaMOps.PushInteger[f.opstk, map.side-1-besti];
};
Abs:
PROCEDURE [f: Frame] = {
mapno: NAT ← JaMOps.PopInteger[f.opstk];
map: Wordmap ← wordmap[mapno];
FOR index:
NAT
IN [0..map.length)
DO
map[index] ← ABS[map[index]];
ENDLOOP;
};
Sqr:
PROCEDURE [f: Frame] = {
mapno: NAT ← JaMOps.PopInteger[f.opstk];
map: Wordmap ← wordmap[mapno];
FOR index:
NAT
IN [0..map.length)
DO
int: INT ← map[index];
map[index] ← int*int/map.unit;
ENDLOOP;
};
Scale:
PROCEDURE [f: Frame] = {
scale: REAL ← JaMOps.PopReal[f.opstk];
mapno: NAT ← JaMOps.PopInteger[f.opstk];
map: Wordmap ← wordmap[mapno];
FOR index:
NAT
IN [0..map.length)
DO
map[index] ← Real.RoundLI[map[index]*scale];
ENDLOOP;
};
Threshold:
PROCEDURE [f: Frame] = {
threshold: REAL ← JaMOps.PopReal[f.opstk];
mapno: NAT ← JaMOps.PopInteger[f.opstk];
map: Wordmap ← wordmap[mapno];
t: INT ← Real.RoundLI[map.unit*threshold];
FOR index:
NAT
IN [0..map.length)
DO
map[index] ← IF map[index] > t THEN map.unit ELSE 0;
ENDLOOP;
};
Clip:
PROCEDURE [f: Frame] = {
max: REAL ← JaMOps.PopReal[f.opstk];
min: REAL ← JaMOps.PopReal[f.opstk];
mapno: NAT ← JaMOps.PopInteger[f.opstk];
map: Wordmap ← wordmap[mapno];
imax: INT ← Real.RoundLI[map.unit*max];
imin: INT ← Real.RoundLI[map.unit*min];
FOR index:
NAT
IN [0..map.length)
DO
map[index] ← MAX[imin, MIN[imax, map[index]]];
ENDLOOP;
};
Mask:
PROCEDURE [f: Frame] = {
source: NAT ← JaMOps.PopInteger[f.opstk];
dest: NAT ← JaMOps.PopInteger[f.opstk];
destMap: Wordmap ← wordmap[dest];
sourceMap: Wordmap ← wordmap[source];
IF destMap.unit # sourceMap.unit OR destMap.side # sourceMap.side THEN ERROR;
FOR index:
NAT
IN [0..sourceMap.length)
DO
IF sourceMap[index] = 0 THEN destMap[index] ← 0;
ENDLOOP;
};
Fixate:
PROCEDURE [f: Frame] = {
max: REAL ← JaMOps.PopReal[f.opstk];
center: REAL ← JaMOps.PopReal[f.opstk];
min: REAL ← JaMOps.PopReal[f.opstk];
imageno: NAT ← JaMOps.PopInteger[f.opstk];
maskno: NAT ← JaMOps.PopInteger[f.opstk];
image: Wordmap ← wordmap[imageno];
mask: Wordmap ← wordmap[maskno];
imax: INT ← Real.RoundLI[image.unit*max];
icenter: INT ← Real.RoundLI[image.unit*center];
imin: INT ← Real.RoundLI[image.unit*min];
IF image.side # mask.side THEN ERROR;
FOR index:
NAT
IN [0..image.length)
DO
sample: INT ← image[index];
IF mask[index]#0
AND imin <= sample
AND sample <= imax
THEN {
image[index] ← icenter;
mask[index] ← 0;
}
ENDLOOP;
};
Twiddle:
PROCEDURE [f: Frame] = {
max: REAL ← JaMOps.PopReal[f.opstk];
min: REAL ← JaMOps.PopReal[f.opstk];
unit: REAL ← JaMOps.PopReal[f.opstk];
imageno: NAT ← JaMOps.PopInteger[f.opstk];
changeno: NAT ← JaMOps.PopInteger[f.opstk];
change: Wordmap ← wordmap[changeno];
image: Wordmap ← wordmap[imageno];
imax: INT ← Real.RoundLI[change.unit*max];
imin: INT ← Real.RoundLI[change.unit*min];
iunit: INT ← Real.RoundLI[change.unit*unit];
IF image.side # change.side THEN ERROR;
FOR index:
NAT
IN [0..image.length)
DO
IF change[index]<=imin
THEN {
image[index] ← 0;
};
IF change[index]>=imax
THEN {
image[index] ← iunit;
};
ENDLOOP;
};
Histogram:
PROCEDURE [f: Frame] = {
mapNumber: NAT ← JaMOps.PopInteger[f.opstk];
map: Wordmap ← wordmap[mapNumber];
count: ARRAY [0..256] OF INT;
Paint:
PROCEDURE [context: Graphics.Context] = {
FOR index:
NAT
IN [0..256]
DO
Graphics.DrawBox[context, [index, 0, index+1, count[index]]];
ENDLOOP;
};
FOR index:
NAT
IN [0..256]
DO
count[index] ← 0;
ENDLOOP;
FOR index:
NAT
IN [0..map.length)
DO
sample: INT ← MAX[0, MIN[256, map[index]*256/map.unit]];
count[sample] ← count[sample] + 1;
ENDLOOP;
TJaMGraphics.Painter[Paint];
};
Statistics:
PROCEDURE [f: Frame] = {
mapNumber: NAT ← JaMOps.PopInteger[f.opstk];
map: Wordmap ← wordmap[mapNumber];
min: INT ← LAST[INT];
max: INT ← FIRST[INT];
sum: INT ← 0;
unit: REAL ← map.unit;
FOR index:
NAT
IN [0..map.length)
DO
sample: INT ← map[index];
min ← MIN[min, sample];
max ← MAX[max, sample];
sum ← sum + sample;
ENDLOOP;
JaMOps.PushReal[f.opstk, min/unit];
JaMOps.PushReal[f.opstk, max/unit];
JaMOps.PushReal[f.opstk, sum/(unit*map.length)];
};
SumOfSquares:
PROCEDURE [f: Frame] = {
mapNumber: NAT ← JaMOps.PopInteger[f.opstk];
map: Wordmap ← wordmap[mapNumber];
sumsqr: REAL ← 0;
unit: REAL ← map.unit;
FOR index:
NAT
IN [0..map.length)
DO
realSample: REAL ← map[index]/unit;
sumsqr ← sumsqr + realSample*realSample;
ENDLOOP;
JaMOps.PushReal[f.opstk, sumsqr];
};
Wordmap: TYPE = REF WordmapRec;
WordmapRec: TYPE = RECORD[unit: INT ← 1, side: NAT, words: SEQUENCE length: NAT OF INT];
NewWordmap:
PROCEDURE [side:
NAT]
RETURNS [wordmap: Wordmap] = {
wordmap ← NEW[WordmapRec[side*side]];
wordmap.side ← side;
};
wordmap: ARRAY [0..9] OF Wordmap;
bitImage: GraphicsOps.BitmapRef;
bitImageDescriptor: BitmapDescriptor;
bitImageContext: Graphics.Context;
BitmapDescriptor: PUBLIC TYPE = REF READONLY BitmapDescriptorRec;
BitmapDescriptorRec:
PUBLIC
TYPE =
RECORD[
bitmapRef: GraphicsOps.BitmapRef,
lines: SEQUENCE height: NAT OF LONG DESCRIPTOR FOR PACKED ARRAY OF [0..1]
];
DescriptorFor:
PUBLIC
PROCEDURE [bitmap: GraphicsOps.BitmapRef]
RETURNS [BitmapDescriptor] = {
bitmapDescriptor: REF BitmapDescriptorRec ← NEW[BitmapDescriptorRec[bitmap.height]];
raster: NAT ← bitmap.raster;
p: LONG POINTER ← LOOPHOLE[bitmap.base];
IF p=NIL THEN [base: p, raster: raster] ← CGScreen.Bits[];
FOR i:
NAT
IN [0..bitmap.height)
DO
bitmapDescriptor[i] ← DESCRIPTOR[p, bitmap.width];
p ← p + raster;
ENDLOOP;
bitmapDescriptor.bitmapRef ← bitmap;
RETURN[bitmapDescriptor];
};
DescBase:
PUBLIC
PROCEDURE [d:
LONG
DESCRIPTOR
FOR
PACKED
ARRAY
OF [0..1]]
RETURNS [LONG POINTER] = {RETURN[BASE[d]]};
DescLength:
PUBLIC
PROCEDURE [d:
LONG
DESCRIPTOR
FOR
PACKED
ARRAY
OF [0..1]]
RETURNS [INT] = {RETURN[LENGTH[d]]};
This module implements some operations on images that consist of two-dimensional arrays of intensities. Thses images are called maps. The model is a 10-register machine, with each register capable of holding a map. The registers are numbered 0 thru 9. In addition, there is a bitmap that can be hooked up to Graphics to capture a binary image. Operations on maps take one or two register numbers to specify the operands. The first of these is always the destination.
JaMOps.RegisterExplicit[JaMOps.defaultFrame, "bt.AllocateBitmap", AllocateBitmap];
<size: integer> -> . Allocates a size x size bitmap
JaMOps.RegisterExplicit[JaMOps.defaultFrame, "bt.DrawBitmap", DrawBitmap];
-> . Draws the bitmap
JaMOps.RegisterExplicit[JaMOps.defaultFrame, "bt.StoreAIS", StoreAIS];
<fileName: string> <register> -> . Saves the map in an AIS file
JaMOps.RegisterExplicit[JaMOps.defaultFrame, "bt.DrawMap", DrawMap];
<register> -> . Draws the map
JaMOps.RegisterExplicit[JaMOps.defaultFrame, "bt.ReDrawMap", ReDrawMap];
-> . redisplays the last image shown with DrawMap
JaMOps.RegisterExplicit[JaMOps.defaultFrame, "bt.GetBit", GetBit];
<x: integer> <y: integer> -> <value: integer> . Gets a bit out of the bitmap
JaMOps.RegisterExplicit[JaMOps.defaultFrame, "bt.PutBit", PutBit];
<bit: integer> <x: integer> <y: integer> -> . Puts a bit into the bitmap
JaMOps.RegisterExplicit[JaMOps.defaultFrame, "bt.ConvolveLeft", ConvolveLeft];
JaMOps.RegisterExplicit[JaMOps.defaultFrame, "bt.ConvolveRight", ConvolveRight];
JaMOps.RegisterExplicit[JaMOps.defaultFrame, "bt.ConvolveUp", ConvolveUp];
JaMOps.RegisterExplicit[JaMOps.defaultFrame, "bt.ConvolveDown", ConvolveDown];
<register> -> . Simple neighbor-averaging convolutions
JaMOps.RegisterExplicit[JaMOps.defaultFrame, "bt.Copy", Copy];
<dest: register> <source: register> -> . Copies the image
JaMOps.RegisterExplicit[JaMOps.defaultFrame, "bt.LoadFromBitmap", LoadFromBitmap];
<dest: register> -> . Makes a map from the bitmap
JaMOps.RegisterExplicit[JaMOps.defaultFrame, "bt.UseBitmap", UseBitmap];
-> . Makes graphics ops go to the bitmap.
JaMOps.RegisterExplicit[JaMOps.defaultFrame, "bt.UseScreen", UseScreen];
-> . Makes graphics ops go to the screen.
JaMOps.RegisterExplicit[JaMOps.defaultFrame, "bt.Add", Add];
<dest: register> <source: register> -> . Adds corresponding samples.
JaMOps.RegisterExplicit[JaMOps.defaultFrame, "bt.Subtract", Subtract];
<dest: register> <source: register> -> . dest ← dest - source.
JaMOps.RegisterExplicit[JaMOps.defaultFrame, "bt.AddShifted", AddShifted];
<dest: register> <source: register> <deltaX: integer> <deltaY: integer> <scale: number> -> . Takes map from source, moves it by (deltaX, deltaY), scales each element, and adds the image to dest.
JaMOps.RegisterExplicit[JaMOps.defaultFrame, "bt.SubSample", SubSample];
<dest: register> <source: register> <k: integer> -> . Extracts every kth sample of source to make dest
JaMOps.RegisterExplicit[JaMOps.defaultFrame, "bt.Biggest", Biggest];
<register> -> <x: integer> <y: integer>. Finds coordinates of largest sample.
JaMOps.RegisterExplicit[JaMOps.defaultFrame, "bt.Abs", Abs];
<register> -> . Replaces each sample by its absolute value.
JaMOps.RegisterExplicit[JaMOps.defaultFrame, "bt.Sqr", Sqr];
<register> -> . Replaces each sample by its square.
JaMOps.RegisterExplicit[JaMOps.defaultFrame, "bt.Scale", Scale];
<register> <scale: number> -> . Multiplies each sample by scale.
JaMOps.RegisterExplicit[JaMOps.defaultFrame, "bt.Threshold", Threshold];
<register> <threshold: number> -> . Makes a binary image based on the threshold.
JaMOps.RegisterExplicit[JaMOps.defaultFrame, "bt.Clip", Clip];
<register> <min: number> <max: number> -> . Clips the samples to lie in the given range.
JaMOps.RegisterExplicit[JaMOps.defaultFrame, "bt.Mask", Mask];
<dest: register> <source: register> -> . Forces dest to 0 whereever source is 0.
JaMOps.RegisterExplicit[JaMOps.defaultFrame, "bt.Histogram", Histogram];
<register> -> .
JaMOps.RegisterExplicit[JaMOps.defaultFrame, "bt.Fixate", Fixate];
<mask: register> <image: register> <min: number> <center: number> <max: number> -> .
JaMOps.RegisterExplicit[JaMOps.defaultFrame, "bt.Twiddle", Twiddle];
you figure it out.
JaMOps.RegisterExplicit[JaMOps.defaultFrame, "bt.Statistics", Statistics];
<register> -> <min: number> <max: number> <mean: number> .
JaMOps.RegisterExplicit[JaMOps.defaultFrame, "bt.SumOfSquares", SumOfSquares];
<register> -> <sumOfSquares: number> .
END.