<> <> DIRECTORY AIS, Environment, FileIO, ImagerColor, ImagerBasic, IO, Rope, Scaled ; ImagerAISImpl: CEDAR PROGRAM IMPORTS AIS, FileIO, IO, Rope, Scaled EXPORTS ImagerColor ~ BEGIN blockHeight: NAT ~ 32; blockWidth: NAT ~ 64; Block: TYPE ~ REF BlockRep; BlockRep: TYPE ~ ARRAY [0..blockHeight) OF ChunkRep; ChunkRep: TYPE ~ PACKED ARRAY [0..blockWidth) OF [0..256); BufferRep: TYPE ~ RECORD [ SEQUENCE numberOfChunks: NAT OF ChunkRep ]; LoadAISData: PROC [aisName: Rope.ROPE] RETURNS [reblockedAIS: ReblockedAIS] ~ TRUSTED { text: Rope.Text _ aisName.Flatten; ais: AIS.FRef _ AIS.OpenFile[LOOPHOLE[text], FALSE]; window: AIS.WRef _ AIS.OpenWindow[ais]; numberOfChunksAcross: NAT _ MAX[(ais.raster.scanLength+blockWidth-1)/blockWidth, 1]; bufferRef: REF BufferRep _ NEW[BufferRep[numberOfChunksAcross]]; buffer: AIS.Buffer _ [numberOfChunksAcross*SIZE[ChunkRep], @bufferRef[0]]; rowNumber: NAT _ 0; file: IO.STREAM _ FileIO.Open[aisName.Concat[".reblocked$"], write]; numberOfBuffers: NAT _ MAX[numberOfChunksAcross, ais.raster.scanCount/blockHeight] + 2; block: REF BufferSeqRep _ NEW[BufferSeqRep[numberOfBuffers]]; FlushBuffers: PROC ~ TRUSTED { byteSize: INT ~ INT[Environment.bytesPerWord]*SIZE[BlockRep]; FOR i: NAT IN [0..numberOfChunksAcross) DO file.UnsafePutBlock[[base: @(block[i].block[0]), startIndex: 0, stopIndexPlusOne: byteSize]]; ENDLOOP; rowNumber _ 0; }; IF ais.raster.bitsPerPixel # 8 THEN ERROR; FOR i: NAT IN [0..numberOfBuffers) DO block[i] _ [LAST[NAT], LAST[NAT], NEW[BlockRep]] ENDLOOP; FOR line: NAT IN [0..ais.raster.scanCount) DO window.ReadLine[buffer, line]; FOR chunkNumber: NAT IN [0..numberOfChunksAcross) DO block[chunkNumber].block[rowNumber] _ bufferRef[chunkNumber]; ENDLOOP; rowNumber _ rowNumber + 1; IF rowNumber >= blockHeight THEN FlushBuffers[]; ENDLOOP; IF rowNumber > 0 THEN FlushBuffers[]; reblockedAIS _ NEW[ReblockedAISRep]; reblockedAIS.file _ file; reblockedAIS.scanCount _ ais.raster.scanCount; reblockedAIS.scanLength _ ais.raster.scanLength; reblockedAIS.scanMode _ ais.raster.scanMode; reblockedAIS.numberOfChunksAcross _ numberOfChunksAcross; ais.CloseFile; reblockedAIS.nextBufferToAllocate _ 0; reblockedAIS.bufferSeq _ block; }; <> <> <> <> <<>> <> <> <> <> <> <> <> < {curLine_0; curPixel_0; xNextLine_0; xNextPixel_1; yNextLine_1; yNextPixel_0};>> <
    {curLine_xPixels-1; curPixel_0; xNextLine_-1; xNextPixel_0; yNextLine_0; yNextPixel_1};>> < {curLine_yPixels-1; curPixel_xPixels-1; xNextLine_0; xNextPixel_-1; yNextLine_-1; yNextPixel_0};>> < {curLine_0; curPixel_yPixels-1; xNextLine_1; xNextPixel_0; yNextLine_0; yNextPixel_-1};>> < {curLine_yPixels-1; curPixel_0; xNextLine_0; xNextPixel_1; yNextLine_-1; yNextPixel_0};>> < {curLine_0; curPixel_0; xNextLine_1; xNextPixel_0; yNextLine_0; yNextPixel_1};>> < {curLine_0; curPixel_xPixels-1; xNextLine_0; xNextPixel_-1; yNextLine_1; yNextPixel_0};>> <
    {curLine_curLine_xPixels-1; curPixel_yPixels-1; xNextLine_-1; xNextPixel_0; yNextLine_0; yNextPixel_-1};>> < ERROR;>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<};>> ReblockedAIS: TYPE ~ REF ReblockedAISRep; ReblockedAISRep: TYPE ~ RECORD [ file: IO.STREAM, scanLength: NAT, scanCount: NAT, scanMode: AIS.ScanMode, numberOfChunksAcross: NAT, nextBufferToAllocate: NAT _ 0, bufferSeq: REF BufferSeqRep ]; BufferSeqRep: TYPE ~ RECORD [ SEQUENCE length: NAT OF BufferDescriptor ]; BufferDescriptor: TYPE ~ RECORD [ xDivBlockWidth, yDivBlockHeight: NAT, block: Block ]; AISToColor: PUBLIC PROC [aisName: Rope.ROPE] RETURNS [ImagerBasic.Color] ~ { pixelArray: ImagerBasic.PixelArray _ NEW[ImagerBasic.PixelArrayRep]; color: ImagerBasic.SampledColor _ NEW[ImagerBasic.SampledColorRep]; reblockedAIS: ReblockedAIS _ LoadAISData[aisName]; SELECT reblockedAIS.scanMode FROM ru, lu, rd, ld => {pixelArray.xPixels _ reblockedAIS.scanLength; pixelArray.yPixels _ reblockedAIS.scanCount}; ur, ul, dr, dl => {pixelArray.xPixels _ reblockedAIS.scanCount; pixelArray.yPixels _ reblockedAIS.scanLength}; ENDCASE => ERROR; pixelArray.maxSampleValue _ 255; pixelArray.samplesPerPixel _ 1; pixelArray.get _ GetOne; pixelArray.data _ reblockedAIS; color.transparent _ FALSE; color.pa _ pixelArray; color.m _ [1, 0, 0, 0, 1, 0, identity]; color.colorMap _ $Intensity8bpp; RETURN [color]; }; GetOne: PROC [self: ImagerBasic.PixelArray, buffer: ImagerBasic.PixelBuffer, nSamples: NAT, layer: INT, xStart, yStart: Scaled.Value, xDelta, yDelta: Scaled.Value] ~ { reblockedAIS: ReblockedAIS _ NARROW[self.data]; curBuf: BufferDescriptor; SELECT reblockedAIS.scanMode FROM ru => NULL; rd => {yStart _ Scaled.FromInt[reblockedAIS.scanCount].MINUS[yStart]; yDelta _ yDelta.UMINUS}; ENDCASE => ERROR; FOR i: NAT IN [0..nSamples) DO y: INTEGER _ yStart.Floor; x: INTEGER _ xStart.Floor; IF NOT x IN [0..reblockedAIS.scanLength) THEN { WHILE x < 0 DO x _ x + reblockedAIS.scanLength ENDLOOP; WHILE x >= reblockedAIS.scanLength DO x _ x - reblockedAIS.scanLength ENDLOOP; xStart.integerPart _ x; }; IF NOT y IN [0..reblockedAIS.scanCount) THEN { WHILE y < 0 DO y _ y + reblockedAIS.scanCount ENDLOOP; WHILE y >= reblockedAIS.scanCount DO y _ y - reblockedAIS.scanCount ENDLOOP; yStart.integerPart _ y; }; IF NAT[x]/blockWidth # curBuf.xDivBlockWidth OR NAT[y]/blockHeight # curBuf.yDivBlockHeight THEN { xDivBlockWidth: NAT _ NAT[x]/blockWidth; yDivBlockHeight: NAT _ NAT[y]/blockHeight; FOR j: NAT IN [0..reblockedAIS.bufferSeq.length) DO curBuf _ reblockedAIS.bufferSeq[j]; IF xDivBlockWidth = curBuf.xDivBlockWidth AND yDivBlockHeight = curBuf.yDivBlockHeight THEN EXIT; ENDLOOP; IF xDivBlockWidth # curBuf.xDivBlockWidth OR yDivBlockHeight # curBuf.yDivBlockHeight THEN TRUSTED { byteSize: INT ~ INT[Environment.bytesPerWord]*SIZE[BlockRep]; curBuf _ reblockedAIS.bufferSeq[reblockedAIS.nextBufferToAllocate]; curBuf.xDivBlockWidth _ xDivBlockWidth; curBuf.yDivBlockHeight _ yDivBlockHeight; reblockedAIS.file.SetIndex[(INT[yDivBlockHeight]*reblockedAIS.numberOfChunksAcross+xDivBlockWidth)*(INT[Environment.bytesPerWord]*SIZE[BlockRep])]; [] _ reblockedAIS.file.UnsafeGetBlock[[base: @(curBuf.block[0]), startIndex: 0, stopIndexPlusOne: byteSize]]; reblockedAIS.bufferSeq[reblockedAIS.nextBufferToAllocate] _ curBuf; reblockedAIS.nextBufferToAllocate _ reblockedAIS.nextBufferToAllocate + 1; IF reblockedAIS.nextBufferToAllocate >= reblockedAIS.bufferSeq.length THEN reblockedAIS.nextBufferToAllocate _ 0; }; }; buffer[i] _ curBuf.block[NAT[y] MOD blockHeight][NAT[x] MOD blockWidth]; xStart _ xStart.PLUS[xDelta]; yStart _ yStart.PLUS[yDelta]; ENDLOOP; }; END.