<<>> <> <> <> <> 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 i> Join3: PUBLIC PROC [pa1, pa2, pa3: PixelArray] RETURNS [PixelArray] ~ { RETURN[Join[LIST[pa1, pa2, pa3]]]; }; pixelMapClass: PixelArrayClass ~ NewClass[ type: $PixelMap, MaxSampleValue: PixelMapMaxSampleValue, Get: PixelMapGet, GetSamples: PixelMapGetSamples, Transfer: PixelMapTransfer, Copy: PixelMapCopy ]; PixelMapData: TYPE ~ PixelMap; PixelMapMaxSampleValue: MaxSampleValueProc ~ { data: PixelMapData ~ NARROW[pa.data]; map: SampleMap ~ data[i]; RETURN[Basics.BITSHIFT[1, ImagerSample.GetBitsPerSample[map]]-1]; }; PixelMapGet: GetProc ~ { data: PixelMapData ~ NARROW[pa.data]; map: SampleMap ~ data[i]; index: Vec ~ [s: s, f: f]; RETURN[map.Get[index]]; }; PixelMapGetSamples: GetSamplesProc ~ { data: PixelMapData ~ NARROW[pa.data]; map: SampleMap ~ data[i]; index: Vec ~ [s: s, f: f]; ImagerSample.GetSamples[map: map, initIndex: index, buffer: buffer, start: start, count: count]; }; PixelMapTransfer: TransferProc ~ { data: PixelMapData ~ NARROW[pa.data]; map: SampleMap ~ data[i]; index: Vec ~ [s: s, f: f]; ImagerSample.BasicTransfer[dst: dst, src: map, dstMin: dstMin, srcMin: index, size: size, function: function]; }; PixelMapCopy: CopyProc ~ { data0: PixelMapData ~ NARROW[pa.data]; data1: PixelMapData ~ NEW[PixelMapRep[data0.samplesPerPixel]]; data1.box ¬ data0.box; FOR i: NAT IN[0..data1.samplesPerPixel) DO data1[i] ¬ ImagerSample.Copy[data0[i]] ENDLOOP; RETURN[New[class: pixelMapClass, data: data1, immutable: TRUE, samplesPerPixel: pa.samplesPerPixel, sSize: pa.sSize, fSize: pa.fSize, m: pa.m]]; }; FromPixelMap: PUBLIC PROC [pixelMap: PixelMap, box: SF.Box, scanMode: ScanMode, immutable: BOOL] RETURNS [PixelArray] ~ { samplesPerPixel: NAT ~ pixelMap.samplesPerPixel; IF SF.Inside[box, pixelMap.box] THEN { delta: Vec ~ SF.Neg[box.min]; size: Vec ~ SF.Size[box]; m: Transformation ~ ImagerTransformation.SFToXY[scanMode: scanMode, sSize: size.s, fSize: size.f]; new: PixelMap ¬ NEW[PixelMapRep[samplesPerPixel]]; new.box ¬ [max: size]; FOR j: NAT IN [0..samplesPerPixel) DO new[j] ¬ ImagerSample.ReIndex[map: pixelMap[j], delta: delta, box: [max: size]]; ENDLOOP; RETURN[New[class: pixelMapClass, data: new, immutable: immutable, samplesPerPixel: samplesPerPixel, sSize: size.s, fSize: size.f, m: m]]; }; ERROR RuntimeError.BoundsFault; }; END.