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];
ColorTransformsImpl: CEDAR PROGRAM
IMPORTS Basics, Real, RealFns, VM
EXPORTS ColorTransforms
~ BEGIN
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: BOOLEANTRUE, 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[];
END.