<> <> <> <<>> <> <<>> DIRECTORY ImageGamuts, CalibratedColor, AIS, SampleCache, IO, FS, ColorPlotGamuts, UserProfileOps, ImagerColor, ImagerColorFns, Rope, CreateCalibration, CalibratedColorFns, Process, PrintColorXForms, ImagerPixel, Real, TRCData; ImageGamutsImpl: CEDAR PROGRAM IMPORTS AIS, SampleCache, UserProfileOps, ColorPlotGamuts, CalibratedColor, CalibratedColorFns, IO, FS,Rope, CreateCalibration, Process, ImagerColorFns, PrintColorXForms, ImagerPixel, Real, TRCData EXPORTS ImageGamuts ~ BEGIN OPEN ImageGamuts; State: TYPE ~ ColorPlotGamuts.State; Projection: TYPE ~ ColorPlotGamuts.Projection; RGBCalibration: TYPE = CalibratedColor.RGBCalibration; SampledCalibration: TYPE = CalibratedColor.SampledCalibration; Sample: TYPE = SampleCache.Sample; Cache: TYPE = SampleCache.Cache; RefCache: TYPE = SampleCache.RefCache; XYZ: TYPE = CalibratedColor.XYZ; CIELAB: TYPE = CalibratedColor.CIELAB; RGB: TYPE = ImagerColor.RGB; ROPE: TYPE = Rope.ROPE; <> <> <> InputData: TYPE = REF InputDataRec; InputDataRec: TYPE = RECORD[rgb: RGB]; <> CreateInputData: PUBLIC PROC [fileStem: ROPE, rgbCal: RGBCalibration] RETURNS [inputData: RefCache] ~ { <> aisFiles: AISFiles _ OpenFiles[fileStem]; nLines: NAT _ aisFiles[r].raster.scanCount; nPixels: NAT _ aisFiles[r].raster.scanLength; white: XYZ _ CalibratedColor.XYZFromRGB[[1,1,1], rgbCal]; ref: REF _ NIL; key: Sample; valid: BOOLEAN _ FALSE; inputData _ SampleCache.CreateRefCache[]; Process.SetPriority[Process.priorityBackground]; FOR line: NAT IN [0..nLines) DO FOR pixel: NAT IN [0..nPixels) DO key.s0 _ AIS.ReadSample[w: aisFiles[r].wRef,line: line, pixel: pixel]; key.s1 _ AIS.ReadSample[w: aisFiles[g].wRef,line: line, pixel: pixel]; key.s2 _ AIS.ReadSample[w: aisFiles[b].wRef,line: line, pixel: pixel]; [valid, ref] _ SampleCache.FetchRef[inputData, key]; IF NOT valid THEN { data: InputData _ NEW[InputDataRec]; data.rgb _ [key.s0/255.0, key.s1/255.0, key.s2/255.0]; SampleCache.StoreRef[inputData, key, data] }; ENDLOOP; ENDLOOP; CloseFiles[aisFiles]; }; OpenFiles: PUBLIC PROC [fileStem: ROPE] RETURNS [aisFiles: AISFiles] ~ { <> aisFiles[r].name _ FindFile[fileStem, "AISseparationKeys.red", "-red"]; aisFiles[g].name _ FindFile[fileStem, "AISseparationKeys.green", "-grn"]; aisFiles[b].name _ FindFile[fileStem, "AISseparationKeys.blue", "-blu"]; FOR c: AISColors IN [r..b] DO aisFiles[c].fRef _ AIS.OpenFile[aisFiles[c].name]; aisFiles[c].wRef _ AIS.OpenWindow[aisFiles[c].fRef]; aisFiles[c].raster _ AIS.ReadRaster[aisFiles[c].fRef] ENDLOOP; }; CloseFiles: PUBLIC PROC [aisFiles: AISFiles] ~ { <> FOR c: AISColors IN [r..b] DO AIS.CloseFile[aisFiles[c].fRef]; ENDLOOP; IF aisFiles[clipped].name#NIL THEN AIS.CloseFile[aisFiles[clipped].fRef]; }; CreateFiles: PUBLIC PROC [fileStem: ROPE, raster: AIS.Raster] RETURNS [aisFiles: AISFiles] ~ { <> aisFiles[r].name _ Rope.Cat[fileStem, "-red.ais"]; aisFiles[g].name _ Rope.Cat[fileStem, "-grn.ais"]; aisFiles[b].name _ Rope.Cat[fileStem, "-blu.ais"]; FOR c: AISColors IN [r..b] DO aisFiles[c].fRef _ AIS.CreateFile[aisFiles[c].name, raster]; aisFiles[c].wRef _ AIS.OpenWindow[aisFiles[c].fRef]; aisFiles[c].raster _ raster; ENDLOOP; aisFiles[clipped].raster _ NEW[AIS.RasterPart _ [ scanCount: raster.scanCount, scanLength: raster.scanLength, scanMode: raster.scanMode, bitsPerPixel: 0, linesPerBlock: -1, paddingPerBlock: 0 ]]; aisFiles[clipped].name _ Rope.Cat[fileStem, "-clipped.ais"]; aisFiles[clipped].fRef _ AIS.CreateFile[aisFiles[clipped].name, aisFiles[clipped].raster]; aisFiles[clipped].wRef _ AIS.OpenWindow[aisFiles[clipped].fRef]; }; FindFile: PUBLIC PROC [stem, key, default: ROPE] RETURNS [ROPE] ~ { fileList: LIST OF ROPE _ UserProfileOps.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]; EXITS notThere => NULL; }; IF fileList = NIL THEN RETURN [NIL]; IF FileExists[fileList.first] THEN RETURN [fileList.first]; fileList _ fileList.rest }; ENDLOOP; }; <> <> <> <> <> <> <> <> <<};>> <> <> <> <> <<};>> <> <> <> <> <> <> <<[word, ] _ IO.GetTokenRope[stream];>> <> <<[] _ IO.GetChar[stream]; --strip off the :>> <<};>> <> <<[] _ IO.GetToken >> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<>> <> <<>> <<};>> << >> <> PlotInputData: PUBLIC PROC [state: State, inputData: RefCache, mapData: REF, mapProc: MapProc, imageColorProc: ColorProc _ NIL] ~ { <> plot: PROC[key: Sample, data: REF, hits: INT] = { inputData: InputData _ NARROW[data]; xyz: XYZ _ mapProc[key, inputData.rgb, mapData]; x,y: REAL; rgb: RGB _ imageColorProc[key]; [x,y] _ ColorPlotGamuts.MapValues[state, xyz]; ColorPlotGamuts.MarkPoint[state, Real.Round[x], Real.Round[y], rgb]; }; Process.SetPriority[Process.priorityBackground]; SampleCache.EnumerateRefCache[inputData, plot]; }; GetCalibrations: PUBLIC PROC[rgbAtom, sampledAtom: ATOM] RETURNS[rgbCal: RGBCalibration, sampledCal: SampledCalibration] = { rgbCal _ CreateCalibration.CreateRGB[CreateCalibration.GetRGBDataValues[rgbAtom]]; sampledCal _ CreateCalibration.CreateSampled[CreateCalibration.GetSampledFiles[sampledAtom], sampledAtom]; }; MakeChromaPlot: PUBLIC PROC [pi: PlotInfo, xAxis, yAxis: Projection, mapInfo: MapInfo] ~ { rgbState: State _ ColorPlotGamuts.StateFromRGBCalibration[pi.rgbCal, xAxis, yAxis, pi.res, ColorPlotGamuts.RGBRainbow, pi.rgbCal]; sampledState: State _ ColorPlotGamuts.StateFromCalibration[pi.sampledCal, xAxis, yAxis, pi.res, ColorPlotGamuts.SampledRainbow, pi.sampledCal]; inputData: RefCache _ pi.inputData; IF inputData = NIL THEN { inputData _ CreateInputData[pi.aisRoot, pi.rgbCal]; pi.inputData _ inputData}; ColorPlotGamuts.RGBSampleAndPlot[rgbState, pi.rgbCal, 256, ColorPlotGamuts.HueCircle]; ColorPlotGamuts.SampleAndPlot[sampledState, pi.sampledCal, 256, ColorPlotGamuts.HueCircle]; IF mapInfo.rgbState THEN PlotInputData[rgbState, inputData, mapInfo.mapData, mapInfo.mapProc, Rainbow] ELSE PlotInputData[sampledState, inputData, mapInfo.mapData, mapInfo.mapProc, Rainbow]; ColorPlotGamuts.StatesToInterpress[states: LIST[rgbState, sampledState], ipName: Rope.Cat[pi.ipRoot, ".ip"], label: TRUE, note: pi.note, labelColor: pi.labelColor, bleedBackground: pi.bleedBackground]; }; MakeLStarPlot: PUBLIC PROC [pi: PlotInfo, xAxis: Projection, mapInfo: MapInfo] ~ { rgbState: State _ ColorPlotGamuts.StateFromRGBCalibration[pi.rgbCal, xAxis, lStar, pi.res, ColorPlotGamuts.White, pi.rgbCal]; sampledState: State _ ColorPlotGamuts.StateFromCalibration[pi.sampledCal, xAxis, lStar, pi.res, ColorPlotGamuts.Black, pi.sampledCal]; inputData: RefCache _ pi.inputData; states: LIST OF State _ LIST[sampledState, rgbState]; IF inputData = NIL THEN { inputData _ CreateInputData[pi.aisRoot, pi.rgbCal]; pi.inputData _ inputData}; ColorPlotGamuts.RGBSampleAndPlot[rgbState, pi.rgbCal, 8, ColorPlotGamuts.WholeGamut]; ColorPlotGamuts.SampleAndPlot[sampledState, pi.sampledCal, 16, ColorPlotGamuts.WholeGamut, FALSE]; IF mapInfo.rgbState THEN PlotInputData[rgbState, inputData, mapInfo.mapData, mapInfo.mapProc, SatRainbow] ELSE { PlotInputData[sampledState, inputData, mapInfo.mapData, mapInfo.mapProc, SatRainbow]; states _ LIST[rgbState, sampledState]; }; ColorPlotGamuts.StatesToInterpress[states: states, ipName: Rope.Cat[pi.ipRoot, ".ip"], label: TRUE, note: pi.note, labelColor: pi.labelColor, bleedBackground: pi.bleedBackground]; }; Make3LABViews: PUBLIC PROC [pi: PlotInfo, mapInfo: MapInfo] ~ { ipRoot: ROPE _ pi.ipRoot; pi.ipRoot _ Rope.Cat[ipRoot, "AB"]; MakeChromaPlot[pi: pi, xAxis: aStar, yAxis: bStar, mapInfo: mapInfo]; pi.ipRoot _ Rope.Cat[ipRoot, "AL"]; MakeLStarPlot[pi: pi, xAxis: aStar, mapInfo: mapInfo]; pi.ipRoot _ Rope.Cat[ipRoot, "BL"]; MakeLStarPlot[pi: pi, xAxis: bStar, mapInfo: mapInfo]; }; Rainbow: ColorProc = { RETURN[[R: sample.s0/255.0, G: sample.s1/255.0, B: sample.s2/255.0]]; }; DoSat: PROC[in: RGB] RETURNS[out: RGB] = { hsl: ImagerColorFns.HSL_ ImagerColorFns.HSLFromRGB[boundRGB[in]]; boundRGB: PROC[val: RGB] RETURNS[RGB] = { RETURN[[R: MAX[MIN[val.R, 1],0], G: MAX[MIN[val.G, 1],0], B: MAX[MIN[val.B, 1],0]]]}; out _ ImagerColorFns.RGBFromHSL[[H: hsl.H, S: hsl.S, L: 0.5]]; }; SatRainbow: ColorProc = { rgb: RGB _ [R: sample.s0/255.0, G: sample.s1/255.0, B: sample.s2/255.0]; rgb _ DoSat[rgb]; RETURN[rgb]; }; SatRGB: ColorPlotGamuts.GetColorProc = { --assumes data is RGBCalibration cal: RGBCalibration _ NARROW[data]; rgb: RGB _ CalibratedColor.RGBFromXYZ[xyz, cal]; rgb _ DoSat[rgb]; RETURN[rgb]; }; SatSampled: ColorPlotGamuts.GetColorProc = { --assumes data is RGBCalibration cal: SampledCalibration _ NARROW[data]; triple: CalibratedColor.Triple _ CalibratedColor.TripleFromXYZ[xyz, cal].triple; rgb: RGB _ [triple.v0, triple.v1, triple.v2]; rgb _ DoSat[rgb]; RETURN[rgb]; }; <> <> <> <> <> GetPlotInfo: PUBLIC PROC [aisRoot, ipRoot, note: ROPE, res: NAT, rgbCal: RGBCalibration, sampledCal: SampledCalibration, labelColor: ImagerColor.Color, bleedBackground: BOOLEAN] RETURNS[PlotInfo] = { RETURN[[aisRoot: aisRoot, ipRoot: ipRoot, note: note, res: res, rgbCal: rgbCal, sampledCal: sampledCal, labelColor: labelColor, bleedBackground: bleedBackground]]; }; GetMonitorMapInfo: PUBLIC PROC [rgbCal: RGBCalibration] RETURNS[MapInfo] = { RETURN[[mapProc: RGBMap, mapData: rgbCal, rgbState: TRUE]]; }; GetMappedMapInfo: PUBLIC PROC [tables: PrintColorXForms.MatrixTables, rgbCal: RGBCalibration] RETURNS[MapInfo] = { data: MatrixMapData _ NEW[MatrixMapDataRec _ [ tables: tables, rgbCal: rgbCal ]]; RETURN[[mapProc: MatrixMap, mapData: data, rgbState: TRUE]]; }; GetPrinterMapInfo: PUBLIC PROC [tables: PrintColorXForms.MatrixTables, sampledCal: SampledCalibration] RETURNS[MapInfo] = { data: PrinterMapData _ NEW[PrinterMapDataRec _ [ tables: tables, sampledCal: sampledCal ]]; RETURN[[mapProc: PrinterMap, mapData: data, rgbState: FALSE]]; }; RGBMap: PUBLIC MapProc = { rgbCal: RGBCalibration _ NARROW[data]; xyz: XYZ _ CalibratedColor.XYZFromRGB[rgb, rgbCal]; RETURN[xyz]; }; MatrixMap: PUBLIC MapProc = { mmData: MatrixMapData _ NARROW[data]; mapped: Sample _ MatrixMapProc[rgbBytes, mmData.tables]; xyz: XYZ _ CalibratedColor.XYZFromRGB[[R: mapped.s0/255.0, G: mapped.s1/255.0, B: mapped.s2/255.0], mmData.rgbCal]; RETURN[xyz]; }; PrinterMap: PUBLIC MapProc = { pmData: PrinterMapData _ NARROW[data]; mapped: Sample _ MatrixMapProc[rgbBytes, pmData.tables]; xyz: XYZ _ CalibratedColor.XYZFromTriple[ [v0: mapped.s0/255.0, v1: mapped.s1/255.0, v2: mapped.s2/255.0], pmData.sampledCal]; RETURN[xyz]; }; <> <> AdjustFiles: PUBLIC PROC [fileStem, adjusted: ROPE, proc: SampleProc] ~ { <> inFiles: AISFiles _ OpenFiles[fileStem]; outFiles: AISFiles _ CreateFiles[adjusted, inFiles[r].raster]; nLines: NAT _ inFiles[r].raster.scanCount; nPixels: NAT _ inFiles[r].raster.scanLength; key, sample: Sample; valid: BOOLEAN _ FALSE; cache: Cache _ SampleCache.Create[]; Process.SetPriority[Process.priorityBackground]; FOR line: NAT IN [0..nLines) DO FOR pixel: NAT IN [0..nPixels) DO key.s0 _ AIS.ReadSample[w: inFiles[r].wRef,line: line, pixel: pixel]; key.s1 _ AIS.ReadSample[w: inFiles[g].wRef,line: line, pixel: pixel]; key.s2 _ AIS.ReadSample[w: inFiles[b].wRef,line: line, pixel: pixel]; [valid, sample] _ SampleCache.Fetch[cache, key]; IF NOT valid THEN { sample _ proc[key]; SampleCache.Store[cache, key, sample] }; AIS.WriteSample[w: outFiles[r].wRef,value: sample.s0, line: line, pixel: pixel]; AIS.WriteSample[w: outFiles[g].wRef,value: sample.s1, line: line, pixel: pixel]; AIS.WriteSample[w: outFiles[b].wRef,value: sample.s2, line: line, pixel: pixel]; AIS.WriteSample[w: outFiles[clipped].wRef,value: sample.s3, line: line, pixel: pixel]; ENDLOOP; ENDLOOP; CloseFiles[inFiles]; CloseFiles[outFiles]; }; SaturationMatrix: PUBLIC PROC [rgbToLStar: PrintColorXForms.TRCTable, saturation: REAL, printerDMax: REAL] RETURNS [PrintColorXForms.MatrixTables]~ { matrix: PrintColorXForms.MatrixN _ PrintColorXForms.IdentityMatrix[]; RETURN[PrintColorXForms.InitMatrixTables[ rgbToLStar: rgbToLStar, densityToDotArea: PrintColorXForms.DensityToLStar[printerDMax], printerDMax: printerDMax, saturation: saturation, contrast: -0.0, matrix: matrix]]; }; MatrixMapProc: PROC[in: Sample, matrixTables: PrintColorXForms.MatrixTables] RETURNS [out: Sample] = { rgbIn: ImagerPixel.PixelBuffer _ ImagerPixel.NewPixels[3,1]; cmyOut: ImagerPixel.PixelBuffer _ ImagerPixel.NewPixels[3,1]; maxSampleIn: ARRAY [0..3) OF CARDINAL _ [255, 255, 255]; rgbIn[0][0] _ in.s0; rgbIn[1][0] _ in.s1; rgbIn[2][0] _ in.s2; PrintColorXForms.MatrixTransform[maxSampleIn, rgbIn, cmyOut, matrixTables]; out.s0 _ 255-cmyOut[0][0]; out.s1 _ 255-cmyOut[1][0]; out.s2 _ 255-cmyOut[2][0]; out.s3 _ 0; }; AdjustWithMatrix: PUBLIC PROC [fileStem, adjusted: ROPE, matrixTables: PrintColorXForms.MatrixTables] ~ { <> rgbIn: ImagerPixel.PixelBuffer _ ImagerPixel.NewPixels[3,1]; cmyOut: ImagerPixel.PixelBuffer _ ImagerPixel.NewPixels[3,1]; maxSampleIn: ARRAY [0..3) OF CARDINAL _ [255, 255, 255]; map: SampleProc = { rgbIn[0][0] _ in.s0; rgbIn[1][0] _ in.s1; rgbIn[2][0] _ in.s2; PrintColorXForms.MatrixTransform[maxSampleIn, rgbIn, cmyOut, matrixTables]; out.s0 _ 255-cmyOut[0][0]; out.s1 _ 255-cmyOut[1][0]; out.s2 _ 255-cmyOut[2][0]; out.s3 _ 0; }; AdjustFiles[fileStem, adjusted, map]; }; AdjustRGBToLStar: PUBLIC PROC [fileStem, adjusted: ROPE, array: ARRAY[0..255] OF BYTE] ~ { <> map: SampleProc = { out.s0 _ array[in.s0]; out.s1 _ array[in.s1]; out.s2 _ array[in.s2]; out.s3 _ 0; }; AdjustFiles[fileStem, adjusted, map]; }; AdjustOutOfGamut: PUBLIC PROC [fileStem, adjusted: ROPE, useCIELAB: BOOLEAN _ FALSE] ~ { <> <> rgbCal: RGBCalibration; sampledCal: SampledCalibration; sampleWhite, rgbWhite: XYZ; map: SampleProc = { clipped: BOOLEAN; xyz: XYZ _ CalibratedColor.XYZFromRGB[[in.s0/255.0, in.s1/255.0, in.s2/255.0],rgbCal]; IF useCIELAB THEN { cielab: CIELAB _ CalibratedColorFns.CIELABFromXYZ[xyz,rgbWhite]; xyz _ [cielab.lStar, cielab.aStar, cielab.bStar]; }; [,,clipped] _ CalibratedColor.TripleFromXYZ[xyz,sampledCal, 0.1]; IF clipped THEN out _ [0,0,0,1] ELSE { out.s0 _ in.s0; out.s1 _ in.s1; out.s2 _ in.s2; out.s3 _ 0; }; }; [rgbCal, sampledCal] _ GetCalibrations[$Conrac, $Cromalin]; sampleWhite _ CalibratedColor.XYZFromTriple[[1,1,1], sampledCal]; rgbWhite _ CalibratedColor.XYZFromRGB[[1,1,1], rgbCal]; <> IF useCIELAB THEN FOR v1: NAT IN [0..8) DO FOR v2: NAT IN [0..8) DO FOR v3: NAT IN [0..8) DO xyz: XYZ; cielab: CIELAB; xyz.X _ sampledCal.cieX[v1][v2][v3]; xyz.Y _ sampledCal.cieY[v1][v2][v3]; xyz.Z _ sampledCal.cieX[v1][v2][v3]; cielab _ CalibratedColorFns.CIELABFromXYZ[xyz,sampleWhite]; sampledCal.cieX[v1][v2][v3] _ cielab.lStar; sampledCal.cieY[v1][v2][v3] _ cielab.aStar; sampledCal.cieZ[v1][v2][v3] _ cielab.bStar; ENDLOOP; ENDLOOP; ENDLOOP; AdjustFiles[fileStem, adjusted, map]; }; RGBToLStar: ARRAY[0..255] OF BYTE _ [0, 9, 18, 26, 33, 39, 44, 48, 52, 56, 60, 63, 66, 69, 72, 74, 77, 79, 81, 84, 86, 88, 90, 92, 94, 96, 97, 99, 101, 103, 104, 106, 107, 109, 110, 112, 113, 115, 116, 117, 119, 120, 121, 123, 124, 125, 126, 128, 129, 130, 131, 132, 133, 134, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 151, 152, 153, 154, 155, 156, 157, 158, 159, 159, 160, 161, 162, 163, 163, 164, 165, 166, 167, 167, 168, 169, 170, 171, 171, 172, 173, 174, 174, 175, 176, 176, 177, 178, 179, 179, 180, 181, 181, 182, 183, 183, 184, 185, 185, 186, 187, 187, 188, 189, 189, 190, 191, 191, 192, 192, 193, 194, 194, 195, 196, 196, 197, 197, 198, 198, 199, 200, 200, 201, 201, 202, 203, 203, 204, 204, 205, 205, 206, 206, 207, 208, 208, 209, 209, 210, 210, 211, 211, 212, 212, 213, 213, 214, 215, 215, 216, 216, 217, 217, 218, 218, 219, 219, 220, 220, 221, 221, 222, 222, 223, 223, 224, 224, 225, 225, 225, 226, 226, 227, 227, 228, 228, 229, 229, 230, 230, 231, 231, 232, 232, 232, 233, 233, 234, 234, 235, 235, 236, 236, 236, 237, 237, 238, 238, 239, 239, 240, 240, 240, 241, 241, 242, 242, 242, 243, 243, 244, 244, 245, 245, 245, 246, 246, 247, 247, 247, 248, 248, 249, 249, 249, 250, 250, 251, 251, 251, 252, 252, 253, 253, 253, 254, 254, 255, 255]; AdjustRGBToLStarGC: PUBLIC PROC [fileStem, adjusted: ROPE] ~ { <> map: SampleProc = { gc: BYTE _ MIN[in.s0, in.s1, in.s2]; newgc: BYTE _ RGBToLStar[gc]; r: NAT _ in.s0-gc+newgc; g: NAT _ in.s1-gc+newgc; b: NAT _ in.s2-gc+newgc; IF r >255 OR g>255 OR b>255 THEN out.s3 _ 1 ELSE out.s3 _ 0; out.s0 _ MIN[255, r]; out.s1 _ MIN[255, g]; out.s2 _ MIN[255, b]; }; AdjustFiles[fileStem, adjusted, map]; }; CMYToLStar: ARRAY[0..255] OF BYTE _ [0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 7, 7, 8, 8, 8, 9, 9, 10, 10, 10, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 30, 31, 31, 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39, 40, 40, 41, 42, 42, 43, 43, 44, 44, 45, 45, 46, 46, 47, 47, 48, 49, 49, 50, 50, 51, 51, 52, 52, 53, 54, 54, 55, 55, 56, 57, 57, 58, 58, 59, 59, 60, 61, 61, 62, 63, 63, 64, 64, 65, 66, 66, 67, 68, 68, 69, 70, 70, 71, 72, 72, 73, 74, 74, 75, 76, 76, 77, 78, 79, 79, 80, 81, 81, 82, 83, 84, 84, 85, 86, 87, 88, 88, 89, 90, 91, 92, 92, 93, 94, 95, 96, 96, 97, 98, 99, 100, 101, 102, 103, 104, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 121, 122, 123, 124, 125, 126, 127, 129, 130, 131, 132, 134, 135, 136, 138, 139, 140, 142, 143, 145, 146, 148, 149, 151, 152, 154, 156, 158, 159, 161, 163, 165, 167, 169, 171, 174, 176, 178, 181, 183, 186, 189, 192, 195, 199, 203, 207, 211, 216, 222, 229, 237, 246, 255]; AdjustCMYToLStar: PUBLIC PROC [fileStem, adjusted: ROPE] ~ { <> <> map: SampleProc = { c: NAT _ 255-in.s0; m: NAT _ 255-in.s1; y: NAT _ 255-in.s2; gc: BYTE _ MIN[c,m,y]; newgc: BYTE _ CMYToLStar[gc]; r: NAT _ 255-(c-gc+newgc); g: NAT _ 255-(m-gc+newgc); b: NAT _ 255-(y-gc+newgc); IF r >255 OR g>255 OR b>255 THEN out.s3 _ 1 ELSE out.s3 _ 0; out.s0 _ MIN[255, r]; out.s1 _ MIN[255, g]; out.s2 _ MIN[255, b]; }; AdjustFiles[fileStem, adjusted, map]; }; ConracToLStarTRC: PROC RETURNS[trc: PrintColorXForms.TRCTable] = { trc _ NEW[PrintColorXForms.TRCTableRec]; FOR i: NAT IN [0..256) DO trc[i] _ ConracToLStar[i]; ENDLOOP; }; ConracToLStar: ARRAY[0..255] OF BYTE _ [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, 9, 11, 14, 16, 19, 22, 25, 29, 32, 35, 37, 39, 42, 44, 46, 48, 51, 53, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 83, 85, 87, 88, 90, 91, 93, 94, 95, 97, 98, 100, 101, 103, 104, 106, 107, 109, 110, 112, 113, 114, 116, 117, 118, 119, 121, 122, 123, 125, 126, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 143, 144, 145, 146, 147, 149, 150, 151, 152, 153, 153, 154, 155, 156, 157, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 168, 169, 170, 171, 172, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 181, 182, 183, 184, 185, 185, 186, 187, 188, 189, 189, 190, 191, 192, 193, 193, 194, 195, 196, 197, 197, 198, 199, 200, 201, 201, 202, 203, 204, 205, 205, 206, 207, 208, 208, 209, 209, 210, 211, 212, 212, 213, 214, 215, 216, 216, 217, 218, 218, 219, 219, 220, 220, 221, 221, 222, 222, 223, 224, 224, 225, 225, 226, 227, 227, 228, 228, 229, 230, 230, 231, 231, 232, 232, 233, 233, 234, 234, 235, 235, 236, 236, 237, 238, 238, 239, 239, 240, 241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 245, 246, 246, 247, 247, 247, 248, 248, 249, 249, 249, 250, 250, 251, 251, 251, 252, 252, 253, 253, 253, 254, 254, 255, 255]; END.