SlowSampleMapOps.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Michael Plass, December 4, 1985 11:31:32 am PST
Willie-Sue, August 18, 1986 6:02:20 pm PDT
Provides a safe set of operations on two-dimensional arrays of small unsigned integers.
~
BEGIN
This interface provides most of the functionality of BitBlt, without the attendant risk of smashing the world. To avoid confusion no matter how the represented image is oriented, terms like height and width are avoided, and the coordinates are expressed in terms of s and f, for slow and fast. On a display, the s axis is normally vertical, and points down, but on a printer that scans in the long direction, the f axis will point up.
Some of the operations in this interface are documented by code fragments; note that in case of unsuccessful completion (due to bounds fault, for instance), the set of samples moved by the implementation may differ from that implied by the documentation.
SampleMap: TYPE ~ SampleMapOps.SampleMap;
SubMap:
TYPE ~ SampleMapOps
.SubMap;
bitsPerWord:
NAT ~ Basics.bitsPerWord;
CVEC:
TYPE ~ SampleMapOps.
CVEC;
zeroCVEC: CVEC ~ [0, 0];
lastCVEC:
CVEC ~ [
CARDINAL.
LAST,
CARDINAL.
LAST];
Function: TYPE ~ SampleMapOps.Function;
nullFunction: Function ~ SampleMapOps.nullFunction;
Operations
Create:
PROC [sSize:
CARDINAL, fSize:
CARDINAL, bitsPerSample: [0..Basics.bitsPerWord]]
RETURNS [s: SampleMap];
creates a SampleMap with no zero entries
CreateZ:
PROC [sSize:
CARDINAL, fSize:
CARDINAL, bitsPerSample: [0..Basics.bitsPerWord]]
RETURNS [s: SampleMap];
creates a SampleMap with all zero entries
Copy: PROC [subMap: SubMap] RETURNS [SampleMap];
DoubleCopy: PROC [to, slowTo, from: SampleMap, destStart: CVEC];
GetSample:
PROC [sampleMap: SampleMap, index:
CVEC]
RETURNS [
CARDINAL];
PutSample:
PROC [sampleMap: SampleMap, index:
CVEC, value:
CARDINAL,
function: Function ← nullFunction, goodDest: SampleMap];
Stores modified value into the SampleMap at indexed location, dropping extra high-order bits.
Bounds fault if index is out of range.
Transfer: PROC [dest: SampleMap, destStart: CVEC ← zeroCVEC, source: SubMap,
function: Function ← nullFunction, goodDest: SampleMap];
size ← MIN[source.size, Size[dest]-destStart, Size[source.sampleMap]-source.start];
FOR s: CARDINAL IN [0..size.s) DO
FOR f: NAT IN [0..size.f) DO
sample: CARDINAL ~ GetSample[source.sampleMap, [source.start.s+s, source.start.f+f]];
PutSample[dest, [destStart.s+s, destStart.f+f], sample, function];
ENDLOOP;
ENDLOOP;
Move: PROC [sampleMap: SampleMap, destStart: CVEC ← zeroCVEC,
sourceStart: CVEC ← zeroCVEC, size: CVEC ← lastCVEC,
function: Function ← nullFunction, goodDest: SampleMap];
Transfers a rectangular region of the sampleMap, ordering it so ripple does not occur even if the rectangles overlap.
Fill:
PROC [dest: SubMap, value:
CARDINAL, function: Function ← nullFunction, goodDest: SubMap];
TileBox:
PROC [dest: SampleMap, start:
CVEC, size:
CVEC, source: SampleMap, s0, f0:
INTEGER, phase:
NAT, function: Function ← nullFunction, goodDest: SampleMap];
Tiles the rectangle designated by (start, size) with the tile designated by (source, s0, f0, phase).
start, size, s0, and f0 all work in the dest coordinate system.
The DIV and MOD functions in the following take the sign of the remainder equal to the sign of the divisor, rather than of the dividend as is usual.
FOR s: NAT IN [start.s..start.s+size.s) DO
FOR f: NAT IN [start.f..start.f+size.f) DO
sSource: CARDINAL ~ (s-s0) MOD source.sSize;
fSource: CARDINAL ~ (f-f0 - ((s-s0)/source.sSize)*phase) MOD source.fSize;
sample: CARDINAL ~ GetSample[source, [sSource, fSource]];
PutSample[dest, [s, f], sample, function];
ENDLOOP;
ENDLOOP;
Sample Buffers
When performing operations on many contiguous samples, it is usually a good idea to unpack them into a one-word-per-sample buffer, work on them, and pack them up again into the output. This works well because whole-word access is typically much faster than partial word access (although byte access is not too bad). The following operations will help to do this kind of processing.
Buffer:
TYPE ~ SampleMapOps.Buffer;
maxCount:
NAT ~
LAST[
NAT];
Get:
PROC [buffer: Buffer, start:
NAT ← 0, count:
NAT ← maxCount,
sampleMap: SampleMap, s, f:
NAT ← 0, ds:
NAT ← 0, df:
NAT ← 1];
FOR j: NAT IN [0..MIN[count, NAT[buffer.length-start]]) DO
buffer[start+j] ← GetSample[sampleMap, [s+j*ds, f+j*df]];
ENDLOOP;
Put:
PROC [buffer: Buffer, start:
NAT ← 0, count:
NAT ← maxCount,
sampleMap: SampleMap, s, f:
NAT ← 0, ds:
NAT ← 0, df:
NAT ← 1,
function: Function ← nullFunction, goodDest: SampleMap];
FOR j: NAT IN [0..MIN[count, NAT[buffer.length-start]]) DO
PutSample[sampleMap, [s+j*ds, f+j*df], buffer[start+j], function];
ENDLOOP;