ImagerPixelArrayImpl.mesa
Copyright © 1984, 1985, 1986 by Xerox Corporation. All rights reserved.
Michael Plass, June 3, 1985 12:40:17 pm PDT
Doug Wyatt, March 7, 1986 4:20:36 pm PST
DIRECTORY
Basics USING [BITSHIFT, BoundsCheck, NonNegative],
ImagerPixelArray USING [ErrorDesc, maxCount, maxVec, PixelArray, PixelArrayRep, zeroVec],
ImagerPixelArrayPrivate USING [CopyProc, GetProc, GetSamplesProc, MaxSampleValueProc, PixelArrayClass, PixelArrayClassRep, TransferProc],
ImagerSample USING [CopyMap, DoWithScratchMap, DoWithScratchSamples, Function, Get, GetSamples, maxBitsPerSample, nullFunction, PixelBuffer, PixelMap, PixelMapRep, Put, PutSamples, Sample, SampleBuffer, SampleMap, Transfer],
ImagerTransformation USING [Equal, ScanMode, SFToXY, Transformation],
SF USING [Min, Sub, Vec];
ImagerPixelArrayImpl: CEDAR PROGRAM
IMPORTS Basics, ImagerSample, ImagerTransformation, 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 ~ ImagerSample.PixelBuffer;
SampleMap: TYPE ~ ImagerSample.SampleMap;
PixelMap: TYPE ~ ImagerSample.PixelMap;
PixelMapRep: TYPE ~ ImagerSample.PixelMapRep;
Function: TYPE ~ ImagerSample.Function;
nullFunction: Function ~ ImagerSample.nullFunction;
PixelArrayClass: TYPE ~ ImagerPixelArrayPrivate.PixelArrayClass;
PixelArrayClassRep: PUBLIC TYPE ~ ImagerPixelArrayPrivate.PixelArrayClassRep;
Error: PUBLIC ERROR [error: ErrorDesc] ~ CODE;
GetClass: PUBLIC PROC [self: PixelArray] RETURNS [ATOM] ~ {
class: PixelArrayClass ~ self.class;
RETURN[class.type];
};
MaxSampleValue: PUBLIC PROC [self: PixelArray, i: NAT] RETURNS [Sample] ~ {
class: PixelArrayClass ~ self.class;
RETURN class.MaxSampleValue[self: self, i: Basics.BoundsCheck[i, self.samplesPerPixel]];
};
Get: PUBLIC PROC [self: PixelArray, i: NAT, s, f: INT] RETURNS [Sample] ~ {
class: PixelArrayClass ~ self.class;
iCheck: NAT ~ Basics.BoundsCheck[i, self.samplesPerPixel];
sRem: INT ~ Basics.NonNegative[self.sSize-Basics.NonNegative[s]];
fRem: INT ~ Basics.NonNegative[self.fSize-Basics.NonNegative[f]];
[] ← Basics.NonNegative[sRem-1];
[] ← Basics.NonNegative[fRem-1];
RETURN class.Get[self: self, i: i, s: s, f: f];
};
GetSamples: PUBLIC PROC [self: PixelArray, i: NAT ← 0, s, f: INT ← 0,
samples: SampleBuffer, start: NAT ← 0, count: NAT ← maxCount] ~ {
class: PixelArrayClass ~ self.class;
iCheck: NAT ~ Basics.BoundsCheck[i, self.samplesPerPixel];
sRem: INT ~ Basics.NonNegative[self.sSize-Basics.NonNegative[s]];
fRem: INT ~ Basics.NonNegative[self.fSize-Basics.NonNegative[f]];
actualCount: NAT ~ MIN[samples.length-start, count];
[] ← Basics.NonNegative[sRem-1];
[] ← Basics.NonNegative[fRem-actualCount];
class.GetSamples[self: self, i: i, s: s, f: f, samples: samples, start: start, count: actualCount];
};
GetPixels: PUBLIC PROC [self: PixelArray, s, f: INT ← 0,
pixels: PixelBuffer, start: NAT ← 0, count: NAT ← maxCount] ~ {
FOR i: NAT IN[0..self.samplesPerPixel) DO
GetSamples[self, i, s, f, pixels[i], start, count]
ENDLOOP
};
Transfer: PUBLIC PROC [self: PixelArray, i: NAT ← 0, s, f: INT ← 0,
dst: SampleMap, dstMin: Vec ← zeroVec, size: Vec ← maxVec,
function: Function ← nullFunction] ~ {
class: PixelArrayClass ~ self.class;
iCheck: NAT ~ Basics.BoundsCheck[i, self.samplesPerPixel];
sRem: INT ~ Basics.NonNegative[self.sSize-Basics.NonNegative[s]];
fRem: INT ~ Basics.NonNegative[self.fSize-Basics.NonNegative[f]];
actualSize: Vec ← dst.size.Sub[dstMin].Min[size];
IF sRem<actualSize.s THEN actualSize.s ← sRem;
IF fRem<actualSize.f THEN actualSize.f ← fRem;
class.Transfer[self: self, i: i, s: s, f: f,
dst: dst, dstMin: dstMin, size: actualSize, function: function];
};
Copy: PUBLIC PROC [self: PixelArray] RETURNS [PixelArray] ~ {
IF self.immutable THEN RETURN[self]
ELSE {
class: PixelArrayClass ~ self.class;
IF class.Copy#NIL THEN RETURN[class.Copy[self]]
ELSE ERROR Error[[code: $unimplemented, explanation: "Copy is unimplemented"]];
};
};
GetViaGetSamples: PROC [self: PixelArray, i: NAT, s, f: INT] RETURNS [Sample] ~ {
class: PixelArrayClass ~ self.class;
value: Sample ← 0;
action: PROC [samples: SampleBuffer] ~ {
class.GetSamples[self: self, i: i, s: s, f: f, samples: samples, start: 0, count: 1];
value ← samples[0];
};
ImagerSample.DoWithScratchSamples[1, action];
RETURN[value];
};
GetViaTransfer: PROC [self: PixelArray, i: NAT, s, f: INT] RETURNS [Sample] ~ {
class: PixelArrayClass ~ self.class;
value: Sample ← 0;
action: PROC [map: SampleMap] ~ {
class.Transfer[self: self, i: i, s: s, f: f, dst: map, dstMin: [0, 0], size: [1, 1],
function: [null, null]];
value ← ImagerSample.Get[self: map, index: [0, 0]];
};
ImagerSample.DoWithScratchMap[[1, 1], ImagerSample.maxBitsPerSample, action];
RETURN[value];
};
GetSamplesViaGet: PROC [self: PixelArray, i: NAT, s, f: INT,
samples: SampleBuffer, start: NAT, count: NAT] ~ {
class: PixelArrayClass ~ self.class;
FOR k: NAT IN[0..count) DO
samples[start+k] ← class.Get[self: self, i: i, s: s, f: f+k];
ENDLOOP;
};
GetSamplesViaTransfer: PROC [self: PixelArray, i: NAT, s, f: INT,
samples: SampleBuffer, start: NAT, count: NAT] ~ {
class: PixelArrayClass ~ self.class;
action: PROC [map: SampleMap] ~ {
class.Transfer[self: self, i: i, s: s, f: f, dst: map, dstMin: [0, 0], size: map.size,
function: [null, null]];
map.GetSamples[samples: samples, start: start, count: count];
};
ImagerSample.DoWithScratchMap[[s: 1, f: count], ImagerSample.maxBitsPerSample, action];
};
TransferViaGet: PROC [self: PixelArray, i: NAT, s, f: INT,
dst: SampleMap, dstMin: Vec, size: Vec, function: Function] ~ {
class: PixelArrayClass ~ self.class;
FOR ks: NAT IN[0..size.s) DO
FOR kf: NAT IN[0..size.f) DO
value: Sample ~ class.Get[self: self, i: i, s: s+ks, f: f+kf];
dst.Put[index: [s: dstMin.s+ks, f: dstMin.f+kf], value: value, function: function];
ENDLOOP;
ENDLOOP;
};
TransferViaGetSamples: PROC [self: PixelArray, i: NAT, s, f: INT,
dst: SampleMap, dstMin: Vec, size: Vec, function: Function] ~ {
class: PixelArrayClass ~ self.class;
action: PROC [samples: SampleBuffer] ~ {
FOR k: NAT IN[0..size.s) DO
class.GetSamples[self: self, i: i, s: s+k, f: f, samples: samples, start: 0, count: size.f];
dst.PutSamples[min: [s: dstMin.s+k, f: dstMin.f], delta: [s: 0, f: 1],
samples: samples, 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[self.data];
layer: Layer ~ ExtractedLayer[data, i];
class: PixelArrayClass ~ layer.base.class;
RETURN class.MaxSampleValue[self: layer.base, i: layer.i];
};
ExtractedGet: GetProc ~ {
data: ExtractedData ~ NARROW[self.data];
layer: Layer ~ ExtractedLayer[data, i];
class: PixelArrayClass ~ layer.base.class;
RETURN class.Get[self: layer.base, i: layer.i, s: s, f: f];
};
ExtractedGetSamples: GetSamplesProc ~ {
data: ExtractedData ~ NARROW[self.data];
layer: Layer ~ ExtractedLayer[data, i];
class: PixelArrayClass ~ layer.base.class;
class.GetSamples[self: layer.base, i: layer.i,
s: s, f: f, samples: samples, start: start, count: count];
};
ExtractedTransfer: TransferProc ~ {
data: ExtractedData ~ NARROW[self.data];
layer: Layer ~ ExtractedLayer[data, i];
class: PixelArrayClass ~ layer.base.class;
class.Transfer[self: 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] ← [base: old, select: ]];
FOR i: NAT IN [0..data.samplesPerPixel) DO
data.select[i] ← Basics.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[self.data];
layer: Layer ~ JoinedLayer[data, i];
class: PixelArrayClass ~ layer.base.class;
RETURN class.MaxSampleValue[self: layer.base, i: layer.i];
};
JoinedGet: GetProc ~ {
data: JoinedData ~ NARROW[self.data];
layer: Layer ~ JoinedLayer[data, i];
class: PixelArrayClass ~ layer.base.class;
RETURN class.Get[self: layer.base, i: layer.i, s: s, f: f];
};
JoinedGetSamples: GetSamplesProc ~ {
data: JoinedData ~ NARROW[self.data];
layer: Layer ~ JoinedLayer[data, i];
class: PixelArrayClass ~ layer.base.class;
class.GetSamples[self: layer.base, i: layer.i,
s: s, f: f, samples: samples, start: start, count: count];
};
JoinedTransfer: TransferProc ~ {
data: JoinedData ~ NARROW[self.data];
layer: Layer ~ JoinedLayer[data, i];
class: PixelArrayClass ~ layer.base.class;
class.Transfer[self: 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: BOOLTRUE;
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[self.data];
map: SampleMap ~ data[i];
RETURN[Basics.BITSHIFT[1, map.bitsPerSample]-1];
};
PixelMapGet: GetProc ~ {
data: PixelMapData ~ NARROW[self.data];
map: SampleMap ~ data[i];
index: Vec ~ [s: s, f: f];
RETURN[map.Get[index]];
};
PixelMapGetSamples: GetSamplesProc ~ {
data: PixelMapData ~ NARROW[self.data];
map: SampleMap ~ data[i];
index: Vec ~ [s: s, f: f];
map.GetSamples[min: index, samples: samples, start: start, count: count];
};
PixelMapTransfer: TransferProc ~ {
data: PixelMapData ~ NARROW[self.data];
map: SampleMap ~ data[i];
index: Vec ~ [s: s, f: f];
dst.Transfer[src: map, dstMin: dstMin, srcMin: index, size: size, function: function];
};
PixelMapCopy: CopyProc ~ {
data0: PixelMapData ~ NARROW[self.data];
data1: PixelMapData ~ NEW[PixelMapRep[data0.samplesPerPixel]];
FOR i: NAT IN[0..data1.samplesPerPixel) DO data1[i] ← data0[i].CopyMap[] ENDLOOP;
RETURN[New[class: pixelMapClass, data: data1, immutable: TRUE,
samplesPerPixel: self.samplesPerPixel, sSize: self.sSize, fSize: self.fSize, m: self.m]];
};
FromPixelMap: PUBLIC PROC [map: PixelMap, scanMode: ScanMode, immutable: BOOL]
RETURNS [PixelArray] ~ {
samplesPerPixel: NAT ~ map.samplesPerPixel;
sSize: NAT ~ map.size.s;
fSize: NAT ~ map.size.f;
RETURN[New[class: pixelMapClass, data: map, immutable: immutable,
samplesPerPixel: samplesPerPixel, sSize: sSize, fSize: fSize,
m: ImagerTransformation.SFToXY[scanMode: scanMode, sSize: sSize, fSize: fSize]]];
};
END.