DIRECTORY Imager USING [Error, Context], ImagerBasic USING [DeviceRectangle, Color, ColorRep], ImagerDisplay USING [DisplayClass, DisplayClassRep, DisplayData, CreateImagerClass], ImagerStdColorDisplay USING [SetUpMapProc, CachedColorProc, Create, ApplyMask, LoadColorMap, DoUnderLock, ColorMapData, MoveOverlay, ColorSequence, PinPixelMap, ReleasePixelMap, LoadColorProc], ImagerManhattan USING [Polygon], ImagerMasks USING [Mask], ImagerPrivate USING [Class, RegisterDevice], ColorModels USING [Calibration], ConstantColors USING [ColorToRGB, ColorToHSV, black, white, red, cyan], Terminal USING [ColorMode, Current, SetColor, Virtual], Atom USING [GetPropFromList], Real USING [FixC], RealFns USING [Power]; ImagerStd2BitDisplayImpl: CEDAR MONITOR IMPORTS Imager, ImagerDisplay, ImagerPrivate, ConstantColors, Terminal, Real, RealFns, Atom, ImagerStdColorDisplay ~ BEGIN DisplayClass: TYPE ~ ImagerDisplay.DisplayClass; DisplayClassRep: TYPE ~ ImagerDisplay.DisplayClassRep; DisplayData: TYPE ~ ImagerDisplay.DisplayData; Color: TYPE ~ ImagerBasic.Color; ColorRep: TYPE ~ ImagerBasic.ColorRep; ConstantColor: TYPE = REF ColorRep.constant; Mask: TYPE ~ ImagerMasks.Mask; on: BOOLEAN ~ TRUE; off: BOOLEAN ~ FALSE; bitsPerPixel: NAT ~ 4; colorAccuracy: REAL _ .1; vt: Terminal.Virtual; mode: Terminal.ColorMode ~ [full: FALSE, bitsPerPixelChannelA: 2, bitsPerPixelChannelB: 2]; std2BitDisplayClass: ImagerDisplay.DisplayClass ~ NEW[ImagerDisplay.DisplayClassRep _ [ displayType: $Std2bpp, viewUnitsPerPixel: 1, Create: Create, ApplyMask: ApplyMask, DoUnderLock: ImagerStdColorDisplay.DoUnderLock ]]; ColorDisplayError: PUBLIC ERROR [reason: ATOM] ~ CODE; Sqr: PROCEDURE [number: REAL] RETURNS [REAL] ~ INLINE { RETURN[number * number]; }; Create: PROC [displayClass: DisplayClass, creationData: REF] RETURNS [displayData: DisplayData] ~ { displayData _ ImagerStdColorDisplay.Create[ vt, mode, displayClass, creationData, bitsPerPixel, SetUpColorMap]; }; ApplyMask: PROC [displayData: DisplayData, color: Color, mask: Mask, sTranslate, fTranslate: INTEGER] ~ { ImagerStdColorDisplay.ApplyMask[displayData, color, mask, sTranslate, fTranslate, CacheColor]; }; SpecialOp: PROC[context: Imager.Context, op: ATOM, data: REF] RETURNS[REF] ~ { SELECT op FROM $DisplayContext => { -- Pin a pixel map to the color display, replace what was there before. ImagerStdColorDisplay.PinPixelMap[vt, NARROW[context.data, ImagerDisplay.DisplayData], mode ]; }; $UnDisplayContext => ImagerStdColorDisplay.ReleasePixelMap[vt, NARROW[context.data, ImagerDisplay.DisplayData]]; $MoveOverlay => ImagerStdColorDisplay.MoveOverlay[vt, data]; -- change DCB offsets $LoadColorMap => ImagerStdColorDisplay.LoadColorMap[vt, data, NARROW[context.data, ImagerDisplay.DisplayData], LoadColor ]; $SetColorAccuracy => colorAccuracy _ NARROW[ NARROW[ data, LIST OF REF ANY].first , REF REAL]^; ENDCASE => Imager.Error[$UnimplementedSpecialOp]; RETURN[ NIL ]; }; SetUpColorMap: ImagerStdColorDisplay.SetUpMapProc ~ { colorData: REF ImagerStdColorDisplay.ColorMapData _ NARROW[displayData.cachedColorData]; colorMap: REF ImagerStdColorDisplay.ColorSequence _ NEW[ImagerStdColorDisplay.ColorSequence[4]]; colorMap[0] _ ConstantColors.black; colorMap[3] _ ConstantColors.white; colorMap[1] _ ConstantColors.red; colorMap[2] _ ConstantColors.cyan; colorData.map _ colorMap; -- plug the map into the colorData record IF Atom.GetPropFromList[displayData.props, $PixelMapStatus] = $Displayed THEN FOR i: NAT IN [0..4) DO LoadColor[colorData.map[i], colorData.colorCalibration, i]; ENDLOOP; }; LoadColor: ImagerStdColorDisplay.LoadColorProc ~ { mapIndex, quadrant: [0..256); r, g, b: REAL; nr, ng, nb: [0..256); [r, g, b] _ ConstantColors.ColorToRGB[color, colorCalibration]; r _ MIN[1.0, MAX[0.0, r]]; g _ MIN[1.0, MAX[0.0, g]]; b _ MIN[1.0, MAX[0.0, b]]; nr _ Real.FixC[255.0 * RealFns.Power[r, .43]]; ng _ Real.FixC[255.0 * RealFns.Power[g, .43]]; nb _ Real.FixC[255.0 * RealFns.Power[b, .43]]; mapIndex _ mapEntry MOD 4; quadrant _ MIN[mapEntry / 4, 3]; vt.SetColor[ mapIndex, quadrant, nr, ng, nb]; }; CacheColor: ImagerStdColorDisplay.CachedColorProc ~ { colorData: REF ImagerStdColorDisplay.ColorMapData _ NARROW[displayData.cachedColorData]; displayData.cachedColor _ NIL; WITH color SELECT FROM constantColor: ConstantColor => { FOR i: NAT IN [0..colorData.map.length) DO IF color = colorData.map[i] THEN { colorData.pixelValueList _ LIST[ i ]; displayData.cachedColor _ color; -- already in colormap }; ENDLOOP; IF displayData.cachedColor = NIL THEN FOR i: NAT IN [0..colorData.map.length) DO IF constantColor.x = colorData.map[i].x -- check if identical to a previous color AND constantColor.y = colorData.map[i].y AND constantColor.Y = colorData.map[i].Y THEN { -- already in colormap colorData.pixelValueList _ LIST[ i ]; displayData.cachedColor _ color; }; ENDLOOP; IF displayData.cachedColor = NIL THEN { minIndex: NAT; minDist: REAL _ 2.0; -- max value for min. summed-squares distance in CIE space h, s, v: REAL _ 0; [h, s, v] _ ConstantColors.ColorToHSV[constantColor, colorData.colorCalibration]; FOR i: NAT IN [0..colorData.map.length) DO mapHue, mapSat, mapVal: REAL; dist: REAL; [mapHue, mapSat, mapVal] _ ConstantColors.ColorToHSV[colorData.map[i], colorData.colorCalibration]; dist _ Sqr[h - mapHue] * 2 + Sqr[s - mapSat] + Sqr[v - mapVal]; IF dist < minDist THEN { minIndex _ i; minDist _ dist; }; ENDLOOP; IF minDist < colorAccuracy THEN { colorData.pixelValueList _ LIST[ minIndex ]; displayData.cachedColor _ color; }; }; }; ENDCASE => Imager.Error[$UnsupportedColorType]; IF displayData.cachedColor = NIL THEN Imager.Error[$CantMatchColor]; -- sorry! }; Init: PROC[] ~ { std2BitImagerClass: ImagerPrivate.Class ~ ImagerDisplay.CreateImagerClass[std2BitDisplayClass]; -- pick up Imager class record std2BitImagerClass.SpecialOp _ SpecialOp; -- modify procedure bindings ImagerPrivate.RegisterDevice[std2BitImagerClass]; -- register device class vt _ Terminal.Current[]; }; Init[]; END. ξImagerStd2BitDisplayImpl.mesa Copyright c 1984 by Xerox Corporation. All rights reserved. Frank Crow, April 19, 1984 3:39:45 pm PST This implements a 2-bit-per-pixel color-mapped display with no antialiasing. Maximum summed-squares distance allowed in color matching. Determined by trial to allow hits with 2-level color names (eg. "vivid dark bluish green") PROC[displayData: DisplayData] Set up 4 standard colors so that complements contrast PROC [ color: ConstantColor, colorCalibration: ColorModels.Calibration, mapEntry: [0..1024) ] Map entries are assumed to be in four quadrants of 4 entries each PROC [displayData: DisplayData, color: Color] Check for presence of color in this context's cache. Failed completely, find closest color Κ©˜Ihead1™šœ Οmœ1™Ÿ˜SJšœ=˜=Jšœ žœ*˜˜>Jšžœ˜——Jšœ˜J˜—š  œ)˜2JšžœY™]J™AJšœ˜Jšœ žœ˜Jšœ˜Jšœ?˜?Jš œžœžœžœžœžœžœ ˜WJšœ1˜1Jšœ/˜/Jšœ.˜.Jšœžœ˜Jšœ žœ˜"Jšœ-˜-Jšœ˜J˜—šΟb œ+˜5Jšžœ)™-J™4Jšœ žœ&žœ˜XJšœžœ˜šžœžœž˜šœ!˜!š žœžœžœžœžœžœ˜NJšœžœ˜%Jšœ"Ÿ˜?J˜Jšžœ˜—š žœžœžœžœžœžœž˜Pšž œ žœžœŸ)˜ZJšžœ žœž˜)Jšžœžœžœ˜+—šžŸ%˜,Jšœžœ˜%Jšœ ˜ J˜—Jšžœ˜JšŸ%™%—šžœžœžœ˜'Jšœ žœ˜Jšœ žœŸ<˜QJšœ žœ˜JšœQ˜Qšžœžœžœž˜*Jšœžœ žœ˜,Jšœv˜vJšœC˜CJšžœžœ(˜>Jšžœ˜—šžœžœ˜!Jšœžœ ˜,Jšœ ˜ J˜—Jšœ˜—Jšœ˜—Jšžœ(˜/Jšžœžœžœ Ÿ ˜O—Jšœ˜J˜—š œžœ˜Jšœ`Ÿ˜Jšœ-Ÿ˜JJšœ3Ÿ˜LMšœ˜J˜J˜—˜J˜—Jšžœ˜—…—j"