<> <> 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.