<> <> <> DIRECTORY ImagerBrick, Inline USING [LongNumber, BITXOR], PriorityQueue USING [Ref, Item, Create, Insert, Remove, Empty], Real USING [RoundLI], RealFns USING [CosDeg, SinDeg]; ImagerBrickImpl: CEDAR PROGRAM IMPORTS Inline, Real, RealFns, PriorityQueue EXPORTS ImagerBrick = { OPEN ImagerBrick; QItem: TYPE = REF QItemRep; QItemRep: TYPE = RECORD [f, s: CARDINAL, val: REAL]; <> SortPred: PROC [x, y: PriorityQueue.Item, data: REF] RETURNS [BOOL] = { na: QItem _ NARROW[x]; nb: QItem _ NARROW[y]; RETURN[IF na.val=nb.val THEN RandomBool[NARROW[data]] ELSE na.val < nb.val] }; <> <> RandomHandle: TYPE = REF RandomRec; RandomRec: TYPE = RECORD [ <> w: INT _ -1978068312 ]; lowTap: INT = 10000000000B; highTap: INT = 100000000B; XorC: PROC [long: Inline.LongNumber] RETURNS [INT] = INLINE { long.lowbits _ Inline.BITXOR[long.lowbits, 514B]; RETURN[long.li]; }; RandomBool: PROC [r: RandomHandle] RETURNS [BOOLEAN] = { RETURN [0>(r.w _ IF r.w<0 THEN XorC[[li[r.w+r.w]]] ELSE r.w+r.w)] }; InitRandom: PROC [w: INT, n: INT] RETURNS [r: RandomHandle] = { r _ NEW[RandomRec _ [w]]; FOR i: INT IN [0..n) DO [] _ RandomBool[r] ENDLOOP; }; <> <> <> BuildBrick: PUBLIC PROC [freq: REAL, angle: REAL, filter: PROC [x, y:REAL] RETURNS [fvalue: REAL]] RETURNS [brick: Brick] = { tInt: INTEGER; --temporary u,v: REAL _ 0.0; --u/v is tangent[angle] iu, iv, iuvsqrd: INTEGER _0; -- closest integer values of u,v absiu, absiv: INTEGER _ 0; -- absolute values of iu,iv riu, riv, riuvsqrd: REAL _ 0.0; --real versions of iu, iv, etc. sSize, fSize: INTEGER _0; --dimensions of halftone brick, fSize wide and sSize high a,b,c,d: REAL _ 0.0; --elements of the transform matrix LIndex, pIndex: INTEGER _ 0; x, y: INTEGER _ 0; --for receiving results of ExtendedEuclid. reali, realj, realiPrime, realjPrime: REAL _ 0.0; <> <> u _ freq*RealFns.SinDeg[angle]; v _ freq*RealFns.CosDeg[angle]; iu _ Real.RoundLI[u];-- get nearest integer iv _ Real.RoundLI[v]; IF iu = 0 AND iv = 0 THEN iu _ 1;--appearance error <> absiv _ ABS[iv]; absiu _ ABS[iu]; IF iu*iv < 0 THEN { tInt _ absiv; absiv _ absiu; absiu _ tInt }; [x, y, sSize] _ ExtendedEuclid[absiu, absiv];--computes GCD of arguments plus phase value arguments iuvsqrd _ iu*iu + iv*iv; fSize _ iuvsqrd/sSize;--calculate length of brick <> <> <> <> <> <<>> <<[ 2 0 ] [ cos -sin] [ a b ]>> <<[ ] * [ ] = [ ]>> <<[ 0 2 ] [ sin cos] [ c d ]>> riu _ iu; riv _ iv; riuvsqrd _ iuvsqrd; d _ a _ 2*riv/riuvsqrd ; c _ 2*riu/riuvsqrd; b _ -c; -- -2*riu/riuvsqrd <> brick _ NEW[BrickRep[fSize*sSize] _ [fSize: fSize, sSize: sSize, phase: 0, u: absiu, v: absiv, cBrick: ]]; brick.phase _ (x*absiv - y*absiu) MOD fSize; <> { -- so we can do some more declarations item: QItem; lxp: NAT = fSize*sSize; sliceInterval: REAL = 1.0/lxp; currentSlice: REAL _ 0; pQ: PriorityQueue.Ref _ PriorityQueue.Create[SortPred, NEW[RandomRec]]; FOR LIndex IN [0..fSize) DO reali _ LIndex+0.5; FOR pIndex IN [0..sSize) DO realj _ pIndex+0.5; realiPrime _ RealMod[(reali*a + realj*c), 2.0] - 1.0; realjPrime _ RealMod[(reali*b + realj*d), 2.0] - 1.0; item _ NEW[QItemRep]; item^ _ [f: LIndex, s: pIndex, val: filter[realiPrime, realjPrime]]; pQ.Insert[item]; ENDLOOP; ENDLOOP; FOR i: NAT IN [0..lxp) DO item _ NARROW[pQ.Remove]; brick.cBrick[fSize*item.s + item.f] _ currentSlice; currentSlice _ currentSlice + sliceInterval; ENDLOOP; IF NOT pQ.Empty THEN ERROR; };--brick values };--BuildBrick ExtendedEuclid: PROC [u, v: INTEGER] RETURNS [u1, u2, u3: INTEGER] = { q, v1, v2, v3, t1, t2, t3: INTEGER; u1 _ 1; u2 _ 0; u3 _u; v1 _ 0; v2 _ 1; v3 _ v; DO IF (v3 = 0) THEN EXIT; q _ u3/v3; t1 _ u1-(v1*q); t2 _ u2-(v2*q); t3 _ u3-(v3*q); u1 _ v1; u2 _ v2; u3 _ v3; v1 _ t1; v2 _ t2; v3 _ t3; ENDLOOP; }; RealMod: PROC[a,b: REAL] RETURNS [REAL] = { RETURN[a - (FloorI[a/b])*b]};--RealMod FloorI: PROC[r: REAL] RETURNS [i: INT] = { i _ Real.RoundLI[r]; IF i>r THEN i_i-1; };--FloorI GetSize: PUBLIC PROC[brick: Brick] RETURNS [fSize, sSize: CARDINAL, phase: INTEGER] = { <> RETURN[brick.fSize, brick.sSize, brick.phase]; };--GetSize Modd: PROC[x, y: LONG INTEGER] RETURNS [LONG INTEGER] = { RETURN [IF x >= 0 THEN (x MOD y) ELSE ((y-1) + (x+1) MOD y)]; };--Modd GetElement: PUBLIC PROC[brick: Brick, x, y: CARDINAL] RETURNS [bElement: REAL] = { row, col: CARDINAL _ 0; row _ GetRow[brick,x,y]; col _ GetCol[brick,x,y]; RETURN [brick.cBrick[brick.fSize*row + col]]; };--GetElement GetRow: PUBLIC PROC[brick: Brick, x, y: CARDINAL] RETURNS [row: CARDINAL] = { RETURN [y MOD brick.sSize]; };--GetRow GetCol: PUBLIC PROC[brick: Brick, x, y: CARDINAL] RETURNS [col: CARDINAL] = { i: LONG INTEGER _ Modd[(x - LONG[brick.phase]*(y/brick.sSize)), brick.fSize]; RETURN [i]; };--GetCol }. --of CGBrickImpl LOG <> <> <> <> <> <> <> <> <> <>