DIRECTORY Environment, ImagerBasic, ImagerBrick, ImagerMasks, ImagerMasksPrivate, Inline, Real, Scaled, ImagerTransform, LFUtil, ImagerHalftone; ImagerHalftoneImpl: CEDAR PROGRAM IMPORTS ImagerBrick, ImagerTransform, ImagerMasks, ImagerMasksPrivate, Inline, Real, Scaled, LFUtil 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 + fMin/16 + Inline.LongMult[sMin, b.rast]; bitPointer: NAT _ fMin MOD 16; 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 { 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: [word: linePointer, bit: bitPointer], count: lineBits, sourcePtr: @(buffer[0]), brickPtr: brickPtr, brickRem: brickRem, brickPeriod: fPeriod]; 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; } 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; word: LONG POINTER _ linePointer + Shift[sMaskReader.fMin, -4]; bit: CARDINAL _ Inline.BITAND[sMaskReader.fMin, 15]; bit _ bit + bitPointer; WHILE bit >= 16 DO bit _ bit - 16; word _ word + 1; ENDLOOP; DoLine[dst: [word: word, bit: bit], 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; }; 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); }; testBrick: DeviceBrick _ MakeDeviceBrick[ImagerBrick.BuildBrick[3, 13, LineScreen], 255]; lf: Mask _ ImagerMasks.LFDisplay[]; pa: PixelArray; tran: Transformation _ [0, -1, 808, 1, 0, 0, hard]; Htest: PROC = { sMin, fMin: INTEGER; sSize, fSize: NAT; [sMin, fMin, sSize, fSize] _ LFUtil.GetArea[]; Halftone[lf, ImagerMasks.Box[sMin, fMin, sSize, fSize], pa, tran, testBrick]; }; IF Environment.bitsPerWord # 16 THEN ERROR; END. PImagerHalftoneImpl.mesa Michael Plass, July 12, 1983 4:06 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šœ\˜cJšœ˜Jšœœœ˜—Jšœ œ˜$š Ïnœœœœœ˜+Jšœœœ!˜?—š žœœœœœœ˜Jšœœ˜#Jšœœ˜#Jšœ˜Jšœ˜—š ž œœœœœ œ˜>Jšœ!˜!Jšœ˜—J˜J˜YJ˜#J˜Jšœ3˜3šžœœ˜Jšœ œ˜'Jšœ.˜.JšœM˜MJšœ˜—J˜Jšœœœ˜+Jšœ˜—…—@(@