DIRECTORY Prop USING [Get, Put], RealInline USING [IsValid, MCFix], ImagerDevice USING [Device], ImagerColorPrivate USING [ColorPoint], ImagerDeviceColor; ImagerDeviceColorImpl: CEDAR PROGRAM IMPORTS Prop, RealInline EXPORTS ImagerDeviceColor ~ 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]]; 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; }; END. Ί ImagerDeviceColorImpl.mesa Copyright Σ 1993 by Xerox Corporation. All rights reserved. Michael Plass, October 26, 1993 2:13 pm PDT NOTE: control.private is not used at present. Κ;•NewlineDelimiter ™code™Kšœ Οeœ1™