DIRECTORY Environment, ImagerBasic, ImagerBrick, ImagerMasks, ImagerMasksPrivate, Inline, Real, Scaled, ImagerTransform, ImagerHalftone, RealFns; ImagerHalftoneImpl: CEDAR PROGRAM IMPORTS ImagerBrick, ImagerTransform, ImagerMasks, ImagerMasksPrivate, Inline, Real, Scaled, RealFns EXPORTS ImagerHalftone ~ BEGIN OPEN ImagerHalftone; MaskRep: TYPE ~ ImagerMasks.MaskRep; 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 INLINE { 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: Mask, mask: Mask, source: PixelArray, transformation: Transformation, deviceBrick: DeviceBrick] ~ { WITH dest.refRep SELECT FROM b: REF MaskRep.bitmap => TRUSTED { sMask: Mask _ mask.InlineShift[-dest.sMin, -dest.fMin]; sMin: NAT _ MAX[sMask.sMin, 0]; sMax: NAT _ MIN[dest.sSize, b.lines, sMask.sMin + sMask.sSize]; fMin: NAT _ MAX[sMask.fMin, 0]; fMax: NAT _ MIN[dest.fSize, b.rast*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, 0.5+fMin+dest.fMin], 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 _ b.pointer + Inline.LongMult[sMin, b.rast]; sPeriod: CARDINAL _ deviceBrick.sPeriod; fPeriod: CARDINAL _ deviceBrick.fPeriod; sDivPeriod, sModPeriod: CARDINAL; fBrick: NAT; sMinBrick: INT _ sMin-(INT[deviceBrick.sMin]-(dest.sMin MOD sPeriod)); fMinBrick: INT _ fMin-(INT[deviceBrick.fMin]-(dest.fMin MOD fPeriod)); WHILE sMinBrick < 0 DO sMinBrick _ sMinBrick + sPeriod ENDLOOP; WHILE fMinBrick < 0 DO fMinBrick _ fMinBrick + fPeriod ENDLOOP; [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 + b.rast; 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 + b.rast; 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; }; }; ENDCASE => ERROR; }; 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. PImagerHalftoneImpl.mesa Michael Plass, July 25, 1983 4:05 pm Because of an apparent bug in Real.FScale. pointer into the threshold brick row. Each word is the negative of the minimum pixel value which 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šœœœ˜—Jšœ œ˜$š Ïnœœœœœ˜+Jšœœœ!˜?—š žœœœœœœ˜Jšœœ˜#Jšœœ˜#Jšœ˜Jšœ˜—š ž œœœœœ œ˜>Jšœ!˜!Jšœ˜—J˜Jšœœœ˜+Jšœ˜—…—f(„