<> <> <> DIRECTORY Basics USING [bitsPerWord, LongMult], ImagerColor, ImagerDevice USING [Class, ClassRep, Device, DeviceRep, HalftoneParameters, RunProc], ImagerPixelArray, ImagerPixelMap USING [Create, DeviceRectangle, Function, PixelMap], ImagerPixelRow, ImagerSampler USING [CreateSampler, ObtainInterpolatedSamples, Sampler], ImagerTransformation USING [Cat, PreRotate, Transformation, Translate], PrincOps USING [BBTableSpace, BitBltTable, BitBltTablePtr, zBNDCK, zINC], PrincOpsUtils USING [AlignedBBTable, BITBLT], Real USING [FixC, RoundC], Vector2 USING [VEC]; ImagerGrayDeviceImpl: CEDAR PROGRAM IMPORTS Basics, ImagerPixelArray, ImagerPixelMap, ImagerPixelRow, ImagerSampler, ImagerTransformation, PrincOpsUtils, Real ~ BEGIN Device: TYPE ~ ImagerDevice.Device; RunProc: TYPE ~ ImagerDevice.RunProc; HalftoneParameters: TYPE ~ ImagerDevice.HalftoneParameters; DeviceRectangle: TYPE ~ ImagerPixelMap.DeviceRectangle; VEC: TYPE ~ Vector2.VEC; Transformation: TYPE ~ ImagerTransformation.Transformation; Color: TYPE ~ ImagerColor.Color; ConstantColor: TYPE ~ ImagerColor.ConstantColor; SampledColor: TYPE ~ ImagerColor.SampledColor; SpecialColor: TYPE ~ ImagerColor.SpecialColor; ColorOperator: TYPE ~ ImagerColor.ColorOperator; ColorOperatorRep: TYPE ~ ImagerColor.ColorOperatorRep; Case: TYPE ~ {nil, constant, sampled}; Data: TYPE ~ REF DataRep; DataRep: TYPE ~ RECORD[ frame: ImagerPixelMap.PixelMap, -- the frame buffer, 8 bits per pixel pixelsPerInch: REAL, -- declared resolution case: Case _ nil, -- what type of color function: ImagerPixelMap.Function _ [null, null], -- bitblt function gray: CARDINAL _ 0, -- bitblt gray value pa: ImagerPixelArray.PixelArray _ NIL, -- pixel array from sampled color multiplier: CARDINAL _ 1, lgScale: INTEGER _ 0, -- scale pa samples to 8 bits paToDevice: Transformation _ NIL, -- transformation from pa coords to display source: ImagerPixelMap.PixelMap _ [0, 0, 0, 0, 0, 0, NIL], -- source values from pixel array paSampler: ImagerSampler.Sampler _ NIL, -- for sampling pixel array paRow: ImagerPixelRow.PixelRow _ NIL -- buffer for pixels sampled from pa ]; class: ImagerDevice.Class ~ NEW[ImagerDevice.ClassRep _ [ type: $GrayDisplay, SetColor: SetColor, SetPriority: SetPriority, SetHalftone: SetHalftone, MaskRuns: MaskRuns ]]; defaultPixelsPerInch: REAL ~ 42; Create: PUBLIC PROC[frame: ImagerPixelMap.PixelMap, pixelsPerInch: REAL _ defaultPixelsPerInch] RETURNS[Device] ~ { data: Data ~ NEW[DataRep _ [frame: frame, pixelsPerInch: pixelsPerInch]]; surfaceToDevice: Transformation ~ ImagerTransformation.Translate[[frame.sSize, 0]]; surfaceToDevice.PreRotate[90]; data.paRow _ ImagerPixelRow.CreatePixelRow[sMin: 0, fMin: 0, fSize: frame.fSize]; RETURN[NEW[ImagerDevice.DeviceRep _ [class: class, clipBox: [sMin: 0, fMin: 0, sSize: frame.sSize, fSize: frame.fSize], surfaceToDevice: surfaceToDevice, surfaceUnitsPerInch: [pixelsPerInch, pixelsPerInch], surfaceUnitsPerPixel: 1, data: data]]]; }; Val: TYPE ~ ImagerPixelArray.Val; Table: TYPE ~ REF TableRep; TableRep: TYPE ~ RECORD[SEQUENCE size: NAT OF CARDINAL]; BuildTable: PROC[max: Val, scale: REAL, sWhite, sBlack: REAL, map: ImagerColor.SampleMap _ NIL] RETURNS[Table] ~ { table: Table ~ NEW[TableRep[max+1]]; FOR s0: Val IN[0..max] DO s: REAL ~ IF map=NIL THEN s0 ELSE map[s0]; v: REAL ~ MIN[MAX[(s-sBlack)/(sWhite-sBlack), 0], 1]; table[s0] _ Real.FixC[scale*v]; ENDLOOP; RETURN[table]; }; SetColor: PROC[device: Device, color: Color, viewToDevice: Transformation] ~ { data: Data ~ NARROW[device.data]; WITH color SELECT FROM color: ConstantColor => { pixel: [0..256) ~ Real.RoundC[MIN[MAX[color.cie.Y, 0], 1]*255]; data.function _ [null, null]; data.gray _ pixel*256+pixel; data.case _ constant; }; color: SampledColor => { pa: ImagerPixelArray.PixelArray ~ color.pa; samples: ImagerPixelArray.Row ~ NEW[ImagerPixelArray.RowRep[pa.fSize]]; row: ImagerPixelRow.PixelRow ~ ImagerPixelRow.CreatePixelRow[ sMin: 0, fMin: 0, fSize: pa.fSize]; data.pa _ pa; data.paToDevice _ ImagerTransformation.Cat[pa.m, color.um, viewToDevice]; data.source _ ImagerPixelMap.Create[lgBitsPerPixel: 3, bounds: [sMin: 0, fMin: 0, sSize: pa.sSize, fSize: pa.fSize]]; WITH color.colorOperator SELECT FROM op: REF ColorOperatorRep.grayLinear => { table: Table _ NIL; IF pa.samplesPerPixel#1 THEN ERROR; -- samplesPerPixel must be 1 table _ BuildTable[max: pa.MaxSampleValue[0], scale: 255, sWhite: op.sWhite, sBlack: op.sBlack, map: op.map]; FOR s: NAT IN[0..pa.sSize) DO ImagerPixelArray.GetRow[pa, samples, s, 0, 0]; FOR f: NAT IN[0..pa.fSize) DO row[f] _ table[samples[f]] ENDLOOP; row.sOrigin _ s; ImagerPixelRow.StorePixelRow[row, data.source]; ENDLOOP; }; op: REF ColorOperatorRep.separations => { tables: ARRAY[0..4) OF Table _ ALL[NIL]; IF pa.samplesPerPixel#op.samplesPerPixel THEN ERROR; -- samplesPerPixel must match FOR i: NAT IN[0..pa.samplesPerPixel) DO sep: ImagerColor.Separation ~ op[i]; tables[i] _ BuildTable[max: pa.MaxSampleValue[i], scale: 255*sep.cie.Y, sWhite: sep.sMax, sBlack: sep.sMin, map: sep.map]; ENDLOOP; FOR s: NAT IN[0..pa.sSize) DO row.sOrigin _ s; ImagerPixelRow.ClearPixelRow[row]; FOR i: NAT IN[0..pa.samplesPerPixel) DO table: Table ~ tables[i]; ImagerPixelArray.GetRow[pa, samples, s, 0, i]; FOR f: NAT IN[0..pa.fSize) DO row[f] _ row[f]+table[samples[f]] ENDLOOP; ENDLOOP; ImagerPixelRow.StorePixelRow[row, data.source]; ENDLOOP; }; < {>> <> <> <<};>> < {>> <> <> <pa.MaxSampleValue[0] THEN NULL>> <> <