DIRECTORY Basics, ImagerSample, ImagerTransformation, PrincOps, PrincOpsUtils, Real; ImagerSampleImpl: CEDAR MONITOR IMPORTS Basics, ImagerSample, ImagerTransformation, PrincOpsUtils, Real EXPORTS ImagerSample ~ BEGIN OPEN ImagerSample; assertSampleSizeMatchesWordSize: BOOL[TRUE..TRUE] ~ SIZE[Sample]=SIZE[WORD]; bitsPerWord: NAT ~ Basics.bitsPerWord; lgBitsPerWord: NAT ~ Basics.logBitsPerWord; NewBuffer: PUBLIC PROC [iSize, jSize: NAT, scratch: SampleBuffer _ NIL] RETURNS [SampleBuffer] ~ { size: NAT ~ Basics.LongMult[iSize, jSize]; new: SampleBuffer _ scratch; IF new=NIL OR new.size NULL; size: NAT ~ Basics.LongMult[iSize, jSize]; FOR i: NAT DECREASING IN [0..nScratchAvail) DO IF scratch[i].size >= size THEN { buffer _ scratch[i]; IF i # nScratchAvail-1 THEN scratch[i] _ scratch[nScratchAvail-1]; nScratchAvail _ nScratchAvail - 1; scratch[nScratchAvail] _ NIL; EXIT; }; ENDLOOP; buffer _ NewBuffer[iSize: iSize, jSize: jSize, scratch: buffer]; }; ReleaseScratchBuffer: PUBLIC ENTRY PROC [buffer: SampleBuffer] ~ { IF nScratchAvail < nScratchSlots THEN { scratch[nScratchAvail] _ buffer; nScratchAvail _ nScratchAvail + 1; } ELSE { scratch[rover] _ buffer; rover _ (rover + 1) MOD nScratchSlots; }; }; DoWithScratchBuffer: PUBLIC PROC [iSize, jSize: NAT, action: PROC [SampleBuffer]] ~ { buffer: SampleBuffer ~ ObtainScratchBuffer[iSize, jSize]; action[buffer ! UNWIND => ReleaseScratchBuffer[buffer]]; ReleaseScratchBuffer[buffer]; }; GetSample: PUBLIC PROC [buffer: SampleBuffer, i, j: NAT] RETURNS [Sample] ~ { k: NAT ~ Basics.BoundsCheck[i, buffer.iSize]*buffer.jSize+Basics.BoundsCheck[j, buffer.jSize]; RETURN[buffer[k]]; }; PutSample: PUBLIC PROC [buffer: SampleBuffer, i, j: NAT, sample: Sample] ~ { k: NAT ~ Basics.BoundsCheck[i, buffer.iSize]*buffer.jSize+Basics.BoundsCheck[j, buffer.jSize]; buffer[k] _ sample; }; GetPointer: PUBLIC PROC [buffer: SampleBuffer, i, j, count: NAT] RETURNS [UnsafeSamples] ~ { k: NAT ~ Basics.BoundsCheck[i, buffer.iSize]*buffer.jSize+Basics.BoundsCheck[j, buffer.jSize]; IF count#0 THEN [] _ Basics.BoundsCheck[j+count-1, buffer.jSize]; TRUSTED { RETURN[LOOPHOLE[@buffer[k]]] }; }; UnsafeAdd: PUBLIC UNSAFE PROC [src1, src2, dst: UnsafeSamples, count: NAT] ~ UNCHECKED { THROUGH [0..count/8) DO dst[0] _ src1[0]+src2[0]; dst[1] _ src1[1]+src2[1]; dst[2] _ src1[2]+src2[2]; dst[3] _ src1[3]+src2[3]; dst[4] _ src1[4]+src2[4]; dst[5] _ src1[5]+src2[5]; dst[6] _ src1[6]+src2[6]; dst[7] _ src1[7]+src2[7]; src1 _ src1+8; src2 _ src2+8; dst _ dst+8; ENDLOOP; FOR k: NAT IN[0..count MOD 8) DO dst[k] _ src1[k]+src2[k] ENDLOOP; }; UnsafeSub: PUBLIC UNSAFE PROC [src1, src2, dst: UnsafeSamples, count: NAT] ~ UNCHECKED { THROUGH [0..count/8) DO dst[0] _ src1[0]-src2[0]; dst[1] _ src1[1]-src2[1]; dst[2] _ src1[2]-src2[2]; dst[3] _ src1[3]-src2[3]; dst[4] _ src1[4]-src2[4]; dst[5] _ src1[5]-src2[5]; dst[6] _ src1[6]-src2[6]; dst[7] _ src1[7]-src2[7]; src1 _ src1+8; src2 _ src2+8; dst _ dst+8; ENDLOOP; FOR k: NAT IN[0..count MOD 8) DO dst[k] _ src1[k]-src2[k] ENDLOOP; }; UnsafeLookup: PUBLIC UNSAFE PROC [tbl, src, dst: UnsafeSamples, count: NAT] ~ UNCHECKED { THROUGH [0..count/8) DO dst[0] _ tbl[src[0]]; dst[1] _ tbl[src[1]]; dst[2] _ tbl[src[2]]; dst[3] _ tbl[src[3]]; dst[4] _ tbl[src[4]]; dst[5] _ tbl[src[5]]; dst[6] _ tbl[src[6]]; dst[7] _ tbl[src[7]]; src _ src+8; dst _ dst+8; ENDLOOP; FOR k: NAT IN[0..count) DO dst[k] _ tbl[src[k]] ENDLOOP; }; AddSamples: PUBLIC PROC [samples: SampleBuffer, si, sj: NAT _ 0, buffer: SampleBuffer, bi, bj: NAT _ 0, count: NAT] ~ { src: UnsafeSamples ~ GetPointer[samples, si, sj, count]; dst: UnsafeSamples ~ GetPointer[buffer, bi, bj, count]; TRUSTED { UnsafeAdd[src1: dst, src2: src, dst: dst, count: count] }; }; SubSamples: PUBLIC PROC [samples: SampleBuffer, si, sj: NAT _ 0, buffer: SampleBuffer, bi, bj: NAT _ 0, count: NAT] ~ { src: UnsafeSamples ~ GetPointer[samples, si, sj, count]; dst: UnsafeSamples ~ GetPointer[buffer, bi, bj, count]; TRUSTED { UnsafeSub[src1: dst, src2: src, dst: dst, count: count] }; }; LookupSamples: PUBLIC PROC [table: SampleBuffer, samples: SampleBuffer, si, sj: NAT _ 0, buffer: SampleBuffer, bi, bj: NAT _ 0, count: NAT] ~ { tbl: UnsafeSamples ~ GetPointer[table, 0, 0, 0]; src: UnsafeSamples ~ GetPointer[samples, si, sj, count]; dst: UnsafeSamples ~ GetPointer[buffer, bi, bj, count]; TRUSTED { FOR k: NAT IN[0..count) DO dst[k] _ table[src[k]] ENDLOOP }; }; LookupPixels: PUBLIC PROC [tables: SampleBuffer, pixels: SampleBuffer, pj: NAT _ 0, buffer: SampleBuffer, bi, bj: NAT _ 0, count: NAT] ~ { dst: UnsafeSamples ~ GetPointer[buffer, bi, bj, count]; SELECT tables.iSize FROM 0 => NULL; 1 => { tbl0: UnsafeSamples ~ GetPointer[tables, 0, 0, 0]; src0: UnsafeSamples ~ GetPointer[pixels, 0, pj, count]; TRUSTED { FOR k: NAT IN[0..count) DO dst[k] _ tbl0[src0[k]] ENDLOOP }; }; 2 => { tbl0: UnsafeSamples ~ GetPointer[tables, 0, 0, 0]; tbl1: UnsafeSamples ~ GetPointer[tables, 1, 0, 0]; src0: UnsafeSamples ~ GetPointer[pixels, 0, pj, count]; src1: UnsafeSamples ~ GetPointer[pixels, 1, pj, count]; TRUSTED { FOR k: NAT IN[0..count) DO dst[k] _ tbl0[src0[k]]+tbl1[src1[k]] ENDLOOP }; }; 3 => { tbl0: UnsafeSamples ~ GetPointer[tables, 0, 0, 0]; tbl1: UnsafeSamples ~ GetPointer[tables, 1, 0, 0]; tbl2: UnsafeSamples ~ GetPointer[tables, 2, 0, 0]; src0: UnsafeSamples ~ GetPointer[pixels, 0, pj, count]; src1: UnsafeSamples ~ GetPointer[pixels, 1, pj, count]; src2: UnsafeSamples ~ GetPointer[pixels, 2, pj, count]; TRUSTED { FOR k: NAT IN[0..count) DO dst[k] _ tbl0[src0[k]]+tbl1[src1[k]]+tbl2[src2[k]] ENDLOOP }; }; ENDCASE => FOR k: NAT IN[0..count) DO sum: Sample _ 0; FOR i: NAT IN[0..tables.iSize) DO sum _ sum+tables.GetSample[i, pixels.GetSample[i, pj+k]]; ENDLOOP; buffer.PutSample[bi, bj+k, sum]; ENDLOOP; }; LgEntry: TYPE ~ RECORD[powerOfTwo: BOOL, lg: NAT _ 0]; LgArray: TYPE ~ ARRAY BitsPerSample OF LgEntry; lgArray: REF LgArray ~ InitLgArray[]; InitLgArray: PROC RETURNS [REF LgArray] ~ { lgArray: REF LgArray ~ NEW[LgArray _ ALL[[powerOfTwo: FALSE]]]; FOR lg: NAT IN[0..lgBitsPerWord] DO lgArray[Basics.BITSHIFT[1, lg]] _ [powerOfTwo: TRUE, lg: lg]; ENDLOOP; RETURN[lgArray]; }; nullBitBltTable: PrincOps.BitBltTable ~ [ dst: [word: NIL, bit: 0], dstBpl: 0, src: [word: NIL, bit: 0], srcDesc: [srcBpl[0]], width: 0, height: 0, flags: [] ]; UnsafeGetF: PUBLIC UNSAFE PROC [samples: UnsafeSamples, count: NAT, s, f: NAT _ 0, base: LONG POINTER, wordsPerLine: NAT, bitsPerSample: BitsPerSample] ~ UNCHECKED { lgEntry: LgEntry ~ lgArray[bitsPerSample]; line: LONG POINTER ~ base+Basics.LongMult[s, wordsPerLine]; bbTableSpace: PrincOps.BBTableSpace; bb: PrincOps.BBptr ~ PrincOpsUtils.AlignedBBTable[@bbTableSpace]; bb^ _ nullBitBltTable; bb.flags _ [disjoint: TRUE, gray: FALSE]; PrincOpsUtils.LongZero[where: samples, nwords: count]; IF lgEntry.powerOfTwo THEN { lgBitsPerItem: NAT ~ lgEntry.lg; bitsPerItem: NAT ~ Basics.BITSHIFT[1, lgBitsPerItem]; lgItemsPerWord: NAT ~ lgBitsPerWord-lgBitsPerItem; itemsPerWord: NAT ~ Basics.BITSHIFT[1, lgItemsPerWord]; bb.dst.bit _ bitsPerWord-bitsPerItem; bb.dstBpl _ Basics.BITSHIFT[bitsPerWord, lgItemsPerWord]; bb.srcDesc.srcBpl _ bitsPerWord; bb.width _ bitsPerItem; FOR k: NAT IN [0..MIN[itemsPerWord, count]) DO x: CARDINAL ~ f+k; bb.dst.word _ @samples[k]; bb.src.word _ line+Basics.BITSHIFT[x, -lgItemsPerWord]; bb.src.bit _ Basics.BITSHIFT[Basics.BITAND[x, itemsPerWord-1], lgBitsPerItem]; bb.height _ Basics.BITSHIFT[(count-k)+(itemsPerWord-1), -lgItemsPerWord]; PrincOpsUtils.BITBLT[bb]; ENDLOOP; } ELSE { bit: LONG CARDINAL ~ Basics.LongMult[f, bitsPerSample]; bb.dst.word _ samples; bb.dst.bit _ bitsPerWord-bitsPerSample; bb.dstBpl _ bitsPerWord; bb.src.word _ line+bit/bitsPerWord; bb.src.bit _ bit MOD bitsPerWord; bb.srcDesc.srcBpl _ bitsPerSample; bb.width _ bitsPerSample; bb.height _ count; PrincOpsUtils.BITBLT[bb]; }; }; UnsafePutF: PUBLIC UNSAFE PROC [samples: UnsafeSamples, count: NAT, s, f: NAT _ 0, base: LONG POINTER, wordsPerLine: NAT, bitsPerSample: BitsPerSample, srcFunc: PrincOps.SrcFunc _ null, dstFunc: PrincOps.DstFunc _ null] ~ UNCHECKED { lgEntry: LgEntry ~ lgArray[bitsPerSample]; line: LONG POINTER ~ base+Basics.LongMult[s, wordsPerLine]; bbTableSpace: PrincOps.BBTableSpace; bb: PrincOps.BBptr ~ PrincOpsUtils.AlignedBBTable[@bbTableSpace]; bb^ _ nullBitBltTable; bb.flags _ [disjoint: TRUE, gray: FALSE, srcFunc: srcFunc, dstFunc: dstFunc]; IF lgEntry.powerOfTwo THEN { lgBitsPerItem: NAT ~ lgEntry.lg; bitsPerItem: NAT ~ Basics.BITSHIFT[1, lgBitsPerItem]; lgItemsPerWord: NAT ~ lgBitsPerWord-lgBitsPerItem; itemsPerWord: NAT ~ Basics.BITSHIFT[1, lgItemsPerWord]; bb.src.bit _ bitsPerWord-bitsPerItem; bb.srcDesc.srcBpl _ Basics.BITSHIFT[bitsPerWord, lgItemsPerWord]; bb.dstBpl _ bitsPerWord; bb.width _ bitsPerItem; FOR k: NAT IN [0..MIN[itemsPerWord, count]) DO x: CARDINAL ~ f+k; bb.src.word _ @samples[k]; bb.dst.word _ line+Basics.BITSHIFT[x, -lgItemsPerWord]; bb.dst.bit _ Basics.BITSHIFT[Basics.BITAND[x, itemsPerWord-1], lgBitsPerItem]; bb.height _ Basics.BITSHIFT[(count-k)+(itemsPerWord-1), -lgItemsPerWord]; PrincOpsUtils.BITBLT[bb]; ENDLOOP; } ELSE { bit: LONG CARDINAL ~ Basics.LongMult[f, bitsPerSample]; bb.src.word _ samples; bb.src.bit _ bitsPerWord-bitsPerSample; bb.srcDesc.srcBpl _ bitsPerWord; bb.dst.word _ line+bit/bitsPerWord; bb.dst.bit _ bit MOD bitsPerWord; bb.dstBpl _ bitsPerSample; bb.width _ bitsPerSample; bb.height _ count; PrincOpsUtils.BITBLT[bb]; }; }; UnsafePutFSign: PUBLIC UNSAFE PROC [samples: UnsafeSamples, count: NAT, s, f: NAT _ 0, base: LONG POINTER, wordsPerLine: NAT] ~ UNCHECKED { line: LONG POINTER ~ base+Basics.LongMult[s, wordsPerLine]; bbTableSpace: PrincOps.BBTableSpace; bb: PrincOps.BBptr ~ PrincOpsUtils.AlignedBBTable[@bbTableSpace]; bb^ _ nullBitBltTable; bb.flags _ [disjoint: TRUE, gray: FALSE]; bb.srcDesc.srcBpl _ bitsPerWord*bitsPerWord; bb.dstBpl _ bitsPerWord; bb.width _ 1; FOR k: NAT IN [0..MIN[bitsPerWord, count]) DO x: CARDINAL ~ f+k; bb.src.word _ @samples[k]; bb.dst.word _ line+x/bitsPerWord; bb.dst.bit _ x MOD bitsPerWord; bb.height _ (CARDINAL[count-k]+bitsPerWord-1)/bitsPerWord; PrincOpsUtils.BITBLT[bb]; ENDLOOP; }; UnsafeGetS: PUBLIC UNSAFE PROC [samples: UnsafeSamples, count: NAT, s, f: NAT _ 0, base: LONG POINTER, wordsPerLine: NAT, bitsPerSample: BitsPerSample] ~ UNCHECKED { lgEntry: LgEntry ~ lgArray[bitsPerSample]; bbTableSpace: PrincOps.BBTableSpace; bb: PrincOps.BBptr ~ PrincOpsUtils.AlignedBBTable[@bbTableSpace]; bb^ _ nullBitBltTable; bb.flags _ [disjoint: TRUE, gray: FALSE]; PrincOpsUtils.LongZero[where: samples, nwords: count]; bb.dst.word _ samples; bb.dst.bit _ bitsPerWord-bitsPerSample; bb.dstBpl _ bitsPerWord; bb.srcDesc.srcBpl _ wordsPerLine*bitsPerWord; bb.width _ bitsPerSample; bb.height _ count; IF lgEntry.powerOfTwo THEN { lgBitsPerItem: NAT ~ lgEntry.lg; lgItemsPerWord: NAT ~ lgBitsPerWord-lgBitsPerItem; itemsPerWord: NAT ~ Basics.BITSHIFT[1, lgItemsPerWord]; bb.src.word _ base+Basics.LongMult[s, wordsPerLine]+Basics.BITSHIFT[f, -lgItemsPerWord]; bb.src.bit _ Basics.BITSHIFT[Basics.BITAND[f, itemsPerWord-1], lgBitsPerItem]; PrincOpsUtils.BITBLT[bb]; } ELSE { x: LONG CARDINAL ~ Basics.LongMult[bitsPerSample, f]; bb.src.word _ base+Basics.LongMult[wordsPerLine, s]+x/bitsPerWord; bb.src.bit _ x MOD bitsPerWord; PrincOpsUtils.BITBLT[bb]; }; }; UnsafePutS: PUBLIC UNSAFE PROC [samples: UnsafeSamples, count: NAT, s, f: NAT _ 0, base: LONG POINTER, wordsPerLine: NAT, bitsPerSample: BitsPerSample, srcFunc: PrincOps.SrcFunc _ null, dstFunc: PrincOps.DstFunc _ null] ~ UNCHECKED { lgEntry: LgEntry ~ lgArray[bitsPerSample]; bbTableSpace: PrincOps.BBTableSpace; bb: PrincOps.BBptr ~ PrincOpsUtils.AlignedBBTable[@bbTableSpace]; bb^ _ nullBitBltTable; bb.flags _ [disjoint: TRUE, gray: FALSE, srcFunc: srcFunc, dstFunc: dstFunc]; bb.dstBpl _ wordsPerLine*bitsPerWord; bb.src.word _ samples; bb.src.bit _ bitsPerWord-bitsPerSample; bb.srcDesc.srcBpl _ bitsPerWord; bb.width _ bitsPerSample; bb.height _ count; IF lgEntry.powerOfTwo THEN { lgBitsPerItem: NAT ~ lgEntry.lg; lgItemsPerWord: NAT ~ lgBitsPerWord-lgBitsPerItem; itemsPerWord: NAT ~ Basics.BITSHIFT[1, lgItemsPerWord]; bb.dst.word _ base+Basics.LongMult[s, wordsPerLine]+Basics.BITSHIFT[f, -lgItemsPerWord]; bb.dst.bit _ Basics.BITSHIFT[Basics.BITAND[f, itemsPerWord-1], lgBitsPerItem]; PrincOpsUtils.BITBLT[bb]; } ELSE { x: LONG CARDINAL ~ Basics.LongMult[bitsPerSample, f]; bb.dst.word _ base+Basics.LongMult[wordsPerLine, s]+x/bitsPerWord; bb.dst.bit _ x MOD bitsPerWord; PrincOpsUtils.BITBLT[bb]; }; }; realLastInt: REAL _ REAL[LAST[INT]]; Floor: PROC[a: REAL] RETURNS[c: REAL] ~ { IF ABS[a] >= realLastInt THEN RETURN [a]; c _ REAL[Real.Fix[a]]; IF c>a THEN RETURN[c-1] ELSE RETURN[c] }; ScaledFromRealMod: PROC [d: REAL, m: CARDINAL] RETURNS [INT] ~ { s: Basics.LongNumber _ [li[0]]; IF m # 0 THEN { modulus: REAL ~ m; residue: REAL _ IF d IN [0..modulus) THEN d ELSE (d-modulus*Floor[d/modulus]); s.li _ Real.Round[Real.FScale[residue, Basics.bitsPerWord]]; IF s.li < 0 THEN {s.hi _ s.hi + m}; IF s.hi >= m THEN {s.hi _ s.hi - m}; IF s.hi >= m THEN ERROR; }; RETURN [s.li]; }; SetSamplerIncrements: PUBLIC PROC [sampler: Sampler, m: Transformation] ~ { sSize: NAT ~ sampler.sSize; fSize: NAT ~ sampler.fSize; s, f: REAL _ 0.0; [[s, f]] _ m.InverseTransformVec[[0, 1] ! Real.RealException => CONTINUE]; sampler.sfDelta.li _ ScaledFromRealMod[s, sSize]; sampler.ffDelta.li _ ScaledFromRealMod[f, fSize]; s _ f _ 0.0; [[s, f]] _ m.InverseTransformVec[[1, 0] ! Real.RealException => CONTINUE]; sampler.ssDelta.li _ ScaledFromRealMod[s, sSize]; sampler.fsDelta.li _ ScaledFromRealMod[f, fSize]; }; SetSamplerPosition: PUBLIC PROC [sampler: Sampler, m: Transformation, s, f: CARDINAL] ~ { sSource, fSource: REAL _ 0.0; sSize: NAT ~ sampler.sSize; fSize: NAT ~ sampler.fSize; [[sSource, fSource]] _ m.InverseTransform[[s+0.5, f+0.5] ! Real.RealException => CONTINUE]; sampler.sSource.li _ ScaledFromRealMod[sSource, sSize]; sampler.fSource.li _ ScaledFromRealMod[fSource, fSize]; sampler.sDest _ s; sampler.fDest _ f; }; Sample0: TYPE ~ CARDINAL[0..000001B]; -- 1 bit Sample1: TYPE ~ CARDINAL[0..000003B]; -- 2 bits Sample2: TYPE ~ CARDINAL[0..000017B]; -- 4 bits Sample3: TYPE ~ CARDINAL[0..000377B]; -- 8 bits Sample4: TYPE ~ CARDINAL[0..177777B]; -- 16 bits Sequence0: TYPE ~ RECORD[PACKED SEQUENCE COMPUTED CARDINAL OF Sample0]; Sequence1: TYPE ~ RECORD[PACKED SEQUENCE COMPUTED CARDINAL OF Sample1]; Sequence2: TYPE ~ RECORD[PACKED SEQUENCE COMPUTED CARDINAL OF Sample2]; Sequence3: TYPE ~ RECORD[PACKED SEQUENCE COMPUTED CARDINAL OF Sample3]; Sequence4: TYPE ~ RECORD[PACKED SEQUENCE COMPUTED CARDINAL OF Sample4]; Pointer0: TYPE ~ LONG POINTER TO Sequence0; Pointer1: TYPE ~ LONG POINTER TO Sequence1; Pointer2: TYPE ~ LONG POINTER TO Sequence2; Pointer3: TYPE ~ LONG POINTER TO Sequence3; Pointer4: TYPE ~ LONG POINTER TO Sequence4; GetPointSamples: PUBLIC PROC [sampler: Sampler, s, f: CARDINAL, buffer: SampleBuffer, bi, bj: NAT _ 0, count: NAT] ~ TRUSTED { lgEntry: LgEntry ~ lgArray[sampler.bitsPerSample]; samples: UnsafeSamples ~ buffer.GetPointer[bi, bj, count]; base: LONG POINTER ~ sampler.base; wordsPerLine: CARDINAL ~ sampler.wordsPerLine; line: LONG POINTER _ base; sLine: CARDINAL _ 0; sSize: CARDINAL ~ sampler.sSize; fSize: CARDINAL ~ sampler.fSize; sMin: CARDINAL ~ sampler.sMin; fMin: CARDINAL ~ sampler.fMin; sMax: CARDINAL ~ sMin+sSize; fMax: CARDINAL ~ fMin+fSize; ssDelta: Basics.LongNumber ~ sampler.ssDelta; fsDelta: Basics.LongNumber ~ sampler.fsDelta; sfDelta: Basics.LongNumber ~ sampler.sfDelta; ffDelta: Basics.LongNumber ~ sampler.ffDelta; sSource: Basics.LongNumber _ sampler.sSource; fSource: Basics.LongNumber _ sampler.fSource; sDest: CARDINAL _ sampler.sDest; fDest: CARDINAL _ sampler.fDest; WHILE sDest FOR k: NAT IN[0..count) DO IF sLine#sSource.hi THEN line _ base+Basics.LongMult[sLine _ sSource.hi, wordsPerLine]; samples[k] _ LOOPHOLE[line, Pointer0][fSource.hi]; sSource.lc _ sSource.lc+sfDelta.lc; fSource.lc _ fSource.lc+ffDelta.lc; IF NOT sSource.hi FOR k: NAT IN[0..count) DO IF sLine#sSource.hi THEN line _ base+Basics.LongMult[sLine _ sSource.hi, wordsPerLine]; samples[k] _ LOOPHOLE[line, Pointer1][fSource.hi]; sSource.lc _ sSource.lc+sfDelta.lc; fSource.lc _ fSource.lc+ffDelta.lc; IF NOT sSource.hi FOR k: NAT IN[0..count) DO IF sLine#sSource.hi THEN line _ base+Basics.LongMult[sLine _ sSource.hi, wordsPerLine]; samples[k] _ LOOPHOLE[line, Pointer2][fSource.hi]; sSource.lc _ sSource.lc+sfDelta.lc; fSource.lc _ fSource.lc+ffDelta.lc; IF NOT sSource.hi FOR k: NAT IN[0..count) DO IF sLine#sSource.hi THEN line _ base+Basics.LongMult[sLine _ sSource.hi, wordsPerLine]; samples[k] _ LOOPHOLE[line, Pointer3][fSource.hi]; sSource.lc _ sSource.lc+sfDelta.lc; fSource.lc _ fSource.lc+ffDelta.lc; IF NOT sSource.hi FOR k: NAT IN[0..count) DO IF sLine#sSource.hi THEN line _ base+Basics.LongMult[sLine _ sSource.hi, wordsPerLine]; samples[k] _ LOOPHOLE[line, Pointer4][fSource.hi]; sSource.lc _ sSource.lc+sfDelta.lc; fSource.lc _ fSource.lc+ffDelta.lc; IF NOT sSource.hi ERROR ELSE ERROR; }; Hi: PROC [a: CARDINAL] RETURNS [CARDINAL] ~ INLINE {RETURN[Basics.BITSHIFT[a, 1-bitsPerWord]]}; Shift: PROC [a: CARDINAL, amt: INTEGER] RETURNS [CARDINAL] ~ INLINE {RETURN[Basics.BITSHIFT[a, amt]]}; SixteenWords: TYPE ~ MACHINE DEPENDENT RECORD [ w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15: CARDINAL ]; UnsafeHalftone: PUBLIC UNSAFE PROC [ samples, thresholds: UnsafeSamples, count: NAT, base: LONG POINTER, wordsPerLine: NAT, s, f: NAT _ 0, invertOutput: BOOL _ FALSE, transparent: BOOL _ FALSE ] ~ UNCHECKED { linePointer: LONG POINTER ~ base+Basics.LongMult[s, wordsPerLine]; bitOffset: CARDINAL ~ f; p: LONG POINTER TO SixteenWords _ LOOPHOLE[@samples[0]]; q: LONG POINTER TO SixteenWords _ LOOPHOLE[@thresholds[0]]; allInvert: CARDINAL _ IF invertOutput THEN LAST[CARDINAL] ELSE 0; GetN: UNSAFE PROC [n: [0..16)] RETURNS [CARDINAL] ~ UNCHECKED { w: CARDINAL _ 0; THROUGH [0..n) DO w _ w*2 + Hi[p^.w0-q^.w0]; p _ p + 1; q _ q + 1; ENDLOOP; RETURN [Basics.BITXOR[w, Basics.BITSHIFT[allInvert, n-16]]]; }; -- GetFirst Get16: UNSAFE PROC RETURNS [CARDINAL] ~ UNCHECKED { s, h: SixteenWords; s _ p^; p _ p + SIZE[SixteenWords]; h _ q^; q _ q + SIZE[SixteenWords]; RETURN [Basics.BITXOR[allInvert, ((((((((((((((Hi[s.w0-h.w0]*2+Hi[s.w1-h.w1])*2+Hi[s.w2-h.w2])*2+Hi[s.w3-h.w3])*2+Hi[s.w4-h.w4])*2+Hi[s.w5-h.w5])*2+Hi[s.w6-h.w6])*2+Hi[s.w7-h.w7])*2+Hi[s.w8-h.w8])*2+Hi[s.w9-h.w9])*2+Hi[s.w10-h.w10])*2+Hi[s.w11-h.w11])*2+Hi[s.w12-h.w12])*2+Hi[s.w13-h.w13])*2+Hi[s.w14-h.w14])*2+Hi[s.w15-h.w15]]] }; -- Get16 d: LONG POINTER TO CARDINAL _ LOOPHOLE[linePointer + bitOffset/16]; IF transparent THEN { IF bitOffset MOD 16 # 0 THEN { firstBits: INTEGER _ 16-(bitOffset MOD 16); z: INTEGER _ MAX[firstBits-INTEGER[count], 0]; d^ _ Basics.BITOR[d^, Shift[GetN[firstBits-z], z]]; d _ d + 1; count _ count - (firstBits-z); }; WHILE count >= 16 DO d^ _ Basics.BITOR[d^, Get16[]]; d _ d + 1; count _ count - 16; ENDLOOP; IF count > 0 THEN { d^ _ Basics.BITOR[d^, Shift[GetN[count], 16-count]]; }; } ELSE { IF bitOffset MOD 16 # 0 THEN { firstBits: INTEGER _ 16-(bitOffset MOD 16); z: INTEGER _ MAX[firstBits-INTEGER[count], 0]; m: CARDINAL _ Shift[1, firstBits] - Shift[1, z]; d^ _ Basics.BITOR[Basics.BITAND[d^, Basics.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^ _ Basics.BITOR[Basics.BITAND[d^, Shift[1, 16-count]-1], Shift[GetN[count], 16-count]]; }; }; }; END. "ImagerSampleImpl.mesa Copyright c 1984, 1985 by Xerox Corporation. All rights reserved. Michael Plass, September 20, 1985 12:12:46 pm PDT Doug Wyatt, May 28, 1985 7:04:18 pm PDT bb.src.word _ line+x/itemsPerWord; bb.src.bit _ (x MOD itemsPerWord)*bitsPerItem; bb.height _ Ceiling[(count-k)/itemsPerWord]; bb.dst.word _ line+x/itemsPerWord; bb.dst.bit _ (x MOD itemsPerWord)*bitsPerItem; bb.height _ Ceiling[(count-k)/itemsPerWord]; bb.src.word _ base+s*wordsPerLine+f/itemsPerWord; bb.src.bit _ (f MOD itemsPerWord)*bitsPerItem; bb.dst.word _ base+s*wordsPerLine+f/itemsPerWord; bb.dst.bit _ (f MOD itemsPerWord)*bitsPerItem; Now some paranoia about floating-point fuzz A singular transformation means the image can't be shown anyway. GetInterpolatedSamples: PUBLIC PROC [sampler: Sampler, sDest, fDest: CARDINAL, samples: Samples, startIndex: NAT _ 0, count: NAT] ~ TRUSTED { lgEntry: LgEntry ~ lgArray[sampler.bitsPerSample]; base: LONG POINTER ~ sampler.base; wordsPerLine: CARDINAL ~ sampler.wordsPerLine; line: LONG POINTER _ base; sLine: CARDINAL _ 0; sSize: CARDINAL ~ sampler.sSize; fSize: CARDINAL ~ sampler.fSize; sfDelta: Basics.LongNumber ~ sampler.sfDelta; ffDelta: Basics.LongNumber ~ sampler.ffDelta; sSource: Basics.LongNumber _ sampler.sSource0; fSource: Basics.LongNumber _ sampler.fSource0; sDest0: CARDINAL _ sampler.sDest; fDest0: CARDINAL _ sampler.fDest0; IF sDest0=sDest THEN { sSource _ sampler.sSource1; fSource _ sampler.fSource1; fDest0 _ sampler.fDest1; } ELSE { ssDelta: Basics.LongNumber ~ sampler.ssDelta; fsDelta: Basics.LongNumber ~ sampler.fsDelta; WHILE sDest0 { p: LONG POINTER TO RECORD[PACKED SEQUENCE COMPUTED CARDINAL OF [0..2)] _ LOOPHOLE[base + lineOffset]; v00 _ p[k]; v01 _ p[k + 1]; p _ p + wordsPerLine; v10 _ p[k]; v11 _ p[k + 1]; }; 1 => { p: LONG POINTER TO RECORD[PACKED SEQUENCE COMPUTED CARDINAL OF [0..4)] _ LOOPHOLE[base + lineOffset]; v00 _ p[k]; v01 _ p[k + 1]; p _ p + wordsPerLine; v10 _ p[k]; v11 _ p[k + 1]; }; 2 => { p: LONG POINTER TO RECORD[PACKED SEQUENCE COMPUTED CARDINAL OF [0..16)] _ LOOPHOLE[base + lineOffset]; v00 _ p[k]; v01 _ p[k + 1]; p _ p + wordsPerLine; v10 _ p[k]; v11 _ p[k + 1]; }; 3 => { p: LONG POINTER TO RECORD[PACKED SEQUENCE COMPUTED CARDINAL OF [0..256)] _ LOOPHOLE[base + lineOffset]; v00 _ p[k]; v01 _ p[k + 1]; p _ p + wordsPerLine; v10 _ p[k]; v11 _ p[k + 1]; }; 4 => { p: LONG POINTER TO RECORD[PACKED SEQUENCE COMPUTED CARDINAL OF CARDINAL] _ LOOPHOLE[base + lineOffset]; v00 _ p[k]; v01 _ p[k + 1]; p _ p + wordsPerLine; v10 _ p[k]; v11 _ p[k + 1]; }; ENDCASE => ERROR; IF multiplier # 1 OR lgScale # 0 THEN { v00 _ Basics.BITSHIFT[v00*multiplier, lgScale]; v01 _ Basics.BITSHIFT[v01*multiplier, lgScale]; v10 _ Basics.BITSHIFT[v10*multiplier, lgScale]; v11 _ Basics.BITSHIFT[v11*multiplier, lgScale]; }; pixelSeq[j] _ IF a=0 AND b=0 THEN v00 ELSE Basics.HighHalf[ Basics.LongMult[CARDINAL.LAST-a+ab-b+1, v00] + Basics.LongMult[b-ab, v01] + Basics.LongMult[a-ab, v10] + Basics.LongMult[ab, v11] ]; ss _ LOOPHOLE[LOOPHOLE[ss, INT]+LOOPHOLE[sDelta, INT]]; ff _ LOOPHOLE[LOOPHOLE[ff, INT]+LOOPHOLE[fDelta, INT]]; lineOffset _ lineOffset + normalDelta; ssFloor _ ssFloor + sDelta.Floor; IF ssFloor < ss.Floor THEN { ssFloor _ ssFloor + 1; lineOffset _ lineOffset + wordsPerLine; }; j _ j + 1; ENDLOOP; s _ ss.PLUS[Scaled.half]; f _ ff.PLUS[Scaled.half]; IF ssFloor # ss.Floor THEN ERROR; }; IF j < pixelSeq.fSize THEN { WHILE s.Floor < 0 DO s _ s.PLUS[Scaled.FromInt[sPixels]] ENDLOOP; WHILE s.Floor >= sPixels DO s _ s.MINUS[Scaled.FromInt[sPixels]] ENDLOOP; WHILE f.Floor < 0 DO f _ f.PLUS[Scaled.FromInt[fPixels]] ENDLOOP; WHILE f.Floor >= fPixels DO f _ f.MINUS[Scaled.FromInt[fPixels]] ENDLOOP; IF s.Floor IN [rect.sMin..rect.sMin+rect.sSize) AND f.Floor IN [rect.fMin..rect.fMin+rect.fSize) THEN { pix: CARDINAL _ source.GetPixel[s.Floor, f.Floor]; pixelSeq[j] _ Basics.BITSHIFT[pix*multiplier, lgScale]; }; s _ s.PLUS[sDelta]; f _ f.PLUS[fDelta]; j _ j + 1; }; ENDLOOP; } ELSE ERROR; sampler.sSource1 _ sSource; sampler.fSource1 _ fSource; sampler.fDest1 _ fDest0+count; }; Κ ͺ˜codešœ™Kšœ Οmœ7™BK™1K™'—K˜šΟk ˜ Kšœ˜Kšœ ˜ Kšœ˜Kšœ ˜ Kšœ˜Kšœ˜—K˜KšΠblœžœž˜Kšžœ@˜GKšžœ ˜Kšœžœžœ˜K˜Kš œ!žœžœžœžœ žœžœ˜LK˜Kšœ žœ˜&Kšœžœ˜+K˜š Οn œžœžœžœžœžœ˜cKšœžœ!˜*Kšœ˜Kš žœžœžœžœžœ˜BKšœ%˜%Kšžœ˜ K˜K™—Kšœžœ˜Kšœžœ˜Kš œ žœžœžœžœ˜=šœžœ˜K˜—š œžœžœžœžœžœžœ˜dKšžœžœžœ˜Kšœžœ!˜*š žœžœž œžœž˜.šžœžœ˜!Kšœ˜Kšžœžœ'˜BKšœ"˜"Kšœžœ˜Kšžœ˜Kšœ˜—Kšžœ˜—Kšœ@˜@K˜K˜—š œžœžœžœ˜Bšžœžœ˜'Kšœ ˜ Kšœ"˜"Kšœ˜—šžœ˜Kšœ˜Kšœžœ˜&Kšœ˜—K˜K™—š  œžœžœžœ žœ˜UKšœ9˜9Kšœžœ"˜8Kšœ˜K˜K™—K˜š   œžœžœžœžœ ˜MKšœžœX˜^Kšžœ ˜K˜K˜—š  œžœžœžœ˜LKšœžœX˜^Kšœ˜K˜K˜—š   œžœžœ%žœžœ˜\KšœžœX˜^Kšžœ žœ2˜AKšžœžœžœ˜)K˜K˜—K˜š   œžœžœžœ)žœž œ˜Xšžœž˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜K˜ Kšžœ˜—Kš žœžœžœ žœžœžœ˜BK˜K™—š   œžœžœžœ)žœž œ˜Xšžœž˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜K˜ Kšžœ˜—Kš žœžœžœ žœžœžœ˜BK˜K™—š   œžœžœžœ'žœž œ˜Yšžœž˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ ˜ K˜ Kšžœ˜—Kš žœžœžœ žœžœ˜8K˜K™—š   œžœžœ!žœ%žœ žœ˜xKšœ8˜8Kšœ7˜7Kšžœ=˜DK˜K™—š   œžœžœ!žœ%žœ žœ˜xKšœ8˜8Kšœ7˜7Kšžœ=˜DK˜K™—š   œžœžœ6žœ%žœ žœ˜Kšœ0˜0Kšœ8˜8Kšœ7˜7Kš žœžœžœžœ žœžœ˜FK˜K™—š   œžœžœ2žœ$žœ žœ˜ŠKšœ7˜7šžœž˜Kšœžœ˜ ˜Kšœ2˜2Kšœ7˜7Kš žœžœžœžœ žœžœ˜FK˜—˜Kšœ2˜2Kšœ2˜2Kšœ7˜7Kšœ7˜7Kš žœžœžœžœ žœ&žœ˜TK˜—˜Kšœ2˜2Kšœ2˜2Kšœ2˜2Kšœ7˜7Kšœ7˜7Kšœ7˜7Kš žœžœžœžœ žœ4žœ˜bK˜—š žœžœžœžœ ž˜%K˜šžœžœžœž˜!Jšœ9˜9Jšžœ˜—K˜ Kšžœ˜——K˜K™—K˜Kš œ žœžœ žœžœ˜6Kšœ žœžœžœ ˜/šœ žœ˜%K˜—š  œžœžœžœ ˜+Kš œ žœ žœ žœžœ˜?šžœžœžœž˜#Kšœžœžœ ˜=Kšžœ˜—Jšžœ ˜K˜K˜—šœ)˜)Kšœ žœ˜$Kšœ žœ ˜/Kšœ˜Kšœ˜K˜—š  œžœžœžœ!žœžœ žœžœžœ"ž œ˜₯Kšœ*˜*Kšœžœžœ)˜;K˜$KšœA˜AK˜Kšœžœžœ˜)Kšœ6˜6šžœžœ˜Kšœžœ˜ Kšœ žœ žœ˜5Kšœžœ˜2Kšœžœ žœ˜7Kšœ%˜%Kšœžœ˜9Kšœ ˜ Kšœ˜š žœžœžœžœž˜.Kšœžœ˜Kšœ˜Kšœžœ˜7Kšœžœžœ$˜Nšœžœ.˜IKšœ"™"Kšœžœ™.Kšœ,™,—Kšœžœ˜Kšžœ˜—K˜—šžœ˜Kšœžœžœ%˜7Kšœ˜Kšœ'˜'Kšœ˜Kšœ#˜#Kšœžœ ˜!Kšœ"˜"Kšœ˜Kšœ˜Kšœžœ˜K˜—K˜K™—š  œžœžœžœ!žœžœ žœžœžœfž œ˜ιKšœ*˜*Kšœžœžœ)˜;K˜$KšœA˜AK˜Kšœžœžœ&˜Mšžœžœ˜Kšœžœ˜ Kšœ žœ žœ˜5Kšœžœ˜2Kšœžœ žœ˜7Kšœ%˜%Kšœžœ˜AKšœ˜Kšœ˜š žœžœžœžœž˜.Kšœžœ˜Kšœ˜Kšœžœ˜7Kšœžœžœ$˜Nšœžœ.˜IKšœ"™"Kšœžœ™.Kšœ,™,—Kšœžœ˜Kšžœ˜—K˜—šžœ˜Kšœžœžœ%˜7Kšœ˜Kšœ'˜'Kšœ ˜ Kšœ#˜#Kšœžœ ˜!Kšœ˜Kšœ˜Kšœ˜Kšœžœ˜K˜—K˜K˜K˜—š œžœžœžœ!žœžœ žœžœžœž œ˜ŒKšœžœžœ)˜;K˜$KšœA˜AK˜Kšœžœžœ˜)Kšœ,˜,Kšœ˜Kšœ ˜ š žœžœžœžœž˜-Kšœžœ˜Kšœ˜Kšœ!˜!Kšœžœ ˜Kšœ žœ%˜:Kšœžœ˜Kšžœ˜—K˜K˜—š  œžœžœžœ!žœžœ žœžœžœ"ž œ˜₯Kšœ*˜*K˜$KšœA˜AK˜Kšœžœžœ˜)Kšœ6˜6Kšœ˜Kšœ'˜'Kšœ˜Kšœ-˜-Kšœ˜Kšœ˜šžœžœ˜Kšœžœ˜ Kšœžœ˜2Kšœžœ žœ˜7Kšœ;žœ˜Xšœžœžœ$˜NKšœ1™1Kšœžœ™.—Kšœžœ˜K˜—šžœ˜Kšœžœžœ%˜5KšœB˜BKšœžœ ˜Kšœžœ˜K˜—K˜K˜—š  œžœžœžœ!žœžœ žœžœžœfž œ˜ιKšœ*˜*K˜$KšœA˜AK˜Kšœžœžœ&˜MKšœ%˜%Kšœ˜Kšœ'˜'Kšœ ˜ Kšœ˜Kšœ˜šžœžœ˜Kšœžœ˜ Kšœžœ˜2Kšœžœ žœ˜7Kšœ;žœ˜Xšœžœžœ$˜NKšœ1™1Kšœžœ™.—Kšœžœ˜K˜—šžœ˜Kšœžœžœ%˜5KšœB˜BKšœžœ ˜Kšœžœ˜K˜—K˜K˜—K˜š œ žœžœžœžœ˜$K˜—š  œžœžœžœžœ˜)Kšžœžœžœžœ˜)Kšœžœ˜Kš žœžœžœžœžœ˜&K˜K˜—š  œžœžœžœžœžœ˜@Kšœ˜šžœžœ˜Kšœ žœ˜Kš œ žœžœžœžœžœ˜NKšœ<˜Kšœžœ™šžœžœžœ™%Kšœžœžœ™2Kšœ™—šžœžœžœ™"Kšœžœžœžœ™9Kšœ™—šžœžœžœ™%Kšœžœžœ™2Kšœ™—šžœžœžœ™"Kšœžœžœžœ™9Kšœ™—šžœžœž™Kšœžœ™'Kšœžœ™Kšœžœ™Kšœžœ*™6Kšœžœ™šžœž™šœ™Kšœžœžœžœžœžœžœžœžœžœ žœ™eKšœ™Kšœ1™1Kšœ™—šœ™Kšœžœžœžœžœžœžœžœžœžœ žœ™eKšœ™Kšœ1™1Kšœ™—šœ™Kšœžœžœžœžœžœžœžœžœžœ žœ™fKšœ™Kšœ1™1Kšœ™—šœ™Kšœžœžœžœžœžœžœžœžœžœ žœ™gKšœ™Kšœ1™1Kšœ™—šœ™Kšœžœžœžœžœžœžœžœžœžœžœžœ™gKšœ™Kšœ1™1Kšœ™—Kšžœžœ™—šžœžœ žœ™'Kšœ žœ™/Kšœ žœ™/Kšœ žœ™/Kšœ žœ™/Kšœ™—š œžœžœžœžœ™;Kšœžœžœ™.Kšœ™Kšœ™Kšœ™Kšœ™—Kš œžœžœžœžœ žœ™7Kš œžœžœžœžœ žœ™7Kšœ&™&Kšœ!™!šžœžœ™Kšœ™Kšœ'™'Kšœ™—K™ Kšžœ™—Kšœžœ™Kšœžœ™Kšžœžœžœ™!Kšœ™—šžœžœ™Kšžœ žœžœžœ™AKšžœžœžœžœ™IKšžœ žœžœžœ™AKšžœžœžœžœ™Iš žœ žœ#žœ žœ#žœ™gKšœžœ%™2Kšœžœ™7Kšœ™—Kšœžœ ™Kšœžœ ™K™ Kšœ™—Kšžœ™—K™—Kšžœžœ™ Kšœ™Kšœ™Kšœ™Kšœ™K™—K˜š  œžœžœžœžœ˜)Kšœžœžœžœ˜5K˜—š  œžœžœžœžœžœ˜:Kšœžœžœžœ ˜+K˜—š œžœžœž œžœ˜/KšœFž˜NKšœ˜K˜—š œžœžœžœ.žœžœžœžœžœžœžœžœžœž œ˜ΡKšœ žœžœ)˜BKšœ žœ˜Kš œžœžœžœžœ˜8Kš œžœžœžœžœ˜;Kš œ žœžœžœžœžœžœ˜Aš  œžœžœžœžœž œ˜?Kšœžœ˜šžœž˜Kšœ˜K˜ K˜ Kšžœ˜—Kšžœ žœ žœ˜