DIRECTORY Basics USING [BITSHIFT, bitsPerWord, LongMult], ImagerPixelMap USING [BoundedWindow, DeviceRectangle, Fill, GetPixel, Intersect, PixelMap, PixelMapRep, Reshape, Window], ImagerPixelRow USING [Pixel, PixelRow, PixelRowRep], ImagerTransformation USING [IntRectangle, InverseTransform, InverseTransformVec, Transformation, TransformIntRectangle], PrincOpsUtils USING [LongCopy, LongZero], Real USING [RoundLI], Scaled USING [Floor, FromInt, FromReal, MINUS, PLUS, Value], Vector2 USING [VEC]; ImagerPixelRowImpl: CEDAR PROGRAM IMPORTS Basics, ImagerPixelMap, PrincOpsUtils, Real, ImagerTransformation, Scaled EXPORTS ImagerPixelRow ~ BEGIN OPEN ImagerPixelRow; VEC: TYPE ~ Vector2.VEC; DeviceRectangle: TYPE ~ ImagerPixelMap.DeviceRectangle; IntRectangle: TYPE ~ ImagerTransformation.IntRectangle; Transformation: TYPE ~ ImagerTransformation.Transformation; PixelMap: TYPE ~ ImagerPixelMap.PixelMap; PixelRowElementSize: NAT ~ SIZE[PixelRowRep[1]]-SIZE[PixelRowRep[0]]; CreatePixelRow: PUBLIC PROC [sMin, fMin: INTEGER, fSize: NAT] RETURNS [new: PixelRow] ~ { new _ NEW[PixelRowRep[fSize]]; new.sOrigin _ sMin; new.fOrigin _ fMin; new.fSize _ fSize; }; ClearPixelRow: PUBLIC PROC [pixelRow: PixelRow] ~ TRUSTED { IF pixelRow.fSize > 0 THEN PrincOpsUtils.LongZero[@(pixelRow[0]), pixelRow.fSize*PixelRowElementSize]; }; CopyPixelRow: PUBLIC PROC [pixelRow: PixelRow, scratch: PixelRow _ NIL] RETURNS [new: PixelRow] ~ { IF scratch = NIL OR scratch.maxSize < pixelRow.fSize THEN new _ NEW[PixelRowRep[pixelRow.fSize]] ELSE new _ scratch; new.sOrigin _ pixelRow.sOrigin; new.fOrigin _ pixelRow.fOrigin; new.fSize _ pixelRow.fSize; IF new.fSize > 0 THEN TRUSTED { PrincOpsUtils.LongCopy[from: @(pixelRow[0]), nwords: new.fSize*PixelRowElementSize, to: @(new[0])]; }; }; AddByColumn: PUBLIC PROC [dest, source: PixelRow] ~ { fMin: INTEGER _ MAX[dest.fOrigin, source.fOrigin]; fMax: INTEGER _ MIN[dest.fOrigin+dest.fSize, source.fOrigin+source.fSize]; IF fMin < fMax THEN TRUSTED { destArr: LONG POINTER TO ARRAY [0..0) OF Pixel _ LOOPHOLE[@(dest[fMin-dest.fOrigin])]; sourceArr: LONG POINTER TO ARRAY [0..0) OF Pixel _ LOOPHOLE[@(source[fMin-source.fOrigin])]; FOR j: INTEGER IN [0..fMax-fMin) DO destArr[j] _ destArr[j] + sourceArr[j]; ENDLOOP; }; }; SubtractByColumn: PUBLIC PROC [dest, source: PixelRow] ~ { fMin: INTEGER _ MAX[dest.fOrigin, source.fOrigin]; fMax: INTEGER _ MIN[dest.fOrigin+dest.fSize, source.fOrigin+source.fSize]; IF fMin < fMax THEN TRUSTED { destArr: LONG POINTER TO ARRAY [0..0) OF Pixel _ LOOPHOLE[@(dest[fMin-dest.fOrigin])]; sourceArr: LONG POINTER TO ARRAY [0..0) OF Pixel _ LOOPHOLE[@(source[fMin-source.fOrigin])]; FOR j: INTEGER IN [0..fMax-fMin) DO destArr[j] _ destArr[j] - sourceArr[j]; ENDLOOP; }; }; LoadPixelRow: PUBLIC PROC [pixelRow: PixelRow, source: PixelMap] ~ TRUSTED { fOriginMap: INTEGER _ source.fOrigin; fOriginRow: INTEGER _ pixelRow.fOrigin; mapBB: DeviceRectangle _ source.BoundedWindow; fMin: INTEGER _ MAX[pixelRow.fOrigin, mapBB.fMin]; fMax: INTEGER _ MIN[pixelRow.fOrigin+pixelRow.fSize, mapBB.fMin+mapBB.fSize]; IF fMin >= fMax THEN {ClearPixelRow[pixelRow]; RETURN}; IF fMin > 0 THEN PrincOpsUtils.LongZero[@(pixelRow[0]), fMin*PixelRowElementSize]; IF fMax < pixelRow.fSize THEN PrincOpsUtils.LongZero[@(pixelRow[fMax]), (pixelRow.fSize-fMax)*PixelRowElementSize]; IF pixelRow.sOrigin IN [mapBB.sMin..mapBB.sMin+mapBB.sSize) THEN { SELECT source.refRep.lgBitsPerPixel FROM 0 => { linePtr: LONG POINTER TO PACKED ARRAY [0..0) OF [0..2) _ source.refRep.pointer + Basics.LongMult[(pixelRow.sOrigin - source.sOrigin), source.refRep.rast]; FOR f: INTEGER IN [fMin..fMax) DO pixelRow[f-fOriginRow] _ linePtr[f-fOriginMap]; ENDLOOP; }; 1 => { linePtr: LONG POINTER TO PACKED ARRAY [0..0) OF [0..4) _ source.refRep.pointer + Basics.LongMult[(pixelRow.sOrigin - source.sOrigin), source.refRep.rast]; FOR f: INTEGER IN [fMin..fMax) DO pixelRow[f-fOriginRow] _ linePtr[f-fOriginMap]; ENDLOOP; }; 2 => { linePtr: LONG POINTER TO PACKED ARRAY [0..0) OF [0..16) _ source.refRep.pointer + Basics.LongMult[(pixelRow.sOrigin - source.sOrigin), source.refRep.rast]; FOR f: INTEGER IN [fMin..fMax) DO pixelRow[f-fOriginRow] _ linePtr[f-fOriginMap]; ENDLOOP; }; 3 => { linePtr: LONG POINTER TO PACKED ARRAY [0..0) OF [0..256) _ source.refRep.pointer + Basics.LongMult[(pixelRow.sOrigin - source.sOrigin), source.refRep.rast]; FOR f: INTEGER IN [fMin..fMax) DO pixelRow[f-fOriginRow] _ linePtr[f-fOriginMap]; ENDLOOP; }; 4 => IF Basics.bitsPerWord = 16 THEN { from: LONG POINTER _ source.refRep.pointer + Basics.LongMult[(pixelRow.sOrigin - source.sOrigin), source.refRep.rast] + (fMin-fOriginMap); PrincOpsUtils.LongCopy[from: from, nwords: (fMax-fMin)*PixelRowElementSize, to: @(pixelRow[fMin-fOriginRow])]; } ELSE { linePtr: LONG POINTER TO PACKED ARRAY [0..0) OF CARDINAL _ source.refRep.pointer + Basics.LongMult[(pixelRow.sOrigin - source.sOrigin), source.refRep.rast]; FOR f: INTEGER IN [fMin..fMax) DO pixelRow[f-fOriginRow] _ linePtr[f-fOriginMap]; ENDLOOP; }; ENDCASE => ERROR; }; }; StorePixelRow: PUBLIC PROC [pixelRow: PixelRow, dest: PixelMap] ~ TRUSTED { fOriginMap: INTEGER _ dest.fOrigin; fOriginRow: INTEGER _ pixelRow.fOrigin; mapBB: DeviceRectangle _ dest.BoundedWindow; fMin: INTEGER _ MAX[pixelRow.fOrigin, mapBB.fMin]; fMax: INTEGER _ MIN[pixelRow.fOrigin+pixelRow.fSize, mapBB.fMin+mapBB.fSize]; IF fMin < fMax AND pixelRow.sOrigin IN [mapBB.sMin..mapBB.sMin+mapBB.sSize) THEN { SELECT dest.refRep.lgBitsPerPixel FROM 0 => { linePtr: LONG POINTER TO PACKED ARRAY [0..0) OF [0..2) _ dest.refRep.pointer + Basics.LongMult[(pixelRow.sOrigin - dest.sOrigin), dest.refRep.rast]; FOR f: INTEGER IN [fMin..fMax) DO linePtr[f-fOriginMap] _ MIN[pixelRow[f-fOriginRow], 1]; ENDLOOP; }; 1 => { linePtr: LONG POINTER TO PACKED ARRAY [0..0) OF [0..4) _ dest.refRep.pointer + Basics.LongMult[(pixelRow.sOrigin - dest.sOrigin), dest.refRep.rast]; FOR f: INTEGER IN [fMin..fMax) DO linePtr[f-fOriginMap] _ MIN[pixelRow[f-fOriginRow], 3]; ENDLOOP; }; 2 => { linePtr: LONG POINTER TO PACKED ARRAY [0..0) OF [0..16) _ dest.refRep.pointer + Basics.LongMult[(pixelRow.sOrigin - dest.sOrigin), dest.refRep.rast]; FOR f: INTEGER IN [fMin..fMax) DO linePtr[f-fOriginMap] _ MIN[pixelRow[f-fOriginRow], 15]; ENDLOOP; }; 3 => { linePtr: LONG POINTER TO PACKED ARRAY [0..0) OF [0..256) _ dest.refRep.pointer + Basics.LongMult[(pixelRow.sOrigin - dest.sOrigin), dest.refRep.rast]; FOR f: INTEGER IN [fMin..fMax) DO linePtr[f-fOriginMap] _ MIN[pixelRow[f-fOriginRow], 255]; ENDLOOP; }; 4 => IF Basics.bitsPerWord = 16 THEN { to: LONG POINTER _ dest.refRep.pointer + Basics.LongMult[(pixelRow.sOrigin - dest.sOrigin), dest.refRep.rast] + (fMin-fOriginMap); PrincOpsUtils.LongCopy[from: @(pixelRow[fMin-fOriginRow]), nwords: (fMax-fMin)*PixelRowElementSize, to: to]; } ELSE { linePtr: LONG POINTER TO PACKED ARRAY [0..0) OF CARDINAL _ dest.refRep.pointer + Basics.LongMult[(pixelRow.sOrigin - dest.sOrigin), dest.refRep.rast]; FOR f: INTEGER IN [fMin..fMax) DO linePtr[f-fOriginMap] _ pixelRow[f-fOriginRow]; ENDLOOP; }; ENDCASE => ERROR; }; }; TransferSamples: PUBLIC PROC [dest, source: PixelMap, transformation: Transformation, tile: BOOLEAN _ FALSE, multiplier: CARDINAL _ 1, lgScale: INTEGER _ 0] ~ { sr: DeviceRectangle _ source.Window; sb: DeviceRectangle _ source.BoundedWindow; db: IntRectangle _ transformation.TransformIntRectangle[[sr.sMin, sr.fMin, sr.sSize, sr.fSize]]; destRect: DeviceRectangle _ dest.BoundedWindow; dr: DeviceRectangle _ IF tile THEN destRect ELSE ImagerPixelMap.Intersect[destRect, [db.x, db.y, db.w, db.h]]; pixelRow: PixelRow _ CreatePixelRow[dr.sMin, dr.fMin, dr.fSize]; deltaPixel: VEC ~ transformation.InverseTransformVec[[0, 1]]; sDelta: Scaled.Value ~ Scaled.FromReal[deltaPixel.x]; fDelta: Scaled.Value ~ Scaled.FromReal[deltaPixel.y]; deltaLine: VEC ~ transformation.InverseTransformVec[[1, 0]]; sDeltaLine: Scaled.Value ~ Scaled.FromReal[deltaLine.x]; fDeltaLine: Scaled.Value ~ Scaled.FromReal[deltaLine.y]; sourceOrigin: VEC ~ transformation.InverseTransform[[dr.sMin+0.5, dr.fMin+0.5]]; sSource: Scaled.Value _ Scaled.FromReal[sourceOrigin.x]; fSource: Scaled.Value _ Scaled.FromReal[sourceOrigin.y]; GetSamples: PROC ~ { sMax: INTEGER _ sb.sMin+sb.sSize; fMax: INTEGER _ sb.fMin+sb.fSize; s: Scaled.Value _ sSource; f: Scaled.Value _ fSource; FOR j: NAT IN [0..pixelRow.fSize) DO IF tile THEN { WHILE s.Floor < sr.sMin DO s _ s.PLUS[Scaled.FromInt[sr.sSize]] ENDLOOP; WHILE s.Floor >= sr.sMin+sr.sSize DO s _ s.MINUS[Scaled.FromInt[sr.sSize]] ENDLOOP; WHILE f.Floor < sr.fMin DO f _ f.PLUS[Scaled.FromInt[sr.fSize]] ENDLOOP; WHILE f.Floor >= sr.fMin+sr.fSize DO f _ f.MINUS[Scaled.FromInt[sr.fSize]] ENDLOOP; }; IF s.Floor IN [sb.sMin..sMax) AND f.Floor IN [sb.fMin..fMax) THEN { pixelRow[j] _ Basics.BITSHIFT[source.GetPixel[s.Floor, f.Floor]*multiplier, lgScale]; }; s _ s.PLUS[sDelta]; f _ f.PLUS[fDelta]; ENDLOOP; }; THROUGH [0..dr.sSize) DO LoadPixelRow[pixelRow, dest]; GetSamples[]; StorePixelRow[pixelRow, dest]; pixelRow.sOrigin _ pixelRow.sOrigin + 1; sSource _ sSource.PLUS[sDeltaLine]; fSource _ fSource.PLUS[fDeltaLine]; ENDLOOP; }; UnderSample: PUBLIC PROC [pixelMap: PixelMap, transformation: Transformation, tile: BOOLEAN _ FALSE, background: CARDINAL _ 0, scratch: REF ImagerPixelMap.PixelMapRep _ NIL] RETURNS [PixelMap] ~ { sr: DeviceRectangle _ pixelMap.Window; db: IntRectangle _ transformation.TransformIntRectangle[[sr.sMin, sr.fMin, sr.sSize, sr.fSize]]; dr: DeviceRectangle _ [db.x, db.y, db.w, db.h]; new: PixelMap _ ImagerPixelMap.Reshape[scratch, pixelMap.refRep.lgBitsPerPixel, dr]; new.Fill[dr, background]; TransferSamples[new, pixelMap, transformation, tile]; RETURN [new] }; BoxTooBig: PUBLIC ERROR ~ CODE; BoxFilter: PUBLIC PROC [pixelMap: PixelMap, sSizeBox, fSizeBox: NAT] ~ { IF LONG[sSizeBox]*fSizeBox*255 > CARDINAL.LAST THEN ERROR BoxTooBig ELSE { sHalf: NAT ~ sSizeBox/2; fHalf: NAT ~ (fSizeBox+1)/2; sStart: INTEGER ~ pixelMap.sOrigin+pixelMap.sMin; sEnd: INTEGER ~ sStart + pixelMap.sSize; fStart: INTEGER ~ pixelMap.fOrigin+pixelMap.fMin; fEnd: INTEGER ~ fStart+pixelMap.fSize; sum: ARRAY [0..32) OF PixelRow; nPixels: CARDINAL _ sSizeBox*fSizeBox; sOrigin: INTEGER _ sStart-2*sSizeBox+sHalf; fOrigin: INTEGER ~ fStart-fSizeBox; result: PixelRow _ CreatePixelRow[sStart, fStart, pixelMap.fSize]; MoveToNextRow: PROC ~ { t: PixelRow _ sum[0]; p: Pixel; FOR i: NAT IN [0..sSizeBox) DO sum[i] _ sum[i+1]; ENDLOOP; sum[sSizeBox] _ t; sOrigin _ sOrigin + 1; t.sOrigin _ MAX[MIN[sOrigin + sSizeBox, sEnd-1], sStart]; LoadPixelRow[t, pixelMap]; p _ t[fSizeBox]; FOR i: NAT IN [0..fSizeBox) DO t[i] _ p; ENDLOOP; p _ t[t.fSize-fSizeBox-1]; FOR i: NAT IN [t.fSize-fSizeBox..t.fSize) DO t[i] _ p; ENDLOOP; t.sOrigin _ sOrigin + sSizeBox; FOR i: NAT IN [1..t.fSize) DO t[i] _ t[i] + t[i-1] ENDLOOP; AddByColumn[t, sum[sSizeBox-1]]; }; FOR i: NAT IN [0..sSizeBox] DO sum[i] _ CreatePixelRow[sOrigin+i, fOrigin, pixelMap.fSize+2*fSizeBox]; ClearPixelRow[sum[i]]; ENDLOOP; FOR s: INTEGER IN [sStart..sEnd) DO WHILE sum[sHalf+1].sOrigin # s DO MoveToNextRow[] ENDLOOP; result.sOrigin _ s; FOR f: INTEGER IN [fStart..fEnd) DO boxSum: Pixel _ sum[sSizeBox][f-fHalf+fSizeBox-fOrigin] - sum[sSizeBox][f-fHalf-fOrigin] - sum[0][f-fHalf+fSizeBox-fOrigin] + sum[0][f-fHalf-fOrigin]; result[f-fStart] _ boxSum/nPixels; ENDLOOP; StorePixelRow[result, pixelMap]; ENDLOOP; }; }; ChangeBitsPerPixel: PUBLIC PROC [pixelMap: PixelMap, newLgBitsPerPixel: [0..4], scratch: REF ImagerPixelMap.PixelMapRep _ NIL] RETURNS [PixelMap] ~ { bounds: DeviceRectangle _ pixelMap.Window; new: PixelMap _ ImagerPixelMap.Reshape[scratch, newLgBitsPerPixel, bounds]; pixelRow: PixelRow _ CreatePixelRow[0, bounds.fMin, bounds.fSize]; FOR s: INTEGER IN [bounds.sMin..bounds.sMin+bounds.sSize) DO pixelRow.sOrigin _ s; LoadPixelRow[pixelRow, pixelMap]; StorePixelRow[pixelRow, new]; ENDLOOP; RETURN [new] }; Renormalize: PUBLIC PROC [pixelMap: PixelMap, oldmin, oldmax, newmin, newmax: REAL] ~ { bounds: DeviceRectangle _ pixelMap.Window; pixelRow: PixelRow _ CreatePixelRow[0, bounds.fMin, bounds.fSize]; m: REAL _ (newmax-newmin)/(oldmax-oldmin); FOR s: INTEGER IN [bounds.sMin..bounds.sMin+bounds.sSize) DO pixelRow.sOrigin _ s; LoadPixelRow[pixelRow, pixelMap]; FOR j: NAT IN [0..bounds.fSize) DO pix: REAL _ pixelRow[j]; out: REAL _ (pix-oldmin)*m+newmin; pixelRow[j] _ MAX[MIN[Real.RoundLI[out], CARDINAL.LAST], 0]; ENDLOOP; StorePixelRow[pixelRow, pixelMap]; ENDLOOP; }; END. ²ImagerPixelRowImpl.mesa Copyright c 1984, Xerox Corporation. All rights reserved. Michael Plass, August 6, 1984 9:07:49 am PDT Doug Wyatt, August 16, 1984 11:22:37 am PDT Ê!˜šœ™Jšœ Ïmœ/™:J™,J™+J˜—šÏk ˜ Jšœžœžœ˜/Jšœžœe˜yJšœžœ ˜4Jšœžœ^˜xJšœžœ˜)Jšœžœ ˜Jšœžœžœžœ ˜˜nJšœ@˜@Jšœ žœ.˜=Jšœ5˜5Jšœ5˜5Jšœ žœ.˜