DIRECTORY Environment, ImagerBasic, ImagerBrick, ImagerMasks, ImagerMasksPrivate, Inline, Real, Scaled, ImagerTransform, ImagerHalftone, RealFns, ImagerPixelMaps; ImagerHalftoneImpl: CEDAR PROGRAM IMPORTS ImagerBrick, ImagerTransform, ImagerMasks, ImagerMasksPrivate, Inline, Real, Scaled, RealFns EXPORTS ImagerHalftone ~ BEGIN OPEN ImagerHalftone; Hi: PROC [a: CARDINAL] RETURNS [CARDINAL] ~ INLINE {RETURN[Inline.BITSHIFT[a, 1-Environment.bitsPerWord]]}; Shift: PROC [a: CARDINAL, amt: INTEGER] RETURNS [CARDINAL] ~ INLINE {RETURN[Inline.BITSHIFT[a, amt]]}; ScaledFromReal: PROC [real: REAL] RETURNS [Scaled.Value] ~ TRUSTED { i: INT _ Real.RoundLI[real * 65536.0]; RETURN[LOOPHOLE[i]] }; SixteenWords: TYPE ~ MACHINE DEPENDENT RECORD [ w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15: CARDINAL ]; DoLine: UNSAFE PROC [ dst: Environment.BitAddress, count: CARDINAL, sourcePtr: LONG POINTER, brickPtr: LONG POINTER, brickRem: INTEGER, brickPeriod: NAT ] ~ UNCHECKED { p: LONG POINTER TO SixteenWords _ sourcePtr; q: LONG POINTER TO SixteenWords _ brickPtr; GetN: UNSAFE PROC [n: [0..16)] RETURNS [CARDINAL] ~ UNCHECKED { w: CARDINAL _ 0; WHILE brickRem <= 0 DO brickRem _ brickRem + brickPeriod; q _ q - brickPeriod ENDLOOP; THROUGH [0..n) DO w _ w*2 + Hi[p^.w0+q^.w0]; p _ p + 1; q _ q + 1; ENDLOOP; brickRem _ brickRem - n; RETURN [w]; }; -- GetFirst Get16: UNSAFE PROC RETURNS [CARDINAL] ~ UNCHECKED INLINE { s, h: SixteenWords; WHILE brickRem <= 0 DO brickRem _ brickRem + brickPeriod; q _ q - brickPeriod ENDLOOP; s _ p^; p _ p + SIZE[SixteenWords]; h _ q^; q _ q + SIZE[SixteenWords]; brickRem _ brickRem - 16; RETURN [((((((((((((((Hi[h.w0+s.w0]*2+Hi[h.w1+s.w1])*2+Hi[h.w2+s.w2])*2+Hi[h.w3+s.w3])*2+Hi[h.w4+s.w4])*2+Hi[h.w5+s.w5])*2+Hi[h.w6+s.w6])*2+Hi[h.w7+s.w7])*2+Hi[h.w8+s.w8])*2+Hi[h.w9+s.w9])*2+Hi[h.w10+s.w10])*2+Hi[h.w11+s.w11])*2+Hi[h.w12+s.w12])*2+Hi[h.w13+s.w13])*2+Hi[h.w14+s.w14])*2+Hi[h.w15+s.w15]] }; -- Get16 d: LONG POINTER TO CARDINAL _ dst.word; firstBits: INTEGER _ 16-dst.bit; IF dst.bit # 0 THEN { z: INTEGER _ MAX[firstBits-INTEGER[count], 0]; m: CARDINAL _ Shift[1, firstBits] - Shift[1, z]; d^ _ Inline.BITOR[Inline.BITAND[d^, Inline.BITNOT[m]], Shift[GetN[firstBits-z], z]]; d _ d + 1; count _ count - (firstBits-z); }; WHILE count >= 16 DO d^ _ Get16[]; d _ d + 1; count _ count - 16; ENDLOOP; IF count > 0 THEN { d^ _ Inline.BITOR[Inline.BITAND[d^, Shift[1, 16-count]-1], Shift[GetN[count], 16-count]]; }; }; -- DoLine Mod: PROC [p, q: INT] RETURNS [rem: INT] ~ { IF q<0 THEN ERROR; rem _ p MOD q; WHILE rem < 0 DO rem _ rem + q ENDLOOP; }; MakeDeviceBrick: PUBLIC PROC [brick: Brick, maxPixelValue: CARDINAL] RETURNS [d: DeviceBrick] ~ { phase: NAT _ Mod[brick.phase, brick.fSize]; fMax: NAT _ MAX[brick.fSize, 16] + phase + 15; d _ NEW[DeviceBrickRep[brick.sSize]]; d.fMin _ 0; d.sMin _ 0; d.phase _ phase; d.fPeriod _ brick.fSize; FOR s: NAT IN [0..d.sPeriod) DO r: PixelBuffer _ NEW[ImagerBasic.PixelBufferRep[fMax]]; d[s] _ r; FOR f: NAT IN [0..fMax) DO r[f] _ LAST[CARDINAL] - Real.RoundI[brick.GetElement[f, s] * (maxPixelValue+1)]; ENDLOOP; ENDLOOP; }; Halftone: PUBLIC PROC [dest: PixelMap, mask: Mask, source: PixelArray, transformation: Transformation, deviceBrick: DeviceBrick] ~ TRUSTED { raster: CARDINAL _ dest.refRep.rast; sMask: Mask _ mask.InlineShift[-(dest.sMin+dest.sOrigin), -(dest.fMin+dest.fOrigin)]; sMin: NAT _ MAX[sMask.sMin, 0]; sMax: NAT _ MIN[dest.sSize, dest.refRep.lines, sMask.sMin + sMask.sSize]; fMin: NAT _ MAX[sMask.fMin, 0]; fMax: NAT _ MIN[dest.fSize, raster*Environment.bitsPerWord, sMask.fMin + sMask.fSize]; nextPixel: ImagerBasic.Pair _ ImagerTransform.InverseTransformVec[[0, 1], transformation]; nextLine: ImagerBasic.Pair _ ImagerTransform.InverseTransformVec[[1, 0], transformation]; start: ImagerBasic.Pair _ ImagerTransform.InverseTransform[[0.5+sMin+dest.sMin+dest.fOrigin, 0.5+fMin+dest.fMin+dest.fOrigin], transformation]; xStart: Scaled.Value _ ScaledFromReal[start.x]; yStart: Scaled.Value _ ScaledFromReal[start.y]; xDeltaPixel: Scaled.Value _ ScaledFromReal[nextPixel.x]; yDeltaPixel: Scaled.Value _ ScaledFromReal[nextPixel.y]; xDeltaLine: Scaled.Value _ ScaledFromReal[nextLine.x]; yDeltaLine: Scaled.Value _ ScaledFromReal[nextLine.y]; lineBits: NAT _ fMax - fMin; buffer: PixelBuffer _ NEW[ImagerBasic.PixelBufferRep[lineBits]]; linePointer: LONG POINTER _ dest.refRep.pointer + Inline.LongMult[sMin, raster]; sPeriod: CARDINAL _ deviceBrick.sPeriod; fPeriod: CARDINAL _ deviceBrick.fPeriod; sDivPeriod, sModPeriod: CARDINAL; fBrick: NAT; sMinBrick: INT _ sMin-(INT[deviceBrick.sMin]-((dest.sMin+dest.sOrigin) MOD sPeriod)); fMinBrick: INT _ fMin-(INT[deviceBrick.fMin]-((dest.fMin+dest.fOrigin) MOD fPeriod)); WHILE sMinBrick < 0 DO sMinBrick _ sMinBrick + sPeriod ENDLOOP; WHILE fMinBrick < 0 DO fMinBrick _ fMinBrick + fPeriod ENDLOOP; IF dest.refRep.lgBitsPerPixel # 0 THEN ERROR; [quotient: sDivPeriod, remainder: sModPeriod] _ Inline.LongDivMod[sMinBrick, sPeriod]; fBrick _ Inline.LongDivMod[Inline.LongMult[sDivPeriod, deviceBrick.phase] + fMinBrick, fPeriod].remainder; IF sMask.refRep = NIL THEN { bitAddress: Environment.BitAddress _ [word: linePointer + fMin/16, bit: fMin MOD 16]; FOR s: CARDINAL IN [sMin..sMax) DO brickRow: PixelBuffer _ deviceBrick[sModPeriod]; brickPtr: LONG POINTER _ @(brickRow[fBrick]); brickRem: INTEGER _ brickRow.maxLength - 15 - fBrick; source.get[source, buffer, lineBits, 0, xStart, yStart, xDeltaPixel, yDeltaPixel]; DoLine[dst: bitAddress, count: lineBits, sourcePtr: @(buffer[0]), brickPtr: brickPtr, brickRem: brickRem, brickPeriod: fPeriod]; bitAddress.word _ bitAddress.word + raster; xStart _ xStart.PLUS[xDeltaLine]; yStart _ yStart.PLUS[yDeltaLine]; sModPeriod _ sModPeriod + 1; IF sModPeriod = sPeriod THEN { sModPeriod _ 0; sDivPeriod _ sDivPeriod + 1; fBrick _ fBrick + deviceBrick.phase; WHILE fBrick >= fPeriod DO fBrick _ fBrick - fPeriod ENDLOOP; }; ENDLOOP; } ELSE { sMaskReader: ImagerMasksPrivate.Reader; ImagerMasksPrivate.SetReader[@sMaskReader, sMask]; ImagerMasksPrivate.SkipTo[@sMaskReader, sMin]; FOR s: NAT IN [sMin..sMax) DO brickRow: PixelBuffer _ deviceBrick[sModPeriod]; brickPtr: LONG POINTER _ @(brickRow[fBrick]); brickRem: INTEGER _ brickRow.maxLength - 15 - fBrick; source.get[source, buffer, lineBits, 0, xStart, yStart, xDeltaPixel, yDeltaPixel]; WHILE sMaskReader.s = s DO fStart: NAT _ sMaskReader.fMin-fMin; DoLine[dst: [word: linePointer + sMaskReader.fMin/16, bit: sMaskReader.fMin MOD 16], count: sMaskReader.fMax-sMaskReader.fMin, sourcePtr: @(buffer[fStart]), brickPtr: brickPtr+fStart, brickRem: brickRem-fStart, brickPeriod: fPeriod]; ImagerMasksPrivate.Advance[@sMaskReader]; ENDLOOP; linePointer _ linePointer + raster; xStart _ xStart.PLUS[xDeltaLine]; yStart _ yStart.PLUS[yDeltaLine]; sModPeriod _ sModPeriod + 1; IF sModPeriod = sPeriod THEN { sModPeriod _ 0; sDivPeriod _ sDivPeriod + 1; fBrick _ fBrick + deviceBrick.phase; WHILE fBrick >= fPeriod DO fBrick _ fBrick - fPeriod ENDLOOP; }; ENDLOOP; }; }; MakeSquareBrick: PUBLIC PROC [size: NAT, p, q: INTEGER, pModulation, qModulation: REAL, maxPixelValue: CARDINAL] RETURNS [DeviceBrick] ~ { max: REAL _ ABS[pModulation]+ABS[qModulation]; min: REAL _ -max; Screen: PROC [x, y: REAL] RETURNS [fvalue: REAL] ~ { x0: REAL _ (x+1)/2.0; y0: REAL _ (y+1)/2.0; u: REAL _ p * x0 + q * y0; v: REAL _ -q * x0 + p * y0; fvalue _ (pModulation*RealFns.CosDeg[u*360] + qModulation*RealFns.CosDeg[v*360] - min)/(max-min); }; RETURN [MakeDeviceBrick[ImagerBrick.BuildBrick[size, 0, Screen], maxPixelValue]] }; DotScreen: PUBLIC PROC [x, y: REAL] RETURNS [fvalue: REAL] ~ { tx: REAL _ (x-1)*(x-1)*(x+1)*(x+1); ty: REAL _ (y-1)*(y-1)*(y+1)*(y+1); fvalue _ (tx+ty)/2; }; LineScreen: PUBLIC PROC [x, y:REAL] RETURNS [fvalue: REAL] ~ { fvalue _ (x-1)*(x-1)*(x+1)*(x+1); }; IF Environment.bitsPerWord # 16 THEN ERROR; END. RImagerHalftoneImpl.mesa Michael Plass, October 4, 1983 10:01 am Because of an apparent bug in Real.FScale. pointer into the threshold brick row. Each word is the negative of the minimum pixel value that should be displayed as white. number of words to the end of the brick row; the row must extend at least 15 words past the end. Ê­˜J™J™'JšÏk œ™˜¢šœ ˜!Jšœ]˜dJšœ˜Jšœœœ˜—š Ïnœœœœœ˜+Jšœœœ!˜?—š žœœœœœœ˜Jšœœ˜#Jšœœ˜#Jšœ˜Jšœ˜—š ž œœœœœ œ˜>Jšœ!˜!Jšœ˜—J˜Jšœœœ˜+Jšœ˜—…—¾(½