ImagerPixelArrayImpl.mesa
Copyright Ó 1984, 1985, 1986, 1987, 1991, 1993 by Xerox Corporation. All rights reserved.
Michael Plass, March 11, 1993 12:03 pm PST
Doug Wyatt, March 7, 1986 4:20:36 pm PST
DIRECTORY
Basics USING [BITSHIFT, NonNegative],
ImagerPixel USING [PixelBuffer, PixelMap, PixelMapRep],
ImagerPixelArray USING [ErrorDesc, maxCount, maxVec, PixelArray, PixelArrayClassRep, PixelArrayRep],
ImagerPixelArrayPrivate USING [CopyProc, GetProc, GetSamplesProc, MaxSampleValueProc, PixelArrayClass, PixelArrayClassRep, TransferProc],
ImagerSample USING [BasicTransfer, Copy, DoWithScratchMap, DoWithScratchSamples, Function, Get, GetBitsPerSample, GetBox, GetSamples, maxBitsPerSample, maxCount, NewSampleMap, nullFunction, Put, PutSamples, ReIndex, Sample, SampleBuffer, SampleMap],
ImagerTransformation USING [Equal, ScanMode, SFToXY, Transformation],
RuntimeError USING [BoundsFault],
SF USING [Box, Inside, Min, Neg, Size, Sub, Vec, zeroVec];
ImagerPixelArrayImpl: CEDAR PROGRAM
IMPORTS Basics, ImagerSample, ImagerTransformation, RuntimeError, SF
EXPORTS ImagerPixelArray, ImagerPixelArrayPrivate
~ BEGIN OPEN ImagerPixelArrayPrivate, ImagerPixelArray;
Vec: TYPE ~ SF.Vec;
Transformation: TYPE ~ ImagerTransformation.Transformation;
ScanMode: TYPE ~ ImagerTransformation.ScanMode;
Sample: TYPE ~ ImagerSample.Sample;
SampleBuffer: TYPE ~ ImagerSample.SampleBuffer;
PixelBuffer: TYPE ~ ImagerPixel.PixelBuffer;
SampleMap: TYPE ~ ImagerSample.SampleMap;
PixelMap: TYPE ~ ImagerPixel.PixelMap;
PixelMapRep: TYPE ~ ImagerPixel.PixelMapRep;
Function: TYPE ~ ImagerSample.Function;
nullFunction: Function ~ ImagerSample.nullFunction;
zeroVec: SF.Vec ~ SF.zeroVec;
PixelArrayClass: TYPE ~ ImagerPixelArrayPrivate.PixelArrayClass;
PixelArrayClassRep: PUBLIC TYPE ~ ImagerPixelArrayPrivate.PixelArrayClassRep;
Error: PUBLIC ERROR [error: ErrorDesc] ~ CODE;
BoundsCheck: PROC [arg: INT, limit: NAT] RETURNS [sameArg: NAT] ~ INLINE {
IF LOOPHOLE[arg, CARD] >= CARD[limit] THEN ERROR RuntimeError.BoundsFault;
RETURN [arg]
};
GetClass: PUBLIC PROC [pa: PixelArray] RETURNS [ATOM] ~ {
class: PixelArrayClass ~ pa.class;
RETURN[class.type];
};
MaxSampleValue: PUBLIC PROC [pa: PixelArray, i: NAT] RETURNS [Sample] ~ {
class: PixelArrayClass ~ pa.class;
RETURN class.MaxSampleValue[pa: pa, i: BoundsCheck[i, pa.samplesPerPixel]];
};
Get: PUBLIC PROC [pa: PixelArray, i: NAT, s, f: INT] RETURNS [Sample] ~ {
class: PixelArrayClass ~ pa.class;
iCheck: NAT ~ BoundsCheck[i, pa.samplesPerPixel];
sRem: INT ~ Basics.NonNegative[pa.sSize-Basics.NonNegative[s]];
fRem: INT ~ Basics.NonNegative[pa.fSize-Basics.NonNegative[f]];
[] ¬ Basics.NonNegative[sRem-1];
[] ¬ Basics.NonNegative[fRem-1];
RETURN class.Get[pa: pa, i: i, s: s, f: f];
};
GetSamples: PUBLIC PROC [pa: PixelArray, i: NAT ¬ 0, s, f: INT ¬ 0,
buffer: SampleBuffer, start: NAT ¬ 0, count: NAT ¬ maxCount] ~ {
class: PixelArrayClass ~ pa.class;
iCheck: NAT ~ BoundsCheck[i, pa.samplesPerPixel];
sRem: INT ~ Basics.NonNegative[pa.sSize-Basics.NonNegative[s]];
fRem: INT ~ Basics.NonNegative[pa.fSize-Basics.NonNegative[f]];
actualCount: NAT ~ MIN[buffer.length-start, count];
[] ¬ Basics.NonNegative[sRem-1];
[] ¬ Basics.NonNegative[fRem-actualCount];
class.GetSamples[pa: pa, i: i, s: s, f: f, buffer: buffer, start: start, count: actualCount];
};
GetPixels: PUBLIC PROC [pa: PixelArray, s, f: INT ¬ 0,
pixels: PixelBuffer, start: NAT ¬ 0, count: NAT ¬ maxCount] ~ {
FOR i: NAT IN[0..pa.samplesPerPixel) DO
GetSamples[pa, i, s, f, pixels[i], start, count]
ENDLOOP
};
Transfer: PUBLIC PROC [pa: PixelArray, i: NAT ¬ 0, s, f: INT ¬ 0, dst: SampleMap, dstMin: Vec ¬ zeroVec, size: Vec ¬ maxVec, function: Function ¬ nullFunction] ~ {
class: PixelArrayClass ~ pa.class;
iCheck: NAT ~ BoundsCheck[i, pa.samplesPerPixel];
sRem: INT ~ Basics.NonNegative[pa.sSize-Basics.NonNegative[s]];
fRem: INT ~ Basics.NonNegative[pa.fSize-Basics.NonNegative[f]];
dstBox: SF.Box ~ ImagerSample.GetBox[dst];
actualSize: Vec ¬ dstBox.max.Sub[dstMin].Min[size];
IF sRem<actualSize.s THEN actualSize.s ¬ sRem;
IF fRem<actualSize.f THEN actualSize.f ¬ fRem;
class.Transfer[pa: pa, i: i, s: s, f: f, dst: dst, dstMin: dstMin, size: actualSize, function: function];
};
BitsPerSampleFromMaxSample: PROC [maxSample: CARD] RETURNS [bitsPerSample: NAT ¬ 0] ~ {
UNTIL maxSample = 0 DO
bitsPerSample ¬ bitsPerSample + 1;
maxSample ¬ maxSample / 2;
ENDLOOP;
};
Copy: PUBLIC PROC [pa: PixelArray] RETURNS [PixelArray] ~ {
class: PixelArrayClass ~ pa.class;
SELECT TRUE FROM
pa.immutable => RETURN [pa];
class.Copy#NIL => RETURN [class.Copy[pa]];
ENDCASE => {
samplesPerPixel: NAT ~ pa.samplesPerPixel;
pm: PixelMapData ~ NEW[PixelMapRep[samplesPerPixel]];
sSize: INT ~ pa.sSize;
fSize: INT ~ pa.fSize;
pm.box ¬ [max: [s: sSize, f: fSize]];
FOR i: NAT IN[0..samplesPerPixel) DO
bitsPerSample: NAT ~ BitsPerSampleFromMaxSample[MaxSampleValue[pa, i]];
sm: SampleMap ~ ImagerSample.NewSampleMap[box: pm.box, bitsPerSample: bitsPerSample];
Transfer[pa: pa, i: i, dst: sm];
pm[i] ¬ sm;
ENDLOOP;
RETURN[New[class: pixelMapClass, data: pm, immutable: TRUE,
samplesPerPixel: samplesPerPixel, sSize: sSize, fSize: fSize, m: pa.m]];
};
};
GetViaGetSamples: PROC [pa: PixelArray, i: NAT, s, f: INT] RETURNS [Sample] ~ {
class: PixelArrayClass ~ pa.class;
value: Sample ¬ 0;
action: PROC [buffer: SampleBuffer] ~ {
class.GetSamples[pa: pa, i: i, s: s, f: f, buffer: buffer, start: 0, count: 1];
value ¬ buffer[0];
};
ImagerSample.DoWithScratchSamples[1, action];
RETURN[value];
};
GetViaTransfer: PROC [pa: PixelArray, i: NAT, s, f: INT] RETURNS [Sample] ~ {
class: PixelArrayClass ~ pa.class;
value: Sample ¬ 0;
action: PROC [map: SampleMap] ~ {
class.Transfer[pa: pa, i: i, s: s, f: f, dst: map, dstMin: [0, 0], size: [1, 1],
function: [null, null]];
value ¬ ImagerSample.Get[map: map, index: [0, 0]];
};
ImagerSample.DoWithScratchMap[[[0,0], [1, 1]], ImagerSample.maxBitsPerSample, action];
RETURN[value];
};
GetSamplesViaGet: PROC [pa: PixelArray, i: NAT, s, f: INT,
buffer: SampleBuffer, start: NAT, count: NAT] ~ {
class: PixelArrayClass ~ pa.class;
FOR k: NAT IN[0..count) DO
buffer[start+k] ¬ class.Get[pa: pa, i: i, s: s, f: f+k];
ENDLOOP;
};
GetSamplesViaTransfer: PROC [pa: PixelArray, i: NAT, s, f: INT,
buffer: SampleBuffer, start: NAT, count: NAT] ~ {
class: PixelArrayClass ~ pa.class;
action: PROC [map: SampleMap] ~ {
class.Transfer[pa: pa, i: i, s: s, f: f, dst: map, dstMin: [0, 0], size: [s: 1, f: count],
function: [null, null]];
ImagerSample.GetSamples[map: map, buffer: buffer, start: start, count: count];
};
ImagerSample.DoWithScratchMap[[[0, 0], [s: 1, f: count]], ImagerSample.maxBitsPerSample, action];
};
TransferViaGet: PROC [pa: PixelArray, i: NAT, s, f: INT,
dst: SampleMap, dstMin: Vec, size: Vec, function: Function] ~ {
class: PixelArrayClass ~ pa.class;
FOR ks: NAT IN[0..size.s) DO
FOR kf: NAT IN[0..size.f) DO
value: Sample ~ class.Get[pa: pa, i: i, s: s+ks, f: f+kf];
ImagerSample.Put[map: dst, index: [s: dstMin.s+ks, f: dstMin.f+kf], value: value, function: function];
ENDLOOP;
ENDLOOP;
};
TransferViaGetSamples: PROC [pa: PixelArray, i: NAT, s, f: INT,
dst: SampleMap, dstMin: Vec, size: Vec, function: Function] ~ {
class: PixelArrayClass ~ pa.class;
action: PROC [buffer: SampleBuffer] ~ {
FOR k: NAT IN[0..size.s) DO
class.GetSamples[pa: pa, i: i, s: s+k, f: f, buffer: buffer, start: 0, count: size.f];
ImagerSample.PutSamples[map: dst, initIndex: [s: dstMin.s+k, f: dstMin.f], delta: [s: 0, f: 1], buffer: buffer, function: function];
ENDLOOP;
};
ImagerSample.DoWithScratchSamples[size.f, action];
};
NewClass: PUBLIC PROC [type: ATOM,
MaxSampleValue: MaxSampleValueProc,
Get: GetProc ¬ NIL,
GetSamples: GetSamplesProc ¬ NIL,
Transfer: TransferProc ¬ NIL,
Copy: CopyProc ¬ NIL
] RETURNS [PixelArrayClass] ~ {
class: PixelArrayClass ~ NEW[PixelArrayClassRep ¬ [
type: type,
MaxSampleValue: MaxSampleValue,
Get: Get,
GetSamples: GetSamples,
Transfer: Transfer,
Copy: Copy
]];
IF Get=NIL THEN SELECT TRUE FROM
GetSamples#NIL => class.Get ¬ GetViaGetSamples;
Transfer#NIL => class.Get ¬ GetViaTransfer;
ENDCASE;
IF GetSamples=NIL THEN SELECT TRUE FROM
Transfer#NIL => class.GetSamples ¬ GetSamplesViaTransfer;
Get#NIL => class.GetSamples ¬ GetSamplesViaGet;
ENDCASE;
IF Transfer=NIL THEN SELECT TRUE FROM
GetSamples#NIL => class.Transfer ¬ TransferViaGetSamples;
Get#NIL => class.Transfer ¬ TransferViaGet;
ENDCASE;
RETURN[class];
};
New: PUBLIC PROC [class: PixelArrayClass, data: REF, immutable: BOOL, samplesPerPixel: NAT, sSize, fSize: INT, m: Transformation] RETURNS [PixelArray] ~ {
RETURN[NEW[PixelArrayRep ¬ [immutable: immutable, samplesPerPixel: samplesPerPixel,
sSize: Basics.NonNegative[sSize], fSize: Basics.NonNegative[fSize],
m: m, class: class, data: data]]];
};
Layer: TYPE ~ RECORD [base: PixelArray, i: NAT];
extractedClass: PixelArrayClass ~ NewClass[
type: $Extracted,
MaxSampleValue: ExtractedMaxSampleValue,
Get: ExtractedGet,
GetSamples: ExtractedGetSamples,
Transfer: ExtractedTransfer
];
ExtractedData: TYPE ~ REF ExtractedDataRep;
ExtractedDataRep: TYPE ~ RECORD [
base: PixelArray,
select: SEQUENCE samplesPerPixel: NAT OF NAT
];
ExtractedLayer: PROC [data: ExtractedData, i: NAT] RETURNS [Layer] ~ {
RETURN[[base: data.base, i: data.select[i]]];
};
ExtractedMaxSampleValue: MaxSampleValueProc ~ {
data: ExtractedData ~ NARROW[pa.data];
layer: Layer ~ ExtractedLayer[data, i];
class: PixelArrayClass ~ layer.base.class;
RETURN class.MaxSampleValue[pa: layer.base, i: layer.i];
};
ExtractedGet: GetProc ~ {
data: ExtractedData ~ NARROW[pa.data];
layer: Layer ~ ExtractedLayer[data, i];
class: PixelArrayClass ~ layer.base.class;
RETURN class.Get[pa: layer.base, i: layer.i, s: s, f: f];
};
ExtractedGetSamples: GetSamplesProc ~ {
data: ExtractedData ~ NARROW[pa.data];
layer: Layer ~ ExtractedLayer[data, i];
class: PixelArrayClass ~ layer.base.class;
class.GetSamples[pa: layer.base, i: layer.i,
s: s, f: f, buffer: buffer, start: start, count: count];
};
ExtractedTransfer: TransferProc ~ {
data: ExtractedData ~ NARROW[pa.data];
layer: Layer ~ ExtractedLayer[data, i];
class: PixelArrayClass ~ layer.base.class;
class.Transfer[pa: layer.base, i: layer.i,
s: s, f: f, dst: dst, dstMin: dstMin, size: size, function: function];
};
Extract: PUBLIC PROC [old: PixelArray, samplesPerPixel: NAT, select: PROC [NAT] RETURNS [NAT]]
RETURNS [new: PixelArray] ~ {
data: ExtractedData ~ NEW[ExtractedDataRep[samplesPerPixel]];
data.base ¬ old;
FOR i: NAT IN [0..data.samplesPerPixel) DO
data.select[i] ¬ BoundsCheck[select[i], old.samplesPerPixel];
ENDLOOP;
RETURN[New[class: extractedClass, data: data, immutable: old.immutable,
samplesPerPixel: samplesPerPixel, sSize: old.sSize, fSize: old.fSize, m: old.m]];
};
joinedClass: PixelArrayClass ~ NewClass[
type: $Joined,
MaxSampleValue: JoinedMaxSampleValue,
Get: JoinedGet,
GetSamples: JoinedGetSamples,
Transfer: JoinedTransfer
];
JoinedData: TYPE ~ LIST OF PixelArray;
JoinedLayer: PROC [data: JoinedData, i: NAT] RETURNS [Layer] ~ {
FOR each: LIST OF PixelArray ¬ data, each.rest UNTIL each=NIL DO
base: PixelArray ~ each.first;
IF i<base.samplesPerPixel THEN RETURN[[base: base, i: i]]
ELSE i ¬ i-base.samplesPerPixel;
ENDLOOP;
ERROR; -- pa.samplesPerPixel was wrong?
};
JoinedMaxSampleValue: MaxSampleValueProc ~ {
data: JoinedData ~ NARROW[pa.data];
layer: Layer ~ JoinedLayer[data, i];
class: PixelArrayClass ~ layer.base.class;
RETURN class.MaxSampleValue[pa: layer.base, i: layer.i];
};
JoinedGet: GetProc ~ {
data: JoinedData ~ NARROW[pa.data];
layer: Layer ~ JoinedLayer[data, i];
class: PixelArrayClass ~ layer.base.class;
RETURN class.Get[pa: layer.base, i: layer.i, s: s, f: f];
};
JoinedGetSamples: GetSamplesProc ~ {
data: JoinedData ~ NARROW[pa.data];
layer: Layer ~ JoinedLayer[data, i];
class: PixelArrayClass ~ layer.base.class;
class.GetSamples[pa: layer.base, i: layer.i,
s: s, f: f, buffer: buffer, start: start, count: count];
};
JoinedTransfer: TransferProc ~ {
data: JoinedData ~ NARROW[pa.data];
layer: Layer ~ JoinedLayer[data, i];
class: PixelArrayClass ~ layer.base.class;
class.Transfer[pa: layer.base, i: layer.i,
s: s, f: f, dst: dst, dstMin: dstMin, size: size, function: function];
};
Join: PUBLIC PROC [list: LIST OF PixelArray] RETURNS [PixelArray] ~ {
immutable: BOOL ¬ TRUE;
samplesPerPixel: NAT ¬ 0;
sSize, fSize: INT ¬ 0;
m: Transformation ¬ NIL;
FOR each: LIST OF PixelArray ¬ list, each.rest UNTIL each=NIL DO
pa: PixelArray ~ each.first;
immutable ¬ immutable AND pa.immutable;
samplesPerPixel ¬ samplesPerPixel+pa.samplesPerPixel;
IF each=list THEN { sSize ¬ pa.sSize; fSize ¬ pa.fSize; m ¬ pa.m } -- first one
ELSE {
IF NOT(pa.sSize=sSize AND pa.fSize=fSize) THEN ERROR Error[[
code: $incompatibleJoin, explanation: "Sizes do not match"]];
IF NOT pa.m.Equal[m] THEN ERROR Error[[
code: $incompatibleJoin, explanation: "Transformations do not match"]];
};
ENDLOOP;
RETURN[New[class: joinedClass, data: list, immutable: immutable,
samplesPerPixel: samplesPerPixel, sSize: sSize, fSize: fSize, m: m]];
};
Join3: PUBLIC PROC [pa1, pa2, pa3: PixelArray] RETURNS [PixelArray] ~ {
RETURN[Join[LIST[pa1, pa2, pa3]]];
};
pixelMapClass: PixelArrayClass ~ NewClass[
type: $PixelMap,
MaxSampleValue: PixelMapMaxSampleValue,
Get: PixelMapGet,
GetSamples: PixelMapGetSamples,
Transfer: PixelMapTransfer,
Copy: PixelMapCopy
];
PixelMapData: TYPE ~ PixelMap;
PixelMapMaxSampleValue: MaxSampleValueProc ~ {
data: PixelMapData ~ NARROW[pa.data];
map: SampleMap ~ data[i];
RETURN[Basics.BITSHIFT[1, ImagerSample.GetBitsPerSample[map]]-1];
};
PixelMapGet: GetProc ~ {
data: PixelMapData ~ NARROW[pa.data];
map: SampleMap ~ data[i];
index: Vec ~ [s: s, f: f];
RETURN[map.Get[index]];
};
PixelMapGetSamples: GetSamplesProc ~ {
data: PixelMapData ~ NARROW[pa.data];
map: SampleMap ~ data[i];
index: Vec ~ [s: s, f: f];
ImagerSample.GetSamples[map: map, initIndex: index, buffer: buffer, start: start, count: count];
};
PixelMapTransfer: TransferProc ~ {
data: PixelMapData ~ NARROW[pa.data];
map: SampleMap ~ data[i];
index: Vec ~ [s: s, f: f];
ImagerSample.BasicTransfer[dst: dst, src: map, dstMin: dstMin, srcMin: index, size: size, function: function];
};
PixelMapCopy: CopyProc ~ {
data0: PixelMapData ~ NARROW[pa.data];
data1: PixelMapData ~ NEW[PixelMapRep[data0.samplesPerPixel]];
data1.box ¬ data0.box;
FOR i: NAT IN[0..data1.samplesPerPixel) DO data1[i] ¬ ImagerSample.Copy[data0[i]] ENDLOOP;
RETURN[New[class: pixelMapClass, data: data1, immutable: TRUE,
samplesPerPixel: pa.samplesPerPixel, sSize: pa.sSize, fSize: pa.fSize, m: pa.m]];
};
FromPixelMap: PUBLIC PROC [pixelMap: PixelMap, box: SF.Box, scanMode: ScanMode, immutable: BOOL]
RETURNS [PixelArray] ~ {
samplesPerPixel: NAT ~ pixelMap.samplesPerPixel;
IF SF.Inside[box, pixelMap.box] THEN {
delta: Vec ~ SF.Neg[box.min];
size: Vec ~ SF.Size[box];
m: Transformation ~ ImagerTransformation.SFToXY[scanMode: scanMode, sSize: size.s, fSize: size.f];
new: PixelMap ¬ NEW[PixelMapRep[samplesPerPixel]];
new.box ¬ [max: size];
FOR j: NAT IN [0..samplesPerPixel) DO
new[j] ¬ ImagerSample.ReIndex[map: pixelMap[j], delta: delta, box: [max: size]];
ENDLOOP;
RETURN[New[class: pixelMapClass, data: new, immutable: immutable,
samplesPerPixel: samplesPerPixel, sSize: size.s, fSize: size.f, m: m]];
};
ERROR RuntimeError.BoundsFault;
};
END.