~
BEGIN
LookupTable: TYPE = REF LookupTableRep;
LookupTableRep:
TYPE = ImagerDeviceColor.LookupTableRep;
ColorLookupTableType: TYPE = ImagerDeviceColor.ColorLookupTableType;
DeviceColorControl: TYPE = REF DeviceColorControlRep;
DeviceColorControlRep: TYPE = ImagerDeviceColor.DeviceColorControlRep;
GetDeviceColorControl:
PUBLIC
PROC [device: ImagerDevice.Device]
RETURNS [DeviceColorControl] = {
key: ATOM = $DeviceColorControl;
WITH Prop.Get[device.parm.propList, key]
SELECT
FROM
control: DeviceColorControl => RETURN [control];
ENDCASE => {
control: DeviceColorControl = NEW[DeviceColorControlRep ¬ [stamp: 0, table: ALL[NIL], setLookupTable: DefaultSetLookupTable]];
NOTE: control.private is not used at present.
device.parm.propList ¬ Prop.Put[device.parm.propList, key, control];
RETURN [control];
};
};
DefaultSetLookupTable:
PUBLIC
PROC [control: DeviceColorControl, which: ColorLookupTableType, table: LookupTable] = {
ident: BOOL ¬ TRUE;
IF table # NIL AND table.size = 0 THEN table ¬ NIL; -- don't store empty tables.
control.table[which] ¬ table;
FOR i: ColorLookupTableType
IN [redTransfer..grayTransfer]
DO
IF control.table[i] # NIL THEN {ident ¬ FALSE; EXIT};
ENDLOOP;
control.allIdentity ¬ ident;
control.stamp ¬ control.stamp + 1;
};
LookupReal:
PUBLIC
PROC [table: LookupTable, real:
REAL]
RETURNS [
REAL] = {
IF table =
NIL
THEN
RETURN [real]
ELSE {
limit: INT = table.size-1;
IF real <= 0.0 THEN RETURN [table[0]] ELSE
IF real >= 1.0 THEN RETURN [table[limit]] ELSE
IF
NOT RealInline.IsValid[real]
THEN
RETURN [real]
ELSE {
s: REAL = limit*real;
k: INT = RealInline.MCFix[s]; -- as good as Floor, since s > 0.0
d: REAL = s-REAL[k];
v: REAL = table[k];
RETURN [IF d <= 0.0 OR k >= limit THEN v ELSE v + d * (table[k+1]-v)]
};
};
};
LookupFlipped:
PUBLIC
PROC [table: LookupTable, real:
REAL]
RETURNS [
REAL] = {
IF table =
NIL
THEN
RETURN [real]
ELSE {
limit: INT = table.size-1;
real ¬ 1.0-real;
IF real <= 0.0 THEN RETURN [1.0-table[0]] ELSE
IF real >= 1.0 THEN RETURN [1.0-table[limit]] ELSE
IF
NOT RealInline.IsValid[real]
THEN
RETURN [real]
ELSE {
s: REAL = limit*real;
k: INT = RealInline.MCFix[s]; -- as good as Floor, since s > 0.0
d: REAL = s-REAL[k];
v: REAL = table[k];
RETURN [1.0-(IF d <= 0.0 OR k >= limit THEN v ELSE v + d * (table[k+1]-v))]
};
};
};
ColorPoint: TYPE = ImagerColorPrivate.ColorPoint;
CMYKFromCMYK:
PUBLIC
PROC [control: DeviceColorControl, c, m, y, k:
REAL, maxOut:
REAL, out: ColorPoint] = {
oog: BOOL ¬ FALSE;
CS:
PROC [r:
REAL]
RETURNS [
REAL] =
INLINE {
r ¬ r * maxOut;
IF r < 0.0 THEN {oog ¬ TRUE; r ¬ 0.0}
ELSE IF r > maxOut THEN {oog ¬ TRUE; r ¬ maxOut};
RETURN [r]
};
out[0] ¬ CS[LookupFlipped[control.table[$redTransfer], c]];
out[1] ¬ CS[LookupFlipped[control.table[$greenTransfer], m]];
out[2] ¬ CS[LookupFlipped[control.table[$blueTransfer], y]];
out[3] ¬ CS[LookupFlipped[control.table[$grayTransfer], k]];
out.outOfGamut ¬ oog;
};
CMYKFromCMY:
PUBLIC
PROC [control: DeviceColorControl, c, m, y:
REAL, maxOut:
REAL, out: ColorPoint] = {
oog: BOOL ¬ FALSE;
CS:
PROC [r:
REAL]
RETURNS [
REAL] =
INLINE {
r ¬ r * maxOut;
IF r < 0.0 THEN {oog ¬ TRUE; r ¬ 0.0}
ELSE IF r > maxOut THEN {oog ¬ TRUE; r ¬ maxOut};
RETURN [r]
};
bg: LookupTable = control.table[$blackGeneration];
ucr: LookupTable = control.table[$undercolorRemoval];
min: REAL = MIN[c, m, y];
k: REAL ¬ IF bg = NIL THEN 0.0 ELSE LookupReal[bg, min];
IF ucr #
NIL
THEN {
u: REAL = LookupReal[ucr, min];
c ¬ c - u;
m ¬ m - u;
k ¬ k - u;
};
out[0] ¬ CS[LookupFlipped[control.table[$redTransfer], c]];
out[1] ¬ CS[LookupFlipped[control.table[$greenTransfer], m]];
out[2] ¬ CS[LookupFlipped[control.table[$blueTransfer], y]];
out[3] ¬ CS[LookupFlipped[control.table[$grayTransfer], k]];
out.outOfGamut ¬ oog;
};
CMYKFromRGB:
PUBLIC
PROC [control: DeviceColorControl, r, g, b:
REAL, maxOut:
REAL, out: ColorPoint] = {
CMYKFromCMY[control, 1.0-r, 1.0-g, 1.0-b, maxOut, out];
};
RGBFromRGB:
PUBLIC
PROC [control: DeviceColorControl, r, g, b:
REAL, maxOut:
REAL, out: ColorPoint] = {
oog: BOOL ¬ FALSE;
CS:
PROC [r:
REAL]
RETURNS [
REAL] =
INLINE {
r ¬ r * maxOut;
IF r < 0.0 THEN {oog ¬ TRUE; r ¬ 0.0}
ELSE IF r > maxOut THEN {oog ¬ TRUE; r ¬ maxOut};
RETURN [r]
};
out[0] ¬ CS[LookupReal[control.table[$redTransfer], r]];
out[1] ¬ CS[LookupReal[control.table[$greenTransfer], g]];
out[2] ¬ CS[LookupReal[control.table[$blueTransfer], b]];
out.outOfGamut ¬ oog;
};
RGBFromCMYK:
PUBLIC
PROC [control: DeviceColorControl, c, m, y, k:
REAL, maxOut:
REAL, out: ColorPoint] = {
RGBFromRGB[control, 1.0-(c+k), 1.0-(m+k), 1.0-(y+k), maxOut, out];
};
YFromY:
PUBLIC
PROC [control: DeviceColorControl,
Y:
REAL, maxOut:
REAL, out: ColorPoint] = {
g: BOOL ¬ FALSE;
CS:
PROC [r:
REAL]
RETURNS [
REAL] =
INLINE {
r ¬ r * maxOut;
IF r < 0.0 THEN {g ¬ TRUE; r ¬ 0.0}
ELSE IF r > maxOut THEN {g ¬ TRUE; r ¬ maxOut};
RETURN [r]
};
out[0] ¬ CS[LookupReal[control.table[$grayTransfer], Y]];
out.outOfGamut ¬ g;
};
KFromY:
PUBLIC
PROC [control: DeviceColorControl,
Y:
REAL, maxOut:
REAL, out: ColorPoint] = {
g: BOOL ¬ FALSE;
CS:
PROC [r:
REAL]
RETURNS [
REAL] =
INLINE {
r ¬ r * maxOut;
IF r < 0.0 THEN {g ¬ TRUE; r ¬ 0.0}
ELSE IF r > maxOut THEN {g ¬ TRUE; r ¬ maxOut};
RETURN [r]
};
out[0] ¬ CS[1.0-LookupReal[control.table[$grayTransfer], Y]];
out.outOfGamut ¬ g;
};
CMYKFromY:
PUBLIC
PROC [control: DeviceColorControl,
Y:
REAL, maxOut:
REAL, out: ColorPoint] = {
g: BOOL ¬ FALSE;
CS:
PROC [r:
REAL]
RETURNS [
REAL] =
INLINE {
r ¬ r * maxOut;
IF r < 0.0 THEN {g ¬ TRUE; r ¬ 0.0}
ELSE IF r > maxOut THEN {g ¬ TRUE; r ¬ maxOut};
RETURN [r]
};
out[0] ¬ out[1] ¬ out[2] ¬ 0.0;
out[3] ¬ CS[1.0-LookupReal[control.table[$grayTransfer], Y]];
out.outOfGamut ¬ g;
};