<> <> <> <> DIRECTORY Basics USING [BITAND, BITNOT, BITOR, BITSHIFT, bitsPerWord, BITXOR, HighHalf, LongMult], ImagerPixelMap USING [BoundedWindow, Create, DeviceRectangle, GetPixel, PixelMap, Window], ImagerPixelRow USING [CreatePixelRow, LoadPixelRow, PixelRow, StorePixelRow], ImagerSampler USING [Sampler, SamplerRep], ImagerTransformation USING [InverseTransform, InverseTransformVec, Transformation], Real USING [RoundLI], RealFns USING [CosDeg], Scaled USING [Floor, FromInt, FromReal, GREATER, half, LESS, MINUS, PLUS, UMINUS, Value, zero], Vector2 USING [VEC]; ImagerSamplerImpl: CEDAR PROGRAM IMPORTS Basics, ImagerPixelMap, ImagerPixelRow, ImagerTransformation, RealFns, Scaled EXPORTS ImagerSampler ~ BEGIN Sampler: TYPE ~ ImagerSampler.Sampler; SamplerRep: TYPE ~ ImagerSampler.SamplerRep; PixelMap: TYPE ~ ImagerPixelMap.PixelMap; PixelRow: TYPE ~ ImagerPixelRow.PixelRow; Transformation: TYPE ~ ImagerTransformation.Transformation; VEC: TYPE ~ Vector2.VEC; CreateSamplerRep: PROC [m: Transformation, x, y: INTEGER, sPixels, fPixels: NAT] RETURNS [samplerRep: SamplerRep] ~ { deltaPixel: VEC ~ m.InverseTransformVec[[0, 1]]; deltaLine: VEC ~ m.InverseTransformVec[[1, 0]]; sourceOrigin: VEC _ m.InverseTransform[[x+0.5, y+0.5]]; IF sPixels = 0 OR fPixels = 0 THEN ERROR; WHILE sourceOrigin.x < 0 DO sourceOrigin.x _ sourceOrigin.x + sPixels ENDLOOP; WHILE sourceOrigin.x >= sPixels DO sourceOrigin.x _ sourceOrigin.x - sPixels ENDLOOP; WHILE sourceOrigin.y < 0 DO sourceOrigin.y _ sourceOrigin.y + fPixels ENDLOOP; WHILE sourceOrigin.y >= sPixels DO sourceOrigin.y _ sourceOrigin.y - fPixels ENDLOOP; samplerRep _ [ m: m, x: x, y: y, sPixels: sPixels, fPixels: fPixels, sStart: Scaled.FromReal[sourceOrigin.x], fStart: Scaled.FromReal[sourceOrigin.y], sDelta: Scaled.FromReal[deltaPixel.x], fDelta: Scaled.FromReal[deltaPixel.y], sDeltaLine: Scaled.FromReal[deltaLine.x], fDeltaLine: Scaled.FromReal[deltaLine.y] ]; }; CreateSampler: PUBLIC PROC [m: Transformation, x, y: INTEGER, sPixels, fPixels: NAT] RETURNS [sampler: Sampler] ~ { sampler _ NEW[SamplerRep _ CreateSamplerRep[m, x, y, sPixels, fPixels]]; }; SetSamplePosition: PUBLIC PROC [sampler: Sampler, x, y: INTEGER] ~ { IF ABS[x-sampler.x] > 20 OR ABS[y-sampler.y] > 20 THEN sampler^ _ CreateSamplerRep[sampler.m, x, y, sampler.sPixels, sampler.fPixels] ELSE { s: Scaled.Value _ sampler.sStart; f: Scaled.Value _ sampler.fStart; WHILE sampler.x < x DO sampler.x _ sampler.x + 1; s _ s.PLUS[sampler.sDeltaLine]; f _ f.PLUS[sampler.fDeltaLine]; ENDLOOP; WHILE sampler.x > x DO sampler.x _ sampler.x - 1; s _ s.MINUS[sampler.sDeltaLine]; f _ f.MINUS[sampler.fDeltaLine]; ENDLOOP; WHILE sampler.y < y DO sampler.y _ sampler.y + 1; s _ s.PLUS[sampler.sDelta]; f _ f.PLUS[sampler.fDelta]; ENDLOOP; WHILE sampler.y > y DO sampler.y _ sampler.y - 1; s _ s.MINUS[sampler.sDelta]; f _ f.MINUS[sampler.fDelta]; ENDLOOP; WHILE s.Floor < 0 DO s _ s.PLUS[Scaled.FromInt[sampler.sPixels]] ENDLOOP; WHILE s.Floor >= sampler.sPixels DO s _ s.MINUS[Scaled.FromInt[sampler.sPixels]] ENDLOOP; WHILE f.Floor < 0 DO f _ f.PLUS[Scaled.FromInt[sampler.fPixels]] ENDLOOP; WHILE f.Floor >= sampler.fPixels DO f _ f.MINUS[Scaled.FromInt[sampler.fPixels]] ENDLOOP; sampler.sStart _ s; sampler.fStart _ f; }; }; SimpleObtainPointSamples: PROC [pixelRow: PixelRow, source: PixelMap, sampler: Sampler, multiplier: CARDINAL, lgScale: INTEGER] ~ { rect: ImagerPixelMap.DeviceRectangle _ source.BoundedWindow; FOR j: NAT IN [0..pixelRow.fSize) DO SetSamplePosition[sampler, pixelRow.sOrigin, pixelRow.fOrigin+j]; IF sampler.sStart.Floor IN [rect.sMin..rect.sMin+rect.sSize) AND sampler.fStart.Floor IN [rect.fMin..rect.fMin+rect.fSize) THEN { pixelRow[j] _ Basics.BITSHIFT[source.GetPixel[sampler.sStart.Floor, sampler.fStart.Floor]*multiplier, lgScale]; }; ENDLOOP; }; TruncDiv: PROC [a, b: Scaled.Value] RETURNS [INT] ~ INLINE { RETURN [LOOPHOLE[a, INT]/LOOPHOLE[b, INT]] }; Mod: PROC [s: Scaled.Value, m: NAT] RETURNS [Scaled.Value] ~ { WHILE s.integerPart < 0 DO s.integerPart _ s.integerPart + m ENDLOOP; WHILE s.integerPart >= m DO s.integerPart _ s.integerPart - m ENDLOOP; RETURN [s] }; SimplePointSamples: PROC [pixelRow: PixelRow, source: PixelMap, sampler: Sampler] ~ TRUSTED { <> rast: INT ~ source.refRep.rast; lgBitsPerPixel: NAT ~ source.refRep.lgBitsPerPixel; sPixels: INTEGER ~ sampler.sPixels; fPixels: INTEGER ~ sampler.fPixels; s: Scaled.Value _ sampler.sStart; sFloor: INTEGER _ s.Floor; f: Scaled.Value _ sampler.fStart; sDelta: Scaled.Value _ Mod[sampler.sDelta, sPixels]; fDelta: Scaled.Value _ Mod[sampler.fDelta, fPixels]; lineOffset: INT _ INT[s.Floor - source.sOrigin]*rast; normalDelta: INT _ INT[sDelta.Floor]*rast; totalDelta: INT _ INT[sPixels]*rast; FOR j: NAT IN [0..pixelRow.fSize) DO pixelRow[j] _ SELECT lgBitsPerPixel FROM 0 => LOOPHOLE[source.refRep.pointer + lineOffset, LONG POINTER TO PACKED ARRAY [0..0) OF [0..2)][f.Floor - source.fOrigin], 1 => LOOPHOLE[source.refRep.pointer + lineOffset, LONG POINTER TO PACKED ARRAY [0..0) OF [0..4)][f.Floor - source.fOrigin], 2 => LOOPHOLE[source.refRep.pointer + lineOffset, LONG POINTER TO PACKED ARRAY [0..0) OF [0..16)][f.Floor - source.fOrigin], 3 => LOOPHOLE[source.refRep.pointer + lineOffset, LONG POINTER TO PACKED ARRAY [0..0) OF [0..256)][f.Floor - source.fOrigin], 4 => LOOPHOLE[source.refRep.pointer + lineOffset, LONG POINTER TO PACKED ARRAY [0..0) OF CARDINAL][f.Floor - source.fOrigin], ENDCASE => ERROR; s _ LOOPHOLE[LOOPHOLE[s, INT]+LOOPHOLE[sDelta, INT]]; f _ LOOPHOLE[LOOPHOLE[f, INT]+LOOPHOLE[fDelta, INT]]; lineOffset _ lineOffset + normalDelta; sFloor _ sFloor + sDelta.Floor; IF sFloor < s.Floor THEN { sFloor _ s.Floor; lineOffset _ lineOffset + rast; }; IF sFloor >= sPixels THEN { sFloor _ s.integerPart _ sFloor - sPixels; lineOffset _ lineOffset - totalDelta; }; IF f.Floor >= fPixels THEN f.integerPart _ f.integerPart - fPixels; ENDLOOP; }; ObtainPointSamples: PUBLIC PROC [pixelRow: PixelRow, source: PixelMap, sampler: Sampler, multiplier: CARDINAL, lgScale: INTEGER] ~ { rect: ImagerPixelMap.DeviceRectangle ~ source.BoundedWindow; sMax: INTEGER ~ rect.sMin+rect.sSize; fMax: INTEGER ~ rect.fMin+rect.fSize; sPixels: INTEGER ~ sampler.sPixels; fPixels: INTEGER ~ sampler.fPixels; rast: INT ~ source.refRep.rast; base: LONG POINTER ~ source.refRep.pointer; lgBitsPerPixel: NAT ~ source.refRep.lgBitsPerPixel; SetSamplePosition[sampler, pixelRow.sOrigin, pixelRow.fOrigin]; IF rect = [0, 0, sPixels, fPixels] AND multiplier = 1 AND lgScale = 0 THEN { SimplePointSamples[pixelRow, source, sampler]; } ELSE { s: Scaled.Value _ sampler.sStart; f: Scaled.Value _ sampler.fStart; sDelta: Scaled.Value _ sampler.sDelta; fDelta: Scaled.Value _ sampler.fDelta; normalDelta: INT _ INT[sDelta.Floor]*rast; j: CARDINAL _ 0; WHILE j < pixelRow.fSize DO IF s.Floor IN [rect.sMin..sMax) AND f.Floor IN [rect.fMin..fMax) THEN TRUSTED { sFloor: INTEGER _ s.Floor; lineOffset: INT _ INT[s.Floor - source.sOrigin]*rast; toGo: INT _ pixelRow.fSize-j; IF sDelta.GREATER[Scaled.zero] THEN { toGo _ MIN[toGo, TruncDiv[Scaled.FromInt[sMax].MINUS[s], sDelta]]; }; IF sDelta.LESS[Scaled.zero] THEN { toGo _ MIN[toGo, TruncDiv[s.MINUS[Scaled.FromInt[rect.sMin]], sDelta.UMINUS]]; }; IF fDelta.GREATER[Scaled.zero] THEN { toGo _ MIN[toGo, TruncDiv[Scaled.FromInt[fMax].MINUS[f], fDelta]]; }; IF fDelta.LESS[Scaled.zero] THEN { toGo _ MIN[toGo, TruncDiv[f.MINUS[Scaled.FromInt[rect.fMin]], fDelta.UMINUS]]; }; THROUGH [0..INTEGER[toGo]) DO pix: CARDINAL _ SELECT lgBitsPerPixel FROM 0 => LOOPHOLE[base + lineOffset, LONG POINTER TO PACKED ARRAY [0..0) OF [0..2)][f.Floor - source.fOrigin], 1 => LOOPHOLE[base + lineOffset, LONG POINTER TO PACKED ARRAY [0..0) OF [0..4)][f.Floor - source.fOrigin], 2 => LOOPHOLE[base + lineOffset, LONG POINTER TO PACKED ARRAY [0..0) OF [0..16)][f.Floor - source.fOrigin], 3 => LOOPHOLE[base + lineOffset, LONG POINTER TO PACKED ARRAY [0..0) OF [0..256)][f.Floor - source.fOrigin], 4 => LOOPHOLE[base + lineOffset, LONG POINTER TO PACKED ARRAY [0..0) OF CARDINAL][f.Floor - source.fOrigin], ENDCASE => ERROR; pixelRow[j] _ Basics.BITSHIFT[pix*multiplier, lgScale]; s _ LOOPHOLE[LOOPHOLE[s, INT]+LOOPHOLE[sDelta, INT]]; f _ LOOPHOLE[LOOPHOLE[f, INT]+LOOPHOLE[fDelta, INT]]; lineOffset _ lineOffset + normalDelta; sFloor _ sFloor + sDelta.Floor; IF sFloor < s.Floor THEN { sFloor _ sFloor + 1; lineOffset _ lineOffset + rast; }; j _ j + 1; ENDLOOP; IF sFloor # s.Floor THEN ERROR; }; IF j < pixelRow.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..sMax) AND f.Floor IN [rect.fMin..fMax) THEN { pix: CARDINAL _ source.GetPixel[s.Floor, f.Floor]; pixelRow[j] _ Basics.BITSHIFT[pix*multiplier, lgScale]; }; s _ s.PLUS[sDelta]; f _ f.PLUS[fDelta]; j _ j + 1; }; ENDLOOP; }; }; ObtainInterpolatedSamples: PUBLIC PROC [pixelRow: PixelRow, source: PixelMap, sampler: Sampler, multiplier: CARDINAL, lgScale: INTEGER] ~ { rect: ImagerPixelMap.DeviceRectangle ~ source.BoundedWindow; sMin: Scaled.Value ~ Scaled.FromInt[rect.sMin].PLUS[Scaled.half]; fMin: Scaled.Value ~ Scaled.FromInt[rect.fMin].PLUS[Scaled.half]; sMax: Scaled.Value ~ Scaled.FromInt[rect.sMin+rect.sSize].MINUS[Scaled.half]; fMax: Scaled.Value ~ Scaled.FromInt[rect.fMin+rect.fSize].MINUS[Scaled.half]; sPixels: INTEGER ~ sampler.sPixels; fPixels: INTEGER ~ sampler.fPixels; rast: INT ~ source.refRep.rast; base: LONG POINTER ~ source.refRep.pointer; lgBitsPerPixel: NAT ~ source.refRep.lgBitsPerPixel; SetSamplePosition[sampler, pixelRow.sOrigin, pixelRow.fOrigin]; BEGIN s: Scaled.Value _ sampler.sStart; f: Scaled.Value _ sampler.fStart; sDelta: Scaled.Value _ sampler.sDelta; fDelta: Scaled.Value _ sampler.fDelta; normalDelta: INT _ INT[sDelta.Floor]*rast; j: CARDINAL _ 0; WHILE j < pixelRow.fSize DO IF NOT s.LESS[sMin] AND s.LESS[sMax] AND NOT f.LESS[fMin] AND f.LESS[fMax] THEN TRUSTED { ss: Scaled.Value _ s.MINUS[Scaled.half]; ff: Scaled.Value _ f.MINUS[Scaled.half]; ssFloor: INTEGER _ ss.Floor; lineOffset: INT _ INT[ss.Floor - source.sOrigin]*rast; toGo: INT _ pixelRow.fSize-j; IF sDelta.GREATER[Scaled.zero] THEN { toGo _ MIN[toGo, TruncDiv[sMax.MINUS[s], sDelta]]; }; IF sDelta.LESS[Scaled.zero] THEN { toGo _ MIN[toGo, TruncDiv[s.MINUS[sMin], sDelta.UMINUS]]; }; IF fDelta.GREATER[Scaled.zero] THEN { toGo _ MIN[toGo, TruncDiv[fMax.MINUS[f], fDelta]]; }; IF fDelta.LESS[Scaled.zero] THEN { toGo _ MIN[toGo, TruncDiv[f.MINUS[fMin], fDelta.UMINUS]]; }; THROUGH [0..INTEGER[toGo]) DO k: INTEGER _ ff.Floor - source.fOrigin; a: CARDINAL _ ss.fraction; b: CARDINAL _ ff.fraction; ab: CARDINAL _ Basics.HighHalf[Basics.LongMult[a, b]]; v00, v01, v10, v11: CARDINAL; SELECT lgBitsPerPixel FROM 0 => { p: LONG POINTER TO RECORD[PACKED SEQUENCE COMPUTED CARDINAL OF [0..2)] _ LOOPHOLE[base + lineOffset]; v00 _ p[k]; v01 _ p[k + 1]; p _ p + rast; 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 + rast; 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 + rast; 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 + rast; 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 + rast; 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]; }; pixelRow[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 + rast; }; j _ j + 1; ENDLOOP; s _ ss.PLUS[Scaled.half]; f _ ff.PLUS[Scaled.half]; IF ssFloor # ss.Floor THEN ERROR; }; IF j < pixelRow.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]; pixelRow[j] _ Basics.BITSHIFT[pix*multiplier, lgScale]; }; s _ s.PLUS[sDelta]; f _ f.PLUS[fDelta]; j _ j + 1; }; ENDLOOP; END; }; Hi: PROC [a: CARDINAL] RETURNS [CARDINAL] ~ INLINE {RETURN[Basics.BITSHIFT[a, 1-Basics.bitsPerWord]]}; Shift: PROC [a: CARDINAL, amt: INTEGER] RETURNS [CARDINAL] ~ INLINE {RETURN[Basics.BITSHIFT[a, amt]]}; HalftoneLine: PUBLIC PROC [dest: PixelMap, pixels: PixelRow, thresholds: PixelRow, invertOutput: BOOLEAN, transparent: BOOLEAN] ~ { rect: ImagerPixelMap.DeviceRectangle _ dest.BoundedWindow; fMin: INTEGER _ MAX[rect.fMin, pixels.fOrigin]; fMax: INTEGER _ MIN[rect.fMin+rect.fSize, pixels.fOrigin+pixels.fSize]; IF fMax <= fMin THEN RETURN; IF pixels.sOrigin NOT IN [rect.sMin..rect.sMin+rect.sSize) THEN RETURN; IF dest.refRep.lgBitsPerPixel # 0 THEN ERROR; IF fMin < thresholds.fOrigin THEN ERROR; IF fMax > thresholds.fOrigin + thresholds.fSize THEN ERROR; TRUSTED { SixteenWords: TYPE ~ MACHINE DEPENDENT RECORD [ w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15: CARDINAL ]; linePointer: LONG POINTER ~ dest.refRep.pointer+Basics.LongMult[dest.refRep.rast, pixels.sOrigin-dest.sOrigin]; bitOffset: CARDINAL ~ fMin - dest.fOrigin; p: LONG POINTER TO SixteenWords _ LOOPHOLE[@(pixels[0])]; q: LONG POINTER TO SixteenWords _ LOOPHOLE[@(thresholds[pixels.fOrigin-thresholds.fOrigin])]; 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 count: CARDINAL _ fMax-fMin; 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]]; }; }; }; }; DotScreen: PUBLIC PROC [r: REAL, sSize: NAT, fSize: NAT, maxPixelValue: CARDINAL] RETURNS [pixelMap: PixelMap] ~ { pixelRow: PixelRow _ ImagerPixelRow.CreatePixelRow[0, 0, fSize]; pixelMap _ ImagerPixelMap.Create[4, [0, 0, sSize, fSize]]; FOR s: NAT IN [0..sSize) DO u: REAL _ RealFns.CosDeg[360.0*s/sSize+0.314159]*(1.0-r); pixelRow.sOrigin _ s; FOR f: NAT IN [0..fSize) DO v: REAL _ u+RealFns.CosDeg[360.0*f/fSize-0.0271828]*r; pix: INT _ Real.RoundLI[maxPixelValue*(v+1)/2]; pixelRow[f] _ MIN[MAX[pix, 0], maxPixelValue]; ENDLOOP; pixelRow.StorePixelRow[pixelMap]; ENDLOOP; }; shellD: ARRAY [1..11] OF CARDINAL = [1, 4, 13, 40, 121, 364, 1093, 3280, 9841, 29524, 65535]; ShellSort: PROCEDURE [key, data: REF ARRAY [0..32000) OF CARDINAL, length: NAT] = { passes: NAT _ 1; UNTIL shellD[passes+2] >= length DO passes _ passes+1 ENDLOOP; FOR pass: NAT DECREASING IN [1..passes] DO h: NAT _ shellD[pass]; FOR i: NAT IN [0..length) DO aKey: CARDINAL _ key[i]; aData: CARDINAL _ data[i]; j: NAT _ i; WHILE j>=h AND aKey < key[j-h] DO key[j] _ key[j-h]; data[j] _ data[j-h]; j _ j-h; ENDLOOP; key[j] _ aKey; data[j] _ aData; ENDLOOP; ENDLOOP; }; ApplyTRC: PUBLIC PROC [thresholds: PixelMap, trc: PROC[x: REAL] RETURNS [y: REAL], maxPixelValue: CARDINAL] ~ { rect: ImagerPixelMap.DeviceRectangle _ thresholds.Window; element: REF ARRAY [0..32000) OF CARDINAL _ NEW[ARRAY [0..32000) OF CARDINAL]; position: REF ARRAY [0..32000) OF CARDINAL _ NEW[ARRAY [0..32000) OF CARDINAL]; pixelRow: PixelRow _ ImagerPixelRow.CreatePixelRow[0, rect.fMin, rect.fSize]; pix: CARDINAL _ 1; n: NAT _ 0; FOR s: NAT IN [rect.sMin..rect.sMin+rect.sSize) DO pixelRow.sOrigin _ s; pixelRow.LoadPixelRow[thresholds]; FOR f: NAT IN [0..rect.fSize) DO element[n] _ pixelRow[f]; position[n] _ n; n _ n + 1; ENDLOOP; ENDLOOP; ShellSort[element, position, n]; FOR i: NAT IN [0..n) DO y: REAL _ REAL[i]/n; UNTIL trc[REAL[pix]/maxPixelValue] >= y DO IF pix + 1 >= maxPixelValue THEN EXIT; pix _ pix + 1; ENDLOOP; element[i] _ pix; ENDLOOP; ShellSort[position, element, n]; n _ 0; FOR s: NAT IN [rect.sMin..rect.sMin+rect.sSize) DO pixelRow.sOrigin _ s; FOR f: NAT IN [0..rect.fSize) DO pixelRow[f] _ element[n]; n _ n + 1; ENDLOOP; pixelRow.StorePixelRow[thresholds]; ENDLOOP; }; Identity: PUBLIC PROC [x: REAL] RETURNS [y: REAL] ~ { RETURN [x] }; END.