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 { 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