ColorTransformsImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Eric Nickell, January 15, 1986 3:15:47 pm PST
DIRECTORY
ColorTransforms,
Basics USING [BITXOR, RawWords],
Real USING [RoundC, RoundI],
RealFns USING [Ln, Power],
VM USING [AddressForPageNumber, PagesForBytes, SimpleAllocate];
OPEN ColorTransforms;
scale: CARDINAL ~ 64;
BuildCCT:
PUBLIC
PROC [t: Transform, trc:
ARRAY [0..3)
OF
TRC]
RETURNS [cct:
CCT] ~ {
bufferSize: NAT ~ trc[0].length;
IF trc[1].length#bufferSize OR trc[2].length#bufferSize THEN ERROR;
FOR from:
NAT
IN [0..3)
DO
FOR to:
NAT
IN [0..3)
DO
constant: REAL ~ IF from=0 THEN t[3][to] ELSE 0.0;
buffer: Buffer ~ ObtainBuffer[bufferSize];
cct[from][to] ← buffer;
FOR sample:
NAT
IN [0..buffer.length)
DO
buffer[sample] ← Real.RoundI[(t[from][to]*trc[from][sample]+constant) * scale]
ENDLOOP;
ENDLOOP;
ENDLOOP;
};
ApplyCCTToSample:
PUBLIC
PROC [cct:
CCT, x0, x1, x2:
CARDINAL]
RETURNS [y0, y1, y2:
INTEGER] ~
TRUSTED {
The following proc is copied from Apply.
CalculateValues:
UNSAFE
PROC [x0, x1, x2:
CARDINAL]
RETURNS [y0, y1, y2:
INTEGER] ~
INLINE {
RETURN [
y0: div64[cct[0][0][x0] + cct[1][0][x1] + cct[2][0][x2]],
y1: div64[cct[0][1][x0] + cct[1][1][x1] + cct[2][1][x2]],
y2: div64[cct[0][2][x0] + cct[1][2][x1] + cct[2][2][x2]]
];
};
[y0, y1, y2] ← CalculateValues[x0, x1, x2];
};
ApplyCCT:
PUBLIC
UNSAFE
PROC [cct:
CCT, x0, x1, x2, y0, y1, y2:
LONG
POINTER
TO Basics.RawWords, count:
LONG
CARDINAL] ~
UNCHECKED {
CalculateValues:
UNSAFE
PROC [x0, x1, x2:
CARDINAL]
RETURNS [y0, y1, y2:
INTEGER] ~
INLINE {
RETURN [
y0: div64[cct[0][0][x0] + cct[1][0][x1] + cct[2][0][x2]],
y1: div64[cct[0][1][x0] + cct[1][1][x1] + cct[2][1][x2]],
y2: div64[cct[0][2][x0] + cct[1][2][x1] + cct[2][2][x2]]
];
};
ApplyToSample:
UNSAFE
PROC [index:
NAT] ~
INLINE {
[y0: y0[index], y1: y1[index], y2: y2[index]] ← CalculateValues[x0: x0[index], x1: x1[index], x2:x2[index]];
};
THROUGH [0 .. count/8)
DO
ApplyToSample[0];
ApplyToSample[1];
ApplyToSample[2];
ApplyToSample[3];
ApplyToSample[4];
ApplyToSample[5];
ApplyToSample[6];
ApplyToSample[7];
x0 ← x0+8;
x1 ← x1+8;
x2 ← x2+8;
y0 ← y0+8;
y1 ← y1+8;
y2 ← y2+8;
ENDLOOP;
FOR k:
NAT
IN [0 ..
NAT[count
MOD 8])
DO
ApplyToSample[k];
ENDLOOP;
};
ApplyCCTToBytes:
PUBLIC
UNSAFE
PROC [cct:
CCT, x0, x1, x2, y0, y1, y2:
LONG
POINTER
TO RawBytes, count:
LONG
CARDINAL] ~
UNCHECKED {
CalculateValues:
UNSAFE
PROC [x0, x1, x2:
CARDINAL]
RETURNS [y0, y1, y2:
INTEGER] ~
INLINE {
RETURN [
y0: div64[cct[0][0][x0] + cct[1][0][x1] + cct[2][0][x2]],
y1: div64[cct[0][1][x0] + cct[1][1][x1] + cct[2][1][x2]],
y2: div64[cct[0][2][x0] + cct[1][2][x1] + cct[2][2][x2]]
];
};
ApplyToSample:
UNSAFE
PROC [index:
NAT] ~
INLINE {
[y0: y0[index], y1: y1[index], y2: y2[index]] ← CalculateValues[x0: x0[index], x1: x1[index], x2:x2[index]];
};
THROUGH [0 .. count/8)
DO
ApplyToSample[0];
ApplyToSample[1];
ApplyToSample[2];
ApplyToSample[3];
ApplyToSample[4];
ApplyToSample[5];
ApplyToSample[6];
ApplyToSample[7];
x0 ← x0+8/2;
x1 ← x1+8/2;
x2 ← x2+8/2;
y0 ← y0+8/2;
y1 ← y1+8/2;
y2 ← y2+8/2;
ENDLOOP;
FOR k:
NAT
IN [0 ..
NAT[count
MOD 8])
DO
ApplyToSample[k];
ENDLOOP;
};
Invert:
PROC [value:
CARDINAL, inversion:
WORD]
RETURNS [
CARDINAL] ~
INLINE {
RETURN [Basics.BITXOR[value, inversion]];
};
BuildUCR:
PUBLIC
PROC [threshold, gamma, fractionRemoved:
REAL, invertResult:
BOOLEAN ←
TRUE, bufferSize:
NAT ← 256]
RETURNS [ucr:
UCR] ~ {
Sqr:
PROC [r:
REAL]
RETURNS [
REAL] ~
INLINE {
RETURN [r*r];
};
removeCoef: REAL ~ fractionRemoved/Sqr[bufferSize-1-threshold];
blackCoef: REAL ~ gamma/Sqr[bufferSize-1-threshold];
ucr ← [
black: ObtainBuffer[bufferSize],
remove: ObtainBuffer[bufferSize],
invert: IF invertResult THEN 255 ELSE 0
];
FOR sample:
CARDINAL
IN [0 .. bufferSize)
DO
IF sample<threshold
THEN {
ucr.remove[sample] ← ucr.black[sample] ← 0;
}
ELSE {
ucr.remove[sample] ← Real.RoundC[removeCoef*Sqr[sample-threshold]];
ucr.black[sample] ← Invert[Real.RoundC[blackCoef*Sqr[sample-threshold]], ucr.invert];
};
ENDLOOP;
};
ApplyUCRToSample:
PUBLIC
PROC [ucr:
UCR, x0, x1, x2:
CARDINAL]
RETURNS [y0, y1, y2, y3:
CARDINAL] ~
TRUSTED {
CalculateValues:
UNSAFE
PROC [x0, x1, x2:
CARDINAL, inv:
WORD]
RETURNS [
CARDINAL,
CARDINAL,
CARDINAL,
CARDINAL] ~
INLINE {
BlackAndRemove:
PROC [x:
CARDINAL]
RETURNS [black, remove:
CARDINAL] ~
CHECKED
INLINE {
RETURN [black: ucr.black[x], remove: ucr.remove[x]];
};
black, remove: CARDINAL;
[black, remove] ← BlackAndRemove[MIN[x0, x1, x2]];
RETURN [Invert[x0-remove, inv], Invert[x1-remove, inv], Invert[x2-remove, inv], black];
};
[y0, y1, y2, y3] ← CalculateValues[x0, x1, x2, ucr.invert];
};
ApplyUCR:
PUBLIC
UNSAFE
PROC [ucr:
UCR, x0, x1, x2, y0, y1, y2, y3:
LONG
POINTER
TO Basics.RawWords, count:
LONG
CARDINAL] ~
UNCHECKED {
CalculateValues:
UNSAFE
PROC [x0, x1, x2:
CARDINAL, inv:
WORD]
RETURNS [
CARDINAL,
CARDINAL,
CARDINAL,
CARDINAL] ~
INLINE {
BlackAndRemove:
PROC [x:
CARDINAL]
RETURNS [black, remove:
CARDINAL] ~
CHECKED
INLINE {
RETURN [black: ucr.black[x], remove: ucr.remove[x]];
};
black, remove: CARDINAL;
[black, remove] ← BlackAndRemove[MIN[x0, x1, x2]];
RETURN [Invert[x0-remove, inv], Invert[x1-remove, inv], Invert[x2-remove, inv], black];
};
ApplyToSample:
UNSAFE
PROC [index:
NAT] ~ {
[y0[index], y1[index], y2[index], y3[index]] ← CalculateValues[x0: x0[index], x1: x1[index], x2: x2[index], inv: ucr.invert];
};
THROUGH [0 .. count/8)
DO
ApplyToSample[0];
ApplyToSample[1];
ApplyToSample[2];
ApplyToSample[3];
ApplyToSample[4];
ApplyToSample[5];
ApplyToSample[6];
ApplyToSample[7];
x0 ← x0+8;
x1 ← x1+8;
x2 ← x2+8;
y0 ← y0+8;
y1 ← y1+8;
y2 ← y2+8;
y3 ← y3+8;
ENDLOOP;
FOR k:
NAT
IN [0 ..
NAT[count
MOD 8])
DO
ApplyToSample[k];
ENDLOOP;
};
ApplyUCRToBytes:
PUBLIC
UNSAFE
PROC [ucr:
UCR, x0, x1, x2, y0, y1, y2, y3:
LONG
POINTER
TO RawBytes, count:
LONG
CARDINAL] ~
UNCHECKED {
CalculateValues:
UNSAFE
PROC [x0, x1, x2:
CARDINAL, inv:
WORD]
RETURNS [
CARDINAL,
CARDINAL,
CARDINAL,
CARDINAL] ~
INLINE {
BlackAndRemove:
PROC [x:
CARDINAL]
RETURNS [black, remove:
CARDINAL] ~
CHECKED
INLINE {
RETURN [black: ucr.black[x], remove: ucr.remove[x]];
};
black, remove: CARDINAL;
[black, remove] ← BlackAndRemove[MIN[x0, x1, x2]];
RETURN [Invert[x0-remove, inv], Invert[x1-remove, inv], Invert[x2-remove, inv], black];
};
ApplyToSample:
UNSAFE
PROC [index:
NAT] ~ {
[y0[index], y1[index], y2[index], y3[index]] ← CalculateValues[x0: x0[index], x1: x1[index], x2: x2[index], inv: ucr.invert];
};
THROUGH [0 .. count/8)
DO
ApplyToSample[0];
ApplyToSample[1];
ApplyToSample[2];
ApplyToSample[3];
ApplyToSample[4];
ApplyToSample[5];
ApplyToSample[6];
ApplyToSample[7];
x0 ← x0+8/2;
x1 ← x1+8/2;
x2 ← x2+8/2;
y0 ← y0+8/2;
y1 ← y1+8/2;
y2 ← y2+8/2;
y3 ← y3+8/2;
ENDLOOP;
FOR k:
NAT
IN [0 ..
NAT[count
MOD 8])
DO
ApplyToSample[k];
ENDLOOP;
};
ObtainBuffer:
PUBLIC
PROC [bufferSize:
NAT]
RETURNS [Buffer] ~ {
RETURN [NEW[BufferRep[bufferSize]]]
};
Build8To14BitLogTable:
PROC
RETURNS [log:
ARRAY [0..255)
OF
NAT] ~ {
logScaleFactor14: REAL ~ RealFns.Power[base: 2, exponent: 14]/RealFns.Ln[256];
factor: REAL ~ logScaleFactor14;
FOR i:
CARDINAL
IN [0..255)
DO
log[i] ← Real.RoundI[factor*RealFns.Ln[i+1]];
ENDLOOP;
};
div64: LONG POINTER TO RawBytes;
Init:
PROC ~
TRUSTED {
div64 ← LOOPHOLE[VM.AddressForPageNumber[VM.SimpleAllocate[count: VM.PagesForBytes[CARDINAL.LAST]].page]];
FOR i:
INTEGER
IN [
INTEGER.
FIRST .. 0)
DO
div64[LOOPHOLE[i, CARDINAL]] ← 0;
ENDLOOP;
FOR i:
CARDINAL
IN [0..256*64)
DO
div64[i] ← i/64;
ENDLOOP;
FOR i:
CARDINAL
IN [256*64 ..
CARDINAL[
INTEGER.
LAST]]
DO
div64[i] ← 255;
ENDLOOP;
};
Init[];