ApplyMatrix:
PROC [
inStem, outStem: Rope.ROPE, -- filename stems
matrix: MatrixN, -- correction matrix
inTRCRed: TRCTable ← NIL, -- red input TRC
inTRCGrn: TRCTable ← NIL, -- green input TRC
inTRCBlu: TRCTable ← NIL, -- blu input TRC
outTRCCyan: TRCTable ← NIL, -- cyan device linearization trc
outTRCMag: TRCTable ← NIL, -- magenta device linearization trc
outTRCYel: TRCTable ← NIL, -- yellow device linearization trc
outTRCBlack: TRCTable ← NIL, -- black device linearization trc
ucrTRC: TRCTable ← NIL, -- Under Color Removal trc
bpTRC: TRCTable ← NIL, -- black printer trc
mode: CCMode ← Color4, -- Ouput: 3 color; 4 color or 4 color+UCR
normalize:BOOLEAN ← TRUE -- CC matrix rows need fixing to sum to 1
] ~ {
Buffer: TYPE = REF BufferRec;
BufferRec: TYPE = PACKED ARRAY [0..2048) OF [0..255];
redBufIn, grnBufIn, bluBufIn, cyanBufOut, magBufOut, yelBufOut, blackBufOut: Buffer;
redInF, grnInF, bluInF, cyanOutF, magOutF, yelOutF, blackOutF: AIS.FRef;
redInW, grnInW, bluInW, cyanOutW, magOutW, yelOutW, blackOutW: AIS.WRef;
raster: AIS.Raster ← NEW[AIS.RasterPart];
singular:BOOLEAN ← FALSE;
m00, m01, m02, m10, m11, m12, m20, m21, m22: TranslateTable;
CreateTable:
PROC [matrixEl:
REAL, trc:TRCTable]
RETURNS [table: TranslateTable] ~ {
-- creates table such that AIS pixel value i => matrixEl*(255-i)
-- This means AIS 0 = Dmax => 255*matrixEl
table ← NEW[TranslateTableRec];
IF trc=
NIL
THEN
FOR i:
NAT
IN [0..255]
DO
table[i] ← (255-i)*matrixEl;
ENDLOOP
ELSE
FOR i:
NAT
IN [0..255]
DO
table[i] ← (255-trc[i])*matrixEl;
ENDLOOP
};
Normalise:
PROC[m:MatrixN] ~ {
FOR i:
NAT
IN [0..2]
DO
sum: REAL ← 0;
FOR j:
NAT
IN [0..2]
DO
sum ← sum + m[i][j];
ENDLOOP;
FOR j:
NAT
IN [0..2]
DO
m[i][j] ← m[i][j] / sum;
ENDLOOP;
ENDLOOP;
};
CreateSeparation:
PROC [stem, key, default: Rope.
ROPE]
RETURNS [fd:
AIS.FRef, wd:
AIS.WRef] ~ {
fileList:
LIST
OF Rope.
ROPE ← UPOps.Expand[
"%g%k|%g|%g|.%k|AISExtensions|AIS|",
IO.rope[stem],
IO.rope[key], IO.rope[default]];
fd ← AIS.CreateFile[name: fileList.first, raster: raster];
wd ← AIS.OpenWindow[fd];
};
OpenSeparation:
PROC [stem, key, default: Rope.
ROPE]
RETURNS [fd:
AIS.FRef, wd:
AIS.WRef] ~ {
fileList:
LIST
OF Rope.
ROPE ← UPOps.Expand[
"%g%k|%g|%g|.%k|AISExtensions|AIS|",
IO.rope[stem],
IO.rope[key], IO.rope[default]];
DO {
FileExists:
PROCEDURE [fileName:Rope.ROPE]
RETURNS [answer:
BOOLEAN←TRUE] = {
s:
IO.STREAM ← FS.StreamOpen[fileName:fileName
! FS.Error =>
TRUSTED {
answer←FALSE;
GOTO notThere;
}];
IO.Close[s];
};
IF fileList = NIL THEN ERROR;
IF FileExists[fileList.first] THEN EXIT;
fileList ← fileList.rest
};
ENDLOOP;
fd ← AIS.OpenFile[name:fileList.first];
wd ← AIS.OpenWindow[fd];
};
CloseAll:
PROC [] ~ {
CloseSeparation:
PROC [fd:
AIS.FRef, wd:
AIS.WRef] = {
AIS.CloseWindow[wd];
AIS.CloseFile[fd];
};
CloseSeparation[redInF, redInW];
CloseSeparation[grnInF, grnInW];
CloseSeparation[bluInF, bluInW];
CloseSeparation[cyanOutF, cyanOutW];
CloseSeparation[magOutF, magOutW];
CloseSeparation[yelOutF, yelOutW];
IF mode=Color4
OR mode=
UCR THEN
CloseSeparation[blackOutF, blackOutW];
};
Default:
PROC [trc:TRCTable]
RETURNS [initTrc:TRCTable] ~ {
IF trc=
NIL
THEN {
initTrc ← NEW[TRCTableRec ← ALL[0]];
FOR i:
NAT
IN [0..255]
DO
initTrc[i] ← i;
ENDLOOP;
}
};
outTRCCyan ← Default[outTRCCyan];
outTRCMag ← Default[outTRCMag];
outTRCYel ← Default[outTRCYel];
outTRCBlack ← Default[outTRCBlack];
bpTRC ← Default[bpTRC];
ucrTRC ← Default[ucrTRC];
IF normalize THEN Normalise[matrix];
m00 ← CreateTable[matrix[0][0], inTRCRed];
m01 ← CreateTable[matrix[0][1], inTRCGrn];
m02 ← CreateTable[matrix[0][2], inTRCBlu];
m10 ← CreateTable[matrix[1][0], inTRCRed];
m11 ← CreateTable[matrix[1][1], inTRCGrn];
m12 ← CreateTable[matrix[1][2], inTRCBlu];
m20 ← CreateTable[matrix[2][0], inTRCRed];
m21 ← CreateTable[matrix[2][1], inTRCGrn];
m22 ← CreateTable[matrix[2][2], inTRCBlu];
-- **** Open up the input files ***
[redInF, redInW] ← OpenSeparation[inStem, "AISseparationKeys.red", "-red"];
[grnInF, grnInW] ← OpenSeparation[inStem, "AISseparationKeys.green", "-green"];
[bluInF, bluInW] ← OpenSeparation[inStem, "AISseparationKeys.blue", "-blue"];
-- **** Create the output files ****
raster ← AIS.ReadRaster[redInF];
[cyanOutF, cyanOutW] ← CreateSeparation[outStem, "AISseparationKeys.cyan", "-cyan"];
[magOutF, magOutW] ← CreateSeparation[outStem, "AISseparationKeys.magenta", "-magenta"];
[yelOutF, yelOutW] ← CreateSeparation[outStem, "AISseparationKeys.yellow", "-yellow"];
-- **** Process files ***
redBufIn ← NEW[BufferRec];
grnBufIn ← NEW[BufferRec];
bluBufIn ← NEW[BufferRec];
cyanBufOut ← NEW[BufferRec];
magBufOut ← NEW[BufferRec];
yelBufOut ← NEW[BufferRec];
IF mode=Color4
OR mode=
UCR
THEN {
-- Color3 doesn't make a black sep
[blackOutF, blackOutW] ← CreateSeparation[outStem, "AISseparationKeys.black", "-black"];
blackBufOut ← NEW[BufferRec];
};
FOR i:
CARDINAL
IN [0..raster.scanCount)
DO TRUSTED {
-- read in a line of pixels
AIS.UnsafeReadLine[w:redInW, buffer:[length:raster.scanLength, addr:LOOPHOLE[redBufIn]], line:i];
AIS.UnsafeReadLine[w:grnInW, buffer:[length:raster.scanLength, addr:LOOPHOLE[grnBufIn]], line:i];
AIS.UnsafeReadLine[w:bluInW, buffer:[length:raster.scanLength, addr:LOOPHOLE[bluBufIn]], line:i];
-- Process each pixel on the line
FOR j:
NAT
IN [0..raster.scanLength)
DO
-- get input pixel and apply input TRCs
r: NAT ← redBufIn[j];
g: NAT ← grnBufIn[j];
b: NAT ← bluBufIn[j];
c, m, y: NAT;
-- find out how much black is required: Color3 => NONE
k: NAT ← MAX[r, g, b]; -- this is the black component
SELECT mode
FROM
UCR => {
-- UCR => subtract ucrTRC determined amount of black from r,g,b
-- need to adjust input values before correction for UCR
k ← ucrTRC[k];
r ← MIN[r + (255 - k), 255];
g ← MIN[g + (255 - k), 255];
b ← MIN[b + (255 - k), 255];
};
Color4 => {
-- Black printer => just add bpTRC determined amount of black
k ← bpTRC[k];
}
ENDCASE => NULL;
-- apply 3*3 color corretcion matrix to input seps
c ← Real.RoundC[MAX[MIN[m00[r] + m01[g] + m02[b], 255], 0]];
m ← Real.RoundC[MAX[MIN[m10[r] + m11[g] + m12[b], 255], 0]];
y ← Real.RoundC[MAX[MIN[m20[r] + m21[g] + m22[b], 255], 0]];
-- apply output (normally only device linearisation) TRCs
cyanBufOut[j] ← outTRCCyan[255 - c];
magBufOut[j] ← outTRCMag[255 - m];
yelBufOut[j] ← outTRCYel[255 - y];
IF mode#Color3
THEN
blackBufOut[j] ← outTRCBlack[k];
ENDLOOP;
-- write out this line of results
IF mode#Color3
THEN
AIS.UnsafeWriteLine[w:blackOutW, buffer:[length:raster.scanLength, addr:LOOPHOLE[blackBufOut]], line:i];
AIS.UnsafeWriteLine[w:cyanOutW, buffer:[length:raster.scanLength, addr:LOOPHOLE[cyanBufOut]], line:i];
AIS.UnsafeWriteLine[w:magOutW, buffer:[length:raster.scanLength, addr:LOOPHOLE[magBufOut]], line:i];
AIS.UnsafeWriteLine[w:yelOutW, buffer:[length:raster.scanLength, addr:LOOPHOLE[yelBufOut]], line:i];
} -- end of trusted block
ENDLOOP;
-- shut up shop and go home
CloseAll[];
};
END.