<> <> <> <> <> <<>> DIRECTORY Basics, IO, PressImage, PressReader, ImagerPixelArray, ImagerColorOperator, Imager, ImagerTransformation, ImagerPixelMap, ImagerPixelArrayPrivate, SafeStorage, ImagerPixelArrayDefs, ImagerSample, PrincOps, PrincOpsUtils; <<>> PressImageImpl: CEDAR PROGRAM IMPORTS Basics, IO, ImagerPixelMap, ImagerPixelArray, ImagerColorOperator, Imager, ImagerTransformation, SafeStorage, ImagerSample, PrincOpsUtils EXPORTS PressImage, ImagerPixelArrayDefs = BEGIN Context: TYPE = Imager.Context; Transformation: TYPE = ImagerTransformation.Transformation; PixelArray: TYPE = ImagerPixelArrayDefs.PixelArray; PixelMap: TYPE = ImagerPixelMap.PixelMap; ru: NAT = 2; rd: NAT = 3; lu: NAT = 6; ld: NAT = 7; ul: NAT = 9; ur: NAT = 8; dl: NAT = 13; dr: NAT = 12; TransformationFromScanMode: PROC [scanMode: NAT, lines, pixelsPerLine: INT] RETURNS [Transformation] ~ { pixelDeltaX: REAL _ SELECT scanMode FROM ru, rd => 1, lu, ld => -1, ENDCASE => 0; pixelDeltaY: REAL _ SELECT scanMode FROM ul, ur => 1, dr, dl => -1, ENDCASE => 0; lineDeltaX: REAL _ SELECT scanMode FROM dr, ur => 1, ul, dl => -1, ENDCASE => 0; lineDeltaY: REAL _ SELECT scanMode FROM ru, lu => 1, ld, rd => -1, ENDCASE => 0; RETURN [ImagerTransformation.Create[ a: lineDeltaX, b: pixelDeltaX, c: MAX[-(pixelDeltaX*pixelsPerLine + lineDeltaX*lines), 0], d: lineDeltaY, e: pixelDeltaY, f: MAX[-(pixelDeltaY*pixelsPerLine + lineDeltaY*lines), 0] ]] }; PressImage: PUBLIC TYPE = REF PressImageData; PressImageData: PUBLIC TYPE = RECORD [ stream: IO.STREAM, streamIndex: INT, byteLength: INT, scanMode: CARDINAL, scanCount: CARDINAL, -- lines scanLength: CARDINAL, -- dots wordsPerLine: CARDINAL, -- words per scan line passDots: NAT, displayDots: NAT, passLines: NAT, displayLines: NAT, imageHeight: REAL, imageWidth: REAL, lgBitsPerPixel: [0..4], isBitmap: BOOL ]; PressImageError: PUBLIC ERROR = CODE; MakePressImage: PUBLIC PROC [sampleType, dots, lines, mode, pd, dd, pl, dl: INT, width, height: REAL, bits: PressReader.Dots] RETURNS [self: PressImage _ NIL] = { bitsperline: LONG CARDINAL _ Basics.LongMult[dots, IF sampleType IN [1..16] THEN sampleType ELSE 1]; wpl: CARDINAL _ (bitsperline + (bitsPerWord-1)) / bitsPerWord; lgBitsPerPixel: [0..4] ~ SELECT sampleType FROM 0, 1 => 0, 2 => 1, 4 => 2, 8 => 3, 16 => 4, ENDCASE => ERROR PressImageError; IF bitsperline MOD bitsPerWord # 0 THEN ERROR PressImageError; self _ NEW[PressImageData _ [ stream: bits.file, streamIndex: LONG[bits.pageNumber]*512+bits.byteOffset, byteLength: bits.length*Basics.bytesPerWord, -- bits.length is in words! scanMode: mode, scanCount: lines, scanLength: dots, wordsPerLine: wpl, passDots: pd, displayDots: dd, passLines: pl, displayLines: dl, imageHeight: height, imageWidth: width, lgBitsPerPixel: lgBitsPerPixel, isBitmap: sampleType = 0 ]]; RETURN [self]; }; PixelArrayImpl: TYPE ~ ImagerPixelArrayPrivate.PixelArrayImpl; PixelArrayImplRep: PUBLIC TYPE ~ ImagerPixelArrayPrivate.PixelArrayImplRep; <> <<>> PixelArrayClass: TYPE ~ REF PixelArrayClassRep; PixelArrayClassRep: PUBLIC TYPE ~ ImagerPixelArrayPrivate.PixelArrayClassRep; pixelArrayClass: PixelArrayClass ~ NEW[PixelArrayClassRep _ [ type: $PressImage, MaxSampleValue: MyMaxSampleValue, UnsafeGetSamples: MyUnsafeGetSamples, UnsafeGetBits: MyUnsafeGetBits ]]; MyMaxSampleValue: PROC [pa: PixelArray, i: NAT] RETURNS [ImagerPixelArray.Sample] ~ { impl: PixelArrayImpl ~ pa.impl; data: REF PixelMap ~ NARROW[pa.data]; pm: PixelMap ~ data^; lgBitsPerPixel: [0..4] _ pm.refRep.lgBitsPerPixel; RETURN [Basics.BITSHIFT[1, Basics.BITSHIFT[1, lgBitsPerPixel]]-1] }; MyUnsafeGetSamples: UNSAFE PROC [pa: PixelArray, i: NAT, s, f: INT, samples: ImagerSample.UnsafeSamples, count: NAT] ~ UNCHECKED { data: REF PixelMap ~ NARROW[pa.data]; ImagerSample.UnsafeGetF[samples: samples, count: count, base: data.refRep.pointer, wordsPerLine: data.refRep.rast, bitsPerSample: Basics.BITSHIFT[1, data.refRep.lgBitsPerPixel], s: s+data.sOrigin, f: f+data.fOrigin]; }; bitsPerWord: NAT ~ Basics.bitsPerWord; MyUnsafeGetBits: UNSAFE PROC [pa: PixelArray, i: NAT _ 0, s, f: INT, dst: PrincOps.BitAddress, dstBpl: INTEGER, width, height: CARDINAL, srcFunc: PrincOps.SrcFunc _ null, dstFunc: PrincOps.DstFunc _ null] ~ UNCHECKED { data: REF PixelMap ~ NARROW[pa.data]; source: PixelMap ~ data^; sStartSource: NAT ~ s-source.sOrigin; fMinSource: NAT ~ f-source.fOrigin; bbTableSpace: PrincOps.BBTableSpace; bb: PrincOps.BBptr ~ PrincOpsUtils.AlignedBBTable[@bbTableSpace]; IF source.refRep.lgBitsPerPixel # 0 THEN ERROR; bb^ _ [ dstBpl: dstBpl, srcDesc: [srcBpl[source.refRep.rast*bitsPerWord]], height: height, width: width, flags: [direction: forward, disjoint: TRUE, disjointItems: TRUE, gray: FALSE, srcFunc: srcFunc, dstFunc: dstFunc], dst: dst, src: [word: (source.refRep.pointer + Basics.LongMult[sStartSource, source.refRep.rast] + (fMinSource/bitsPerWord)), bit: fMinSource MOD bitsPerWord] ]; PrincOpsUtils.BITBLT[bb]; }; identity: Transformation ~ ImagerTransformation.Scale[1]; MakePixelArray: PROC [pressImage: PressImage] RETURNS [ImagerPixelArray.PixelArray] ~ { pm: PixelMap ~ ImagerPixelMap.Create[lgBitsPerPixel: pressImage.lgBitsPerPixel, bounds: [0, 0, pressImage.scanCount, pressImage.scanLength]]; IF INT[pm.refRep.words*Basics.bytesPerWord] < pressImage.byteLength THEN ERROR PressImageError; IO.SetIndex[pressImage.stream, pressImage.streamIndex]; TRUSTED { [] _ IO.UnsafeGetBlock[pressImage.stream, [LOOPHOLE[pm.refRep.pointer], 0, pressImage.byteLength]]; }; RETURN [NEW[ImagerPixelArrayDefs.PixelArrayRep _ [ samplesPerPixel: 1, sSize: pressImage.displayLines, fSize: pressImage.displayDots, m: TransformationFromScanMode[pressImage.scanMode, pressImage.displayLines, pressImage.displayDots], impl: NIL, class: pixelArrayClass, data: NEW[PixelMap _ pm.ShiftMap[-pressImage.passLines, -pressImage.passDots].Clip[[0,0,pressImage.displayLines, pressImage.displayDots]]] ]]]; }; DrawPressImage: PUBLIC PROC [self: Context, image: PressImage] = { Proc: PROC ~ { pa: ImagerPixelArray.PixelArray ~ MakePixelArray[image]; paDimen: Imager.VEC ~ ImagerTransformation.TransformVec[pa.m, [pa.sSize, pa.fSize]]; Imager.Move[self]; Imager.Scale2T[self, [image.imageWidth/ABS[paDimen.x], image.imageHeight/ABS[paDimen.y]]]; IF image.isBitmap THEN { WhiteBackground: PROC ~ { Imager.SetColor[self, Imager.white]; Imager.MaskRectangle[self, [0, 0, ABS[paDimen.x], ABS[paDimen.y]]]; }; IF TRUE -- NOT show dots opaque -- THEN Imager.DoSave[self, WhiteBackground]; Imager.MaskPixel[context: self, pa: pa]; } ELSE { maxSampleValue: INT ~ ImagerPixelArray.MaxSampleValue[pa, 0]; SampleMap: PROC [cardinal: CARDINAL] RETURNS [REAL] ~ { RETURN [cardinal] }; colorOperator: ImagerColorOperator.ColorOperator ~ ImagerColorOperator.GrayLinearColorModel[ sWhite: maxSampleValue, sBlack: 0.0, maxSampleValue: maxSampleValue, sampleMap: SampleMap ]; Imager.SetSampledColor[ context: self, pa: pa, m: identity, colorOperator: colorOperator ]; Imager.MaskRectangle[self, [0, 0, ABS[paDimen.x], ABS[paDimen.y]]]; }; }; Imager.DoSave[self, Proc]; SafeStorage.ReclaimCollectibleObjects[]; }; END. <<>> <> <<>> <> <> <<>> <> <> <<>> <> < VM)>> <<>> <> <> <<>> <> <> <<>>