DIRECTORY Basics USING [BITSHIFT, NonNegative], ImagerPixel USING [PixelBuffer, PixelMap, PixelMapRep], ImagerPixelArray USING [ErrorDesc, maxCount, maxVec, PixelArray, PixelArrayClassRep, PixelArrayRep], ImagerPixelArrayPrivate USING [CopyProc, GetProc, GetSamplesProc, MaxSampleValueProc, PixelArrayClass, PixelArrayClassRep, TransferProc], ImagerSample USING [BasicTransfer, Copy, DoWithScratchMap, DoWithScratchSamples, Function, Get, GetBitsPerSample, GetBox, GetSamples, maxBitsPerSample, maxCount, NewSampleMap, nullFunction, Put, PutSamples, ReIndex, Sample, SampleBuffer, SampleMap], ImagerTransformation USING [Equal, ScanMode, SFToXY, Transformation], RuntimeError USING [BoundsFault], SF USING [Box, Inside, Min, Neg, Size, Sub, Vec, zeroVec]; ImagerPixelArrayImpl: CEDAR PROGRAM IMPORTS Basics, ImagerSample, ImagerTransformation, RuntimeError, SF EXPORTS ImagerPixelArray, ImagerPixelArrayPrivate ~ BEGIN OPEN ImagerPixelArrayPrivate, ImagerPixelArray; Vec: TYPE ~ SF.Vec; Transformation: TYPE ~ ImagerTransformation.Transformation; ScanMode: TYPE ~ ImagerTransformation.ScanMode; Sample: TYPE ~ ImagerSample.Sample; SampleBuffer: TYPE ~ ImagerSample.SampleBuffer; PixelBuffer: TYPE ~ ImagerPixel.PixelBuffer; SampleMap: TYPE ~ ImagerSample.SampleMap; PixelMap: TYPE ~ ImagerPixel.PixelMap; PixelMapRep: TYPE ~ ImagerPixel.PixelMapRep; Function: TYPE ~ ImagerSample.Function; nullFunction: Function ~ ImagerSample.nullFunction; zeroVec: SF.Vec ~ SF.zeroVec; PixelArrayClass: TYPE ~ ImagerPixelArrayPrivate.PixelArrayClass; PixelArrayClassRep: PUBLIC TYPE ~ ImagerPixelArrayPrivate.PixelArrayClassRep; Error: PUBLIC ERROR [error: ErrorDesc] ~ CODE; BoundsCheck: PROC [arg: INT, limit: NAT] RETURNS [sameArg: NAT] ~ INLINE { IF LOOPHOLE[arg, CARD] >= CARD[limit] THEN ERROR RuntimeError.BoundsFault; RETURN [arg] }; GetClass: PUBLIC PROC [pa: PixelArray] RETURNS [ATOM] ~ { class: PixelArrayClass ~ pa.class; RETURN[class.type]; }; MaxSampleValue: PUBLIC PROC [pa: PixelArray, i: NAT] RETURNS [Sample] ~ { class: PixelArrayClass ~ pa.class; RETURN class.MaxSampleValue[pa: pa, i: BoundsCheck[i, pa.samplesPerPixel]]; }; Get: PUBLIC PROC [pa: PixelArray, i: NAT, s, f: INT] RETURNS [Sample] ~ { class: PixelArrayClass ~ pa.class; iCheck: NAT ~ BoundsCheck[i, pa.samplesPerPixel]; sRem: INT ~ Basics.NonNegative[pa.sSize-Basics.NonNegative[s]]; fRem: INT ~ Basics.NonNegative[pa.fSize-Basics.NonNegative[f]]; [] ฌ Basics.NonNegative[sRem-1]; [] ฌ Basics.NonNegative[fRem-1]; RETURN class.Get[pa: pa, i: i, s: s, f: f]; }; GetSamples: PUBLIC PROC [pa: PixelArray, i: NAT ฌ 0, s, f: INT ฌ 0, buffer: SampleBuffer, start: NAT ฌ 0, count: NAT ฌ maxCount] ~ { class: PixelArrayClass ~ pa.class; iCheck: NAT ~ BoundsCheck[i, pa.samplesPerPixel]; sRem: INT ~ Basics.NonNegative[pa.sSize-Basics.NonNegative[s]]; fRem: INT ~ Basics.NonNegative[pa.fSize-Basics.NonNegative[f]]; actualCount: NAT ~ MIN[buffer.length-start, count]; [] ฌ Basics.NonNegative[sRem-1]; [] ฌ Basics.NonNegative[fRem-actualCount]; class.GetSamples[pa: pa, i: i, s: s, f: f, buffer: buffer, start: start, count: actualCount]; }; GetPixels: PUBLIC PROC [pa: PixelArray, s, f: INT ฌ 0, pixels: PixelBuffer, start: NAT ฌ 0, count: NAT ฌ maxCount] ~ { FOR i: NAT IN[0..pa.samplesPerPixel) DO GetSamples[pa, i, s, f, pixels[i], start, count] ENDLOOP }; Transfer: PUBLIC PROC [pa: PixelArray, i: NAT ฌ 0, s, f: INT ฌ 0, dst: SampleMap, dstMin: Vec ฌ zeroVec, size: Vec ฌ maxVec, function: Function ฌ nullFunction] ~ { class: PixelArrayClass ~ pa.class; iCheck: NAT ~ BoundsCheck[i, pa.samplesPerPixel]; sRem: INT ~ Basics.NonNegative[pa.sSize-Basics.NonNegative[s]]; fRem: INT ~ Basics.NonNegative[pa.fSize-Basics.NonNegative[f]]; dstBox: SF.Box ~ ImagerSample.GetBox[dst]; actualSize: Vec ฌ dstBox.max.Sub[dstMin].Min[size]; IF sRem RETURN [pa]; class.Copy#NIL => RETURN [class.Copy[pa]]; ENDCASE => { samplesPerPixel: NAT ~ pa.samplesPerPixel; pm: PixelMapData ~ NEW[PixelMapRep[samplesPerPixel]]; sSize: INT ~ pa.sSize; fSize: INT ~ pa.fSize; pm.box ฌ [max: [s: sSize, f: fSize]]; FOR i: NAT IN[0..samplesPerPixel) DO bitsPerSample: NAT ~ BitsPerSampleFromMaxSample[MaxSampleValue[pa, i]]; sm: SampleMap ~ ImagerSample.NewSampleMap[box: pm.box, bitsPerSample: bitsPerSample]; Transfer[pa: pa, i: i, dst: sm]; pm[i] ฌ sm; ENDLOOP; RETURN[New[class: pixelMapClass, data: pm, immutable: TRUE, samplesPerPixel: samplesPerPixel, sSize: sSize, fSize: fSize, m: pa.m]]; }; }; GetViaGetSamples: PROC [pa: PixelArray, i: NAT, s, f: INT] RETURNS [Sample] ~ { class: PixelArrayClass ~ pa.class; value: Sample ฌ 0; action: PROC [buffer: SampleBuffer] ~ { class.GetSamples[pa: pa, i: i, s: s, f: f, buffer: buffer, start: 0, count: 1]; value ฌ buffer[0]; }; ImagerSample.DoWithScratchSamples[1, action]; RETURN[value]; }; GetViaTransfer: PROC [pa: PixelArray, i: NAT, s, f: INT] RETURNS [Sample] ~ { class: PixelArrayClass ~ pa.class; value: Sample ฌ 0; action: PROC [map: SampleMap] ~ { class.Transfer[pa: pa, i: i, s: s, f: f, dst: map, dstMin: [0, 0], size: [1, 1], function: [null, null]]; value ฌ ImagerSample.Get[map: map, index: [0, 0]]; }; ImagerSample.DoWithScratchMap[[[0,0], [1, 1]], ImagerSample.maxBitsPerSample, action]; RETURN[value]; }; GetSamplesViaGet: PROC [pa: PixelArray, i: NAT, s, f: INT, buffer: SampleBuffer, start: NAT, count: NAT] ~ { class: PixelArrayClass ~ pa.class; FOR k: NAT IN[0..count) DO buffer[start+k] ฌ class.Get[pa: pa, i: i, s: s, f: f+k]; ENDLOOP; }; GetSamplesViaTransfer: PROC [pa: PixelArray, i: NAT, s, f: INT, buffer: SampleBuffer, start: NAT, count: NAT] ~ { class: PixelArrayClass ~ pa.class; action: PROC [map: SampleMap] ~ { class.Transfer[pa: pa, i: i, s: s, f: f, dst: map, dstMin: [0, 0], size: [s: 1, f: count], function: [null, null]]; ImagerSample.GetSamples[map: map, buffer: buffer, start: start, count: count]; }; ImagerSample.DoWithScratchMap[[[0, 0], [s: 1, f: count]], ImagerSample.maxBitsPerSample, action]; }; TransferViaGet: PROC [pa: PixelArray, i: NAT, s, f: INT, dst: SampleMap, dstMin: Vec, size: Vec, function: Function] ~ { class: PixelArrayClass ~ pa.class; FOR ks: NAT IN[0..size.s) DO FOR kf: NAT IN[0..size.f) DO value: Sample ~ class.Get[pa: pa, i: i, s: s+ks, f: f+kf]; ImagerSample.Put[map: dst, index: [s: dstMin.s+ks, f: dstMin.f+kf], value: value, function: function]; ENDLOOP; ENDLOOP; }; TransferViaGetSamples: PROC [pa: PixelArray, i: NAT, s, f: INT, dst: SampleMap, dstMin: Vec, size: Vec, function: Function] ~ { class: PixelArrayClass ~ pa.class; action: PROC [buffer: SampleBuffer] ~ { FOR k: NAT IN[0..size.s) DO class.GetSamples[pa: pa, i: i, s: s+k, f: f, buffer: buffer, start: 0, count: size.f]; ImagerSample.PutSamples[map: dst, initIndex: [s: dstMin.s+k, f: dstMin.f], delta: [s: 0, f: 1], buffer: buffer, function: function]; ENDLOOP; }; ImagerSample.DoWithScratchSamples[size.f, action]; }; NewClass: PUBLIC PROC [type: ATOM, MaxSampleValue: MaxSampleValueProc, Get: GetProc ฌ NIL, GetSamples: GetSamplesProc ฌ NIL, Transfer: TransferProc ฌ NIL, Copy: CopyProc ฌ NIL ] RETURNS [PixelArrayClass] ~ { class: PixelArrayClass ~ NEW[PixelArrayClassRep ฌ [ type: type, MaxSampleValue: MaxSampleValue, Get: Get, GetSamples: GetSamples, Transfer: Transfer, Copy: Copy ]]; IF Get=NIL THEN SELECT TRUE FROM GetSamples#NIL => class.Get ฌ GetViaGetSamples; Transfer#NIL => class.Get ฌ GetViaTransfer; ENDCASE; IF GetSamples=NIL THEN SELECT TRUE FROM Transfer#NIL => class.GetSamples ฌ GetSamplesViaTransfer; Get#NIL => class.GetSamples ฌ GetSamplesViaGet; ENDCASE; IF Transfer=NIL THEN SELECT TRUE FROM GetSamples#NIL => class.Transfer ฌ TransferViaGetSamples; Get#NIL => class.Transfer ฌ TransferViaGet; ENDCASE; RETURN[class]; }; New: PUBLIC PROC [class: PixelArrayClass, data: REF, immutable: BOOL, samplesPerPixel: NAT, sSize, fSize: INT, m: Transformation] RETURNS [PixelArray] ~ { RETURN[NEW[PixelArrayRep ฌ [immutable: immutable, samplesPerPixel: samplesPerPixel, sSize: Basics.NonNegative[sSize], fSize: Basics.NonNegative[fSize], m: m, class: class, data: data]]]; }; Layer: TYPE ~ RECORD [base: PixelArray, i: NAT]; extractedClass: PixelArrayClass ~ NewClass[ type: $Extracted, MaxSampleValue: ExtractedMaxSampleValue, Get: ExtractedGet, GetSamples: ExtractedGetSamples, Transfer: ExtractedTransfer ]; ExtractedData: TYPE ~ REF ExtractedDataRep; ExtractedDataRep: TYPE ~ RECORD [ base: PixelArray, select: SEQUENCE samplesPerPixel: NAT OF NAT ]; ExtractedLayer: PROC [data: ExtractedData, i: NAT] RETURNS [Layer] ~ { RETURN[[base: data.base, i: data.select[i]]]; }; ExtractedMaxSampleValue: MaxSampleValueProc ~ { data: ExtractedData ~ NARROW[pa.data]; layer: Layer ~ ExtractedLayer[data, i]; class: PixelArrayClass ~ layer.base.class; RETURN class.MaxSampleValue[pa: layer.base, i: layer.i]; }; ExtractedGet: GetProc ~ { data: ExtractedData ~ NARROW[pa.data]; layer: Layer ~ ExtractedLayer[data, i]; class: PixelArrayClass ~ layer.base.class; RETURN class.Get[pa: layer.base, i: layer.i, s: s, f: f]; }; ExtractedGetSamples: GetSamplesProc ~ { data: ExtractedData ~ NARROW[pa.data]; layer: Layer ~ ExtractedLayer[data, i]; class: PixelArrayClass ~ layer.base.class; class.GetSamples[pa: layer.base, i: layer.i, s: s, f: f, buffer: buffer, start: start, count: count]; }; ExtractedTransfer: TransferProc ~ { data: ExtractedData ~ NARROW[pa.data]; layer: Layer ~ ExtractedLayer[data, i]; class: PixelArrayClass ~ layer.base.class; class.Transfer[pa: layer.base, i: layer.i, s: s, f: f, dst: dst, dstMin: dstMin, size: size, function: function]; }; Extract: PUBLIC PROC [old: PixelArray, samplesPerPixel: NAT, select: PROC [NAT] RETURNS [NAT]] RETURNS [new: PixelArray] ~ { data: ExtractedData ~ NEW[ExtractedDataRep[samplesPerPixel]]; data.base ฌ old; FOR i: NAT IN [0..data.samplesPerPixel) DO data.select[i] ฌ BoundsCheck[select[i], old.samplesPerPixel]; ENDLOOP; RETURN[New[class: extractedClass, data: data, immutable: old.immutable, samplesPerPixel: samplesPerPixel, sSize: old.sSize, fSize: old.fSize, m: old.m]]; }; joinedClass: PixelArrayClass ~ NewClass[ type: $Joined, MaxSampleValue: JoinedMaxSampleValue, Get: JoinedGet, GetSamples: JoinedGetSamples, Transfer: JoinedTransfer ]; JoinedData: TYPE ~ LIST OF PixelArray; JoinedLayer: PROC [data: JoinedData, i: NAT] RETURNS [Layer] ~ { FOR each: LIST OF PixelArray ฌ data, each.rest UNTIL each=NIL DO base: PixelArray ~ each.first; IF iKšœ˜Kš žœžœžœžœ(žœ˜Zšžœ3žœ˜>KšœQ˜Q—K˜K˜—š   œžœžœžœ%žœžœ˜zKšœžœ˜0šžœžœžœ˜&Kšœ žœ˜Kšœ žœ ˜Kšœb˜bKšœžœ˜2Kšœ˜šžœžœžœž˜%KšœP˜PKšžœ˜—šžœ;˜AKšœG˜G—Kšœ˜—Kšžœ˜Kšœ˜K˜——K˜Kšžœ˜K˜—…—;J™