DIRECTORY AIS, ConvertUnsafe, Directory, Graphics, GraphicsColor, GraphicsOps, MessageWindow, ReadAIS, Real, Rope, SV2d, SVBoundBox, SVFiles, SVImage, SVVector2d; SVImageImpl: PROGRAM IMPORTS AIS, ConvertUnsafe, Directory, Graphics, GraphicsColor, GraphicsOps, MessageWindow, ReadAIS, Real, Rope, SVFiles, SVVector2d EXPORTS SVImage = BEGIN Image: TYPE = REF ImageObj; ImageObj: TYPE = SVImage.ImageObj; BoundBox: TYPE = REF BoundBoxObj; BoundBoxObj: TYPE = SVBoundBox.BoundBoxObj; Color: TYPE = GraphicsColor.Color; ImageRef: TYPE = GraphicsOps.ImageRef; Mark: TYPE = Graphics.Mark; Point2d: TYPE = SV2d.Point2d; WRef: TYPE = AIS.WRef; FRef: TYPE = AIS.FRef; IsEven: PRIVATE PROC [n: NAT] RETURNS [BOOL] = { RETURN [(n/2)*2 = n]; }; RoundDown: PRIVATE PROC [r: REAL] RETURNS [rDown: INTEGER] = { IF r = 0 THEN RETURN[0]; IF r > 0 THEN { rDown _ Real.FixI[r]; RETURN} ELSE { r _ -r;-- make it positive rDown _ Real.FixI[r]; rDown _ rDown + 1; rDown _ - rDown; }; }; RoundUp: PRIVATE PROC [r: REAL] RETURNS [rUp: INTEGER] = { IF r = 0 THEN RETURN[0]; IF r > 0 THEN { rUp _ Real.FixI[r]; rUp _ rUp + 1; RETURN} ELSE { r _ -r;-- make it positive rUp _ Real.FixI[r]; rUp _ - rUp; }; }; CountSamples: PRIVATE PROC [realMinX, realMinY, realMaxX, realMaxY, resolution: REAL] RETURNS [numberOfSamplesX, numberOfSamplesY: NAT] = { xExtent, yExtent, realSamplesX, realSamplesY: REAL; xExtent _ realMaxX - realMinX; -- x extent in screen dots yExtent _ realMaxY - realMinY; -- y extent in screen dots realSamplesX _ (xExtent*resolution)/72.0; realSamplesY _ (yExtent*resolution)/72.0; numberOfSamplesX _ Real.FixI[realSamplesX] + 2; numberOfSamplesY _ Real.FixI[realSamplesY] + 2; IF NOT IsEven[numberOfSamplesX] THEN numberOfSamplesX _ numberOfSamplesX + 1; IF NOT IsEven[numberOfSamplesY] THEN numberOfSamplesY _ numberOfSamplesY + 1; }; -- end of CountSamples OpenImage: PUBLIC PROC [aisRope: Rope.ROPE, bAndWOnly: BOOL, realMinX, realMinY, realMaxX, realMaxY, resolution: REAL, raster: AIS.Raster, commentString: LONG STRING] RETURNS [I: Image, numberOfSamplesX, numberOfSamplesY: NAT] = { f: AIS.FRef; I _ NEW[ImageObj]; [numberOfSamplesX, numberOfSamplesY] _ CountSamples[realMinX, realMinY, realMaxX, realMaxY, resolution]; raster^ _ [numberOfSamplesY, numberOfSamplesX, rd, 8, -1, 65535]; IF bAndWOnly THEN { bwString: LONG STRING _ [30]; I.bAndWOnly _ TRUE; ConvertUnsafe.AppendRope[bwString, aisRope]; f _ ReadAIS.CreateFile[bwString, raster, commentString, TRUE, 0, resolution]; I.bwWindow _ AIS.OpenWindow[f]; } ELSE { redRope: Rope.ROPE _ Rope.Concat[SVFiles.FilenameMinusExtension[aisRope], "-red.ais"]; greenRope: Rope.ROPE _ Rope.Concat[SVFiles.FilenameMinusExtension[aisRope], "-green.ais"]; blueRope: Rope.ROPE _ Rope.Concat[SVFiles.FilenameMinusExtension[aisRope], "-blue.ais"]; bwRope: Rope.ROPE _ aisRope; redString: LONG STRING _ [30]; greenString: LONG STRING _ [30]; blueString: LONG STRING _ [30]; bwString: LONG STRING _ [30]; I.bAndWOnly _ FALSE; ConvertUnsafe.AppendRope[bwString, bwRope]; ConvertUnsafe.AppendRope[redString, redRope]; ConvertUnsafe.AppendRope[greenString, greenRope]; ConvertUnsafe.AppendRope[blueString, blueRope]; f _ ReadAIS.CreateFile[redString, raster, commentString, TRUE, 0, resolution]; I.redWindow _ AIS.OpenWindow[f]; f _ ReadAIS.CreateFile[greenString, raster, commentString, TRUE, 0, resolution]; I.greenWindow _ AIS.OpenWindow[f]; f _ ReadAIS.CreateFile[blueString, raster, commentString, TRUE, 0, resolution]; I.blueWindow _ AIS.OpenWindow[f]; f _ ReadAIS.CreateFile[bwString, raster, commentString, TRUE, 0, resolution]; I.bwWindow _ AIS.OpenWindow[f]; }; MessageWindow.Append[" New "]; MessageWindow.Append[aisRope]; MessageWindow.Append["'s created."]; };-- end of OpenImage DeleteFile: PRIVATE PROC [name: Rope.ROPE] = { success: BOOL; nameString: LONG STRING _ [20]; ConvertUnsafe.AppendRope[nameString, name]; success _ AIS.DeleteFile[nameString]; IF NOT success THEN {MessageWindow.Append["No "]; MessageWindow.Append[name]; MessageWindow.Append[". "];} ELSE { MessageWindow.Append[name]; MessageWindow.Append["... "]; }; };-- end of DeleteFile Truncate: PROC [value: REAL] RETURNS [m: CARDINAL] = { SELECT value FROM <0 => ERROR; >255.0 => m _ 255; ENDCASE => m _ Real.FixC[value]; }; PutImage2: PROC [I: Image, i, j: INTEGER, color: Color, minX, maxX, minY, maxY: INTEGER] = { intRed, intGreen, intBlue, intIntensity: CARDINAL; red, green, blue: REAL; [red, green, blue] _ GraphicsColor.ColorToRGB [color]; intRed _ Truncate[red*255.0]; intGreen _ Truncate[green*255.0]; intBlue _ Truncate[blue*255.0]; intIntensity _ Truncate[GraphicsColor.ColorToIntensity[color]*255.0]; AIS.WriteSample[I.redWindow, intRed, maxY - i, j - minX]; AIS.WriteSample[I.greenWindow, intGreen, maxY - i, j - minX]; AIS.WriteSample[I.blueWindow, intBlue, maxY - i, j - minX]; AIS.WriteSample[I.bwWindow, intIntensity, maxY - i, j - minX]; }; PutImage: PUBLIC PROC [I: Image, i, j: INTEGER, color: Color, xSamples, ySamples: NAT] = { IF I.bAndWOnly THEN { intIntensity: CARDINAL; intIntensity _ Truncate[GraphicsColor.ColorToIntensity[color]*255.0]; AIS.WriteSample[I.bwWindow, intIntensity, ySamples-i, j]; } ELSE { intRed, intGreen, intBlue, intIntensity: CARDINAL; red, green, blue: REAL; [red, green, blue] _ GraphicsColor.ColorToRGB [color]; intRed _ Truncate[red*255.0]; intGreen _ Truncate[green*255.0]; intBlue _ Truncate[blue*255.0]; intIntensity _ Truncate[GraphicsColor.ColorToIntensity[color]*255.0]; AIS.WriteSample[I.redWindow, intRed, ySamples-i, j]; AIS.WriteSample[I.greenWindow, intGreen, ySamples-i, j]; AIS.WriteSample[I.blueWindow, intBlue, ySamples-i, j]; AIS.WriteSample[I.bwWindow, intIntensity, ySamples-i, j]; }; }; CloseImage: PUBLIC PROC [I: Image, aisRope: Rope.ROPE] = { f: AIS.FRef; IF I.bAndWOnly THEN { f _ I.bwWindow.fref; AIS.CloseWindow[I.bwWindow]; AIS.CloseFile[f]; MessageWindow.Append[aisRope]; MessageWindow.Append[" now closed"]; MessageWindow.Blink[]; } ELSE { f _ I.blueWindow.fref; AIS.CloseWindow[I.blueWindow]; AIS.CloseFile[f]; f _ I.bwWindow.fref; AIS.CloseWindow[I.bwWindow]; AIS.CloseFile[f]; f _ I.redWindow.fref; AIS.CloseWindow[I.redWindow]; AIS.CloseFile[f]; f _ I.greenWindow.fref; AIS.CloseWindow[I.greenWindow]; AIS.CloseFile[f]; MessageWindow.Append[" (red green blue BandW) "]; MessageWindow.Append[aisRope]; MessageWindow.Append[" now closed"]; MessageWindow.Blink[]; }; }; -- end of CloseImage BoundBoxOfImage: PRIVATE PROC [image: ImageRef, resolution: REAL _ 72.0] RETURNS [boundBox: BoundBox] = { xmin,ymin,xmax,ymax, xExtent, yExtent: REAL; [xmin,ymin,xmax,ymax] _ GraphicsOps.ImageBox[image]; xExtent _ xmax - xmin; yExtent _ ymax - ymin; xExtent _ (xExtent/resolution)*72.0; yExtent _ (yExtent/resolution)*72.0; boundBox _ NEW[BoundBoxObj]; boundBox.minVert _ [0,0,0]; boundBox.maxVert _ [xExtent,yExtent, 0]; }; NewBlackAndWhiteImage: PUBLIC PROC [imageName: Rope.ROPE] RETURNS [image: ImageRef, success: BOOL] = { bwName: Rope.ROPE _ Rope.Concat[SVFiles.FilenameMinusExtension[imageName],".ais"]; success _ TRUE; image _ GraphicsOps.NewAisImage[imageName !Directory.Error => {success _ FALSE; CONTINUE}]; IF NOT success THEN { MessageWindow.Append["Open AIS file failed", TRUE]; MessageWindow.Blink[]; RETURN}; }; NewColorImage: PUBLIC PROC [imageName: Rope.ROPE] RETURNS [redimage, greenimage, blueimage: ImageRef, success: BOOL] = { redName: Rope.ROPE _ Rope.Concat[SVFiles.FilenameMinusExtension[imageName],"-red.ais"]; greenName: Rope.ROPE _ Rope.Concat[SVFiles.FilenameMinusExtension[imageName],"-green.ais"]; blueName: Rope.ROPE _ Rope.Concat[SVFiles.FilenameMinusExtension[imageName],"-blue.ais"]; success _ TRUE; redimage _ GraphicsOps.NewAisImage[redName !Directory.Error => {success _ FALSE; CONTINUE}]; greenimage _ GraphicsOps.NewAisImage[greenName !Directory.Error => {success _ FALSE; CONTINUE}]; blueimage _ GraphicsOps.NewAisImage[blueName !Directory.Error => {success _ FALSE; CONTINUE}]; IF NOT success THEN { MessageWindow.Append["Open AIS file failed", TRUE]; MessageWindow.Blink[]; RETURN}; }; DrawAlignedBlackAndWhiteImage: PUBLIC PROC [dc: Graphics.Context, imageName: Rope.ROPE, resolution: REAL, screenWRTCamera: Point2d, boundBox: BoundBox, raw: BOOL] = { info: ReadAIS.MyAISInfo; stepSize, xStart, yStart: REAL; lowerLeft, upperRight: Point2d; samplesX, samplesY: NAT; mark: Mark; success: BOOL; extentX, extentY, projectionX, projectionY, trueExtentX, trueExtentY: REAL; [info, success] _ ReadAIS.Read[imageName]; IF NOT success THEN RETURN; [samplesX, samplesY] _ ReadAIS.SamplesFromInfo[info]; stepSize _ 72.0/resolution; -- in screen dots per sample lowerLeft _ SVVector2d.Difference[[boundBox.minVert[1], boundBox.minVert[2]], screenWRTCamera]; upperRight _ SVVector2d.Difference[[boundBox.maxVert[1], boundBox.maxVert[2]], screenWRTCamera]; extentX _ boundBox.maxVert[1] - boundBox.minVert[1]; extentY _ boundBox.maxVert[2] - boundBox.minVert[2]; trueExtentX _ Real.Float[samplesX-1]*stepSize; trueExtentY _ Real.Float[samplesY-1]*stepSize; projectionX _ (trueExtentX - extentX)/2.0; projectionY _ (trueExtentY - extentY)/2.0; xStart _ lowerLeft[1] - projectionX; yStart _ lowerLeft[2] - projectionY; xStart _ xStart - stepSize/2.0; yStart _ yStart - stepSize/2.0; mark _ Graphics.Save[dc]; Graphics.Translate[dc, xStart, yStart]; DrawBlackAndWhiteImage[dc, imageName, boundBox, resolution, raw]; Graphics.Restore[dc, mark]; }; DrawBlackAndWhiteImage: PUBLIC PROC [dc: Graphics.Context, imageName: Rope.ROPE, clipBox: BoundBox _ NIL, resolution: REAL _ 72.0, raw: BOOL] = { minX, maxX, minY, maxY: REAL; clipPath: Graphics.Path _ Graphics.NewPath[4]; lowerLeft, upperRight: Point2d; image: ImageRef; success: BOOL; scale: REAL; mark: Mark; [image, success] _ NewBlackAndWhiteImage[imageName]; IF NOT success THEN RETURN; IF clipBox = NIL THEN clipBox _ BoundBoxOfImage[image, resolution]; lowerLeft _ [0,0];-- screen coords upperRight _ SVVector2d.Sum[[clipBox.maxVert[1], clipBox.maxVert[2]], lowerLeft];-- screen coords minX _ lowerLeft[1]; maxX _ upperRight[1] +1; minY _ lowerLeft[2]; maxY _ upperRight[2] +1; scale _ 72.0/resolution; mark _ Graphics.Save[dc]; Graphics.SetCP[dc, 0, 0];-- put lower left corner of image at this new origin Graphics.SetColor[dc, GraphicsColor.black]; Graphics.Scale[dc, scale, scale]; Graphics.DrawImage[dc, image]; Graphics.Restore[dc, mark]; }; DrawAndScaleBlackAndWhiteImage: PUBLIC PROC [dc: Graphics.Context, imageName: Rope.ROPE, screenWRTCamera: Point2d, realMinX, realMinY, realMaxX, realMaxY: REAL] = { minX, maxX, minY, maxY: INTEGER; clipPath: Graphics.Path _ Graphics.NewPath[4]; lowerLeft, upperRight: Point2d; screenOrigin: Point2d; success: BOOL _ TRUE; image: ImageRef; imageXmin, imageYmin, imageXmax, imageYmax, xScale, yScale: REAL; mark: Mark _ Graphics.Save[dc]; [image, success] _ NewBlackAndWhiteImage[imageName]; IF NOT success THEN RETURN; lowerLeft _ SVVector2d.Difference[[realMinX, realMinY], screenWRTCamera]; upperRight _ SVVector2d.Difference[[realMaxX, realMaxY], screenWRTCamera]; minX _ RoundDown[lowerLeft[1]]; maxX _ RoundUp[upperRight[1]]; minY _ RoundDown[lowerLeft[2]]; maxY _ RoundUp[upperRight[2]]; IF NOT IsEven[maxX - minX + 1] THEN maxX _ maxX + 1; IF NOT IsEven[maxY - minY + 1] THEN maxY _ maxY + 1; screenOrigin _ [minX, minY];-- ais file origin with respect to screen origin [imageXmin, imageYmin, imageXmax, imageYmax] _ GraphicsOps.ImageBox[image]; xScale _ (maxX-minX)/(imageXmax-imageXmin); yScale _ (maxY-minY)/(imageYmax-imageYmin); Graphics.MoveTo[clipPath, screenOrigin[1], screenOrigin[2]]; Graphics.LineTo[clipPath, screenOrigin[1], screenOrigin[2]+maxY-minY]; Graphics.LineTo[clipPath, screenOrigin[1] + maxX-minX, screenOrigin[2]+maxY-minY]; Graphics.LineTo[clipPath, screenOrigin[1] + maxX-minX, screenOrigin[2]]; Graphics.ClipArea[dc, clipPath]; Graphics.Translate[dc, screenOrigin[1], screenOrigin[2]]; Graphics.SetCP[dc, 0, 0]; Graphics.Scale[dc, xScale, yScale]; Graphics.SetColor[dc, GraphicsColor.white]; Graphics.DrawImage[dc, image, TRUE]; Graphics.Restore[dc, mark]; }; DrawAlignedColorImage: PUBLIC PROC [dc: Graphics.Context, imageName: Rope.ROPE, resolution: REAL, screenWRTCamera: Point2d, boundBox: BoundBox] = { info: ReadAIS.MyAISInfo; stepSize, xStart, yStart: REAL; lowerLeft, upperRight: Point2d; redName: Rope.ROPE _ Rope.Concat[SVFiles.FilenameMinusExtension[imageName],"-red.ais"]; samplesX, samplesY: NAT; mark: Mark; success: BOOL; extentX, extentY, projectionX, projectionY, trueExtentX, trueExtentY: REAL; [info, success] _ ReadAIS.Read[redName]; IF NOT success THEN RETURN; [samplesX, samplesY] _ ReadAIS.SamplesFromInfo[info]; stepSize _ 72.0/resolution; -- in screen dots per sample lowerLeft _ SVVector2d.Difference[[boundBox.minVert[1], boundBox.minVert[2]], screenWRTCamera]; upperRight _ SVVector2d.Difference[[boundBox.maxVert[1], boundBox.maxVert[2]], screenWRTCamera]; extentX _ boundBox.maxVert[1] - boundBox.minVert[1]; extentY _ boundBox.maxVert[2] - boundBox.minVert[2]; trueExtentX _ Real.Float[samplesX-1]*stepSize; trueExtentY _ Real.Float[samplesY-1]*stepSize; projectionX _ (trueExtentX - extentX)/2.0; projectionY _ (trueExtentY - extentY)/2.0; xStart _ lowerLeft[1] - projectionX; yStart _ lowerLeft[2] - projectionY; xStart _ xStart - stepSize/2.0; yStart _ yStart - stepSize/2.0; mark _ Graphics.Save[dc]; Graphics.Translate[dc, xStart, yStart]; DrawColorImage[dc, imageName, boundBox, resolution]; Graphics.Restore[dc, mark]; }; DrawColorImage: PUBLIC PROC [dc: Graphics.Context, imageName: Rope.ROPE, clipBox: BoundBox _ NIL, resolution: REAL _ 72.0] = { minX, maxX, minY, maxY: REAL; lowerLeft, upperRight: Point2d; success: BOOL; redimage, greenimage, blueimage: ImageRef; scale: REAL; clipPath: Graphics.Path _ Graphics.NewPath[4]; mark: Mark _ Graphics.Save[dc]; [redimage, greenimage, blueimage, success] _ NewColorImage[imageName]; IF NOT success THEN RETURN; IF clipBox = NIL THEN clipBox _ BoundBoxOfImage[redimage, resolution]; lowerLeft _ [0,0];-- screen coords upperRight _ SVVector2d.Sum[[clipBox.maxVert[1], clipBox.maxVert[2]], lowerLeft];-- screen coords minX _ lowerLeft[1]; maxX _ upperRight[1] +1; minY _ lowerLeft[2]; maxY _ upperRight[2] +1; scale _ 72.0/resolution; Graphics.MoveTo[clipPath, minX, minY]; Graphics.LineTo[clipPath, minX, maxY]; Graphics.LineTo[clipPath, maxX, maxY]; Graphics.LineTo[clipPath, maxX, minY]; Graphics.SetColor[dc, GraphicsColor.black]; Graphics.DrawStroke[dc, clipPath, 2, TRUE]; Graphics.ClipArea[dc, clipPath]; Graphics.SetCP[dc, 0, 0]; -- put lower left corner of image at this new origin Graphics.Scale[dc, scale, scale]; [] _ Graphics.SetPaintMode[dc, opaque]; Graphics.SetColor[dc, GraphicsColor.red]; Graphics.DrawImage[dc, redimage]; [] _ Graphics.SetPaintMode[dc, transparent]; Graphics.SetColor[dc, GraphicsColor.green]; Graphics.DrawImage[dc, greenimage]; Graphics.SetColor[dc, GraphicsColor.blue]; Graphics.DrawImage[dc, blueimage]; Graphics.Restore[dc, mark]; }; DrawAndScaleColorImage: PUBLIC PROC [dc: Graphics.Context, imageName: Rope.ROPE, screenWRTCamera: Point2d, realMinX, realMinY, realMaxX, realMaxY: REAL] = { minX, maxX, minY, maxY: INTEGER; lowerLeft, upperRight: Point2d; screenOrigin: Point2d; redimage, greenimage, blueimage: ImageRef; success: BOOL; imageXmin, imageYmin, imageXmax, imageYmax, xScale, yScale: REAL; clipPath: Graphics.Path _ Graphics.NewPath[4]; mark: Mark _ Graphics.Save[dc]; [redimage, greenimage, blueimage, success] _ NewColorImage[imageName]; IF NOT success THEN RETURN; lowerLeft _ SVVector2d.Difference[[realMinX, realMinY], screenWRTCamera]; upperRight _ SVVector2d.Difference[[realMaxX, realMaxY], screenWRTCamera]; minX _ RoundDown[lowerLeft[1]]; maxX _ RoundUp[upperRight[1]]; minY _ RoundDown[lowerLeft[2]]; maxY _ RoundUp[upperRight[2]]; IF NOT IsEven[maxX - minX + 1] THEN maxX _ maxX + 1; IF NOT IsEven[maxY - minY + 1] THEN maxY _ maxY + 1; screenOrigin _ [minX, minY];-- ais file lower left with respect to screen origin [imageXmin, imageYmin, imageXmax, imageYmax] _ GraphicsOps.ImageBox[redimage]; xScale _ (maxX-minX)/(imageXmax-imageXmin); yScale _ (maxY-minY)/(imageYmax-imageYmin); Graphics.MoveTo[clipPath, screenOrigin[1], screenOrigin[2]]; Graphics.LineTo[clipPath, screenOrigin[1], screenOrigin[2]+maxY-minY]; Graphics.LineTo[clipPath, screenOrigin[1] + maxX-minX, screenOrigin[2]+maxY-minY]; Graphics.LineTo[clipPath, screenOrigin[1] + maxX-minX, screenOrigin[2]]; Graphics.ClipArea[dc, clipPath]; Graphics.Translate[dc, screenOrigin[1], screenOrigin[2]]; Graphics.SetCP[dc, 0, 0]; Graphics.Scale[dc, xScale, yScale]; [] _ Graphics.SetPaintMode[dc, opaque]; Graphics.SetColor[dc, GraphicsColor.red]; Graphics.DrawImage[dc, redimage]; [] _ Graphics.SetPaintMode[dc, transparent]; Graphics.SetColor[dc, GraphicsColor.green]; Graphics.DrawImage[dc, greenimage]; Graphics.SetColor[dc, GraphicsColor.blue]; Graphics.DrawImage[dc, blueimage]; Graphics.Restore[dc, mark]; }; -- end of DrawAndScaleColorImage END. .File: SVImageImpl.mesa Last edited by Bier on December 18, 1982 1:38 am Author: Eric Bier before June 30, 1983 11:27 am Contents: Routines for manipulating 24 bit per pixel color images find the largest integer less than r (or equal to if r is positive). find the smallest integer greater than r (or equal to if r is negative). We are given a minimum bounding box to be filled. Calculate the number of samples in the x direction as follows: Find the number of samples which will just fit in the alloted x extent. Now add one (Since + 1 = number of samples, we actually add two). If the resulting number is odd, add 1 again. Do the same for the y direction. (Because of unimplemented features in some of the printing software, it is useful to round all ais file sizes to even numbers of pixels.) xExtent/72 = x extent in inches. (xExtent/72)*resolution = samples which will fit. Round this down to the nearest integer. Bound box is in camera coordinates Truncate the REAL value to 0-255 i is row. j is column. i = maxY maps to 0. i = minY maps to maxY-minY. j = maxX maps to maxX-minX. j = minX maps to 0. i is row. j is column. i = ySamples maps to 0. i = 1 maps to ySamples-1. j = xSamples-1 maps to xSamples-1. j = 0 maps to 0. xmin,ymin,xmax,ymax are now in units of samples. Resolution is in samples per inch. There are 72 screen dots per inch. We wish to normalize as if xmin = ymin = 0; Count how many samples there are in the x and y directions of the image. Look at the resolution (default is 72.0). This gives the actual size of the image. Frame it evenly around the clipBox. resolution _ ReadAIS.ResolutionFromInfo[info]; clipBox in units of screen dots, in coordinates whose origin is the lower left hand corner of the ais image. resolution is in dots per inch (72 is screen resolution). Draws the ais file of given resolution such that its lower left hand corner is at the current origin of dc. This involves several steps. 1) Find the total size of the clipBox. If no clipBox is given, use the whole image size. 2) Find the scaling factors needed to interpret the image as having the stated resolution 3) Translate appropriately 4) Draw. OPEN THE IMAGE Substitute for NIL parameters. BoundBoxOfImage in screen dots relative to lower left corner of image. Find clipBox in screen coordinates (ie its lowerLeft and upperRight points) box bounds in screen coordinates Now find the scaling factors for the given resolution. create the bounding box we have just calculated Graphics.MoveTo[clipPath, minX, minY]; Graphics.LineTo[clipPath, minX, maxY]; Graphics.LineTo[clipPath, maxX, maxY]; Graphics.LineTo[clipPath, maxX, minY]; Graphics.SetColor[dc, GraphicsColor.black]; Graphics.DrawStroke[dc, clipPath, 2, TRUE]; Graphics.ClipArea[dc, clipPath]; Graphics.Translate[dc, minX, minY]; If lowerLeft were not [0,0], we would perform this translate SVDraw.Cross[dc, 0, 0, 20]; Take file in AIS coordinates (right and down) and display in SCREEN coords. AIS origin is displaced from CAMERA origin by minX, minY. The clipping region has its origin at the ais origin and proceeds scanwidth and scanheight. Substitute for NIL parameters Box bounds in screen coordinates Now find the bounding box of the ais file and scale the ais file to fit in the viewport. Count how many samples there are in the x and y directions of the image. Look at the resolution (default is 72.0). This gives the actual size of the image. Frame it evenly around the clipBox. resolution _ ReadAIS.ResolutionFromInfo[info]; See comment for DrawBlackAndWhiteImage box bounds in screen coordinates now find the scaling factors for the given resolution Graphics.Translate[dc, minX, minY]; If lowerLeft were not [0,0], we would perform this translate. Take file in ais coordinates (right and down) and display in SCREEN coords. AIS origin is displaced from CAMERA origin by minX, minY. The clipping region has its origin at the ais origin and proceeds scanwidth and scanheight. Box bounds in screen coordinates Now find the bounding box of the ais file and scale the ais file to fit in the viewport Κ½– "cedar" style˜Iheadšœ™Iprocšœ0™0Lšœ/™/LšœA™AL˜šΟk ˜ Lšœ˜Lšœ˜Lšœ ˜ Lšœ ˜ Lšœ˜Lšœ ˜ Lšœ˜Lšœ˜Lšœ˜Lšœ˜Lšœ˜Lšœ ˜ Lšœ˜Lšœ˜Lšœ ˜ L˜—šœ ˜Lšœœy˜„Lšœ ˜—Lš˜˜Lšœœœ ˜Lšœ œ˜"L˜Lšœ œœ ˜!Lšœ œ˜+Lšœœ˜"Lšœ œ˜&Lšœœ˜Lšœ œ˜Lšœœœ˜Lšœœœ˜L˜š Οnœœœœœœ˜0Lšœ˜Lšœ˜L˜—Lš ž œœœœœ œ˜>šœD™DLšœœœ˜šœœ˜Lšœ˜Lšœ˜—šœ˜Lšœ˜Lšœ˜Lšœ˜Lšœ˜Lšœ˜—Lšœ˜—L˜Lš žœœœœœœ˜:šœH™HLšœœœ˜šœœ˜Lšœ˜Lšœ˜Lšœ˜—šœ˜Lšœ˜Lšœ˜Lšœ ˜ Lšœ˜—Lšœ˜—L˜š œž œœœ6œœ&ž˜ŒLšžœϋ™όLšœ.œ˜4Lšœ9˜9Lšœ9˜9Lšœ)˜)Lšœ)˜)Lšœ/˜/Lšœ/˜/Lšœœœ)˜MLšœœœ)˜MLšœ˜—L˜Lšœ˜šœž œœœœ œ6œ œœœœœ-œ˜ηLšœ#™#—šœ˜Lšœœ˜ L˜Lšœœ ˜L˜Lšœh˜hL˜LšœA˜AL˜šœ œ˜Lšœ œœ˜Lšœ œ˜Lšœ,˜,Lšœ8œ˜MLšœ œ˜Lšœ˜—šœ˜LšœœD˜VLšœœF˜ZLšœœE˜XLšœ œ ˜Lšœ œœ˜Lšœ œœ˜ Lšœ œœ˜Lšœ œœ˜L˜Lšœ œ˜Lšœ˜Lšœ+˜+Lšœ-˜-Lšœ1˜1Lšœ/˜/L˜Lšœ9œ˜NLšœ œ˜ Lšœ;œ˜PLšœœ˜"Lšœ:œ˜OLšœœ˜!Lšœ8œ˜MLšœ œ˜Lšœ˜—L˜Lšœ˜Lšœ˜Lšœ$˜$Lšœ˜—L˜šž œœœ œ˜.Lšœ œ˜Lšœ œœ˜Lšœ+˜+Lšœ œ˜%šœœ œ˜1Lšœ˜Lšœ˜—šœ˜Lšœ˜Lšœ˜Lšœ˜—Lšœ˜—L˜š žœœ œœœ˜6Lšœ ™ šœ˜Lšœœ˜ Lšœ˜Lšœ˜ —Lšœ˜—L˜š ž œœœœ(œ˜\LšœH™HLšœ0™0Lšœ)œ˜2Lšœœ˜Lšœ6˜6Lšœ˜Lšœ!˜!Lšœ˜LšœE˜ELšœ œ(˜9Lšœ œ,˜=Lšœ œ*˜;Lšœ œ-˜>Lšœ˜—L˜š žœœœœœ$œ˜ZLšœJ™JLšœ4™4šœ œ˜Lšœœ˜LšœE˜ELšœ œ(˜9L˜—šœ˜Lšœ)œ˜2Lšœœ˜Lšœ6˜6Lšœ˜Lšœ!˜!Lšœ˜LšœE˜ELšœ œ#˜4Lšœ œ'˜8Lšœ œ%˜6Lšœ œ(˜9L˜—Lšœ˜—L˜š ž œœœœœ˜:Lšœœ˜ šœ œ˜Lšœœ˜Lšœ œ ˜Lšœ˜Lšœ˜Lšœ$˜$Lšœ˜L˜—šœ˜Lšœœ˜Lšœ œ ˜Lšœ˜Lšœœ˜Lšœ œ ˜Lšœ˜Lšœœ˜Lšœ œ ˜Lšœ˜Lšœœ˜Lšœ œ˜Lšœ˜Lšœ1˜1Lšœ˜Lšœ$˜$Lšœ˜L˜—LšœΟc˜—L˜š žœœœœ œ˜iLšœ'œ˜,Lšœ4˜4LšœT™TLšœO™OLšœ˜Lšœ˜Lšœ$˜$Lšœ$˜$Lšœ œ˜Lšœ˜Lšœ(˜(Lšœ˜—L˜š žœœœœœœ˜fLšœ œA˜RLšœ œ˜Lšœ)˜)Lšœœœ˜1šœœ œ˜Lšœ-œ˜3Lšœ˜Lšœ˜—Lšœ˜—L˜š ž œœœœœ6œ˜xLšœœE˜WLšœœG˜[LšœœF˜YLšœ œ˜Lšœ*˜*Lšœœœ˜1Lšœ.˜.Lšœœœ˜1Lšœ,˜,Lšœœœ˜1šœœ œ˜Lšœ-œ˜3Lšœ˜Lšœ˜—Lšœ˜—L˜Lš žœœœ(œœ5œ˜¦šœΓ™ΓLšœ˜Lšœœ˜Lšœ˜Lšœœ˜Lšœ ˜ Lšœ œ˜LšœFœ˜KLšœ*˜*Lšœœ œœ˜Lšœ.™.Lšœ5˜5Lšœ8˜8Lšœ_˜_Lšœ`˜`Lšœ4˜4Lšœ4˜4Lšœ.˜.Lšœ.˜.Lšœ*˜*Lšœ*˜*Lšœ$˜$Lšœ$˜$Lšœ˜Lšœ˜Lšœ˜Lšœ'˜'LšœA˜ALšœ˜Lšœ˜—˜Lšžœœœ(œœœœ˜‘Lšœl™lLšœ9™9Lšœk™kLšœυ™υLšœœ˜Lšœ.˜.Lšœ˜Lšœ˜Lšœ œ˜Lšœœ˜ Lšœ ˜ Lšœ™Lšœ4˜4Lšœœ œœ˜Lšœ™Lšœ œœ.˜CLšœF™FLšœK™KLšœ"˜"LšœE˜ELšœ˜Lšœ ™ Lšœ˜Lšœ˜Lšœ˜Lšœ˜Lšœ6™6Lšœ˜Lšœ˜Lšœ/™/Lšœ&™&Lšœ&™&Lšœ&™&Lšœ&™&Lšœ+™+Lšœ+™+Lšœ ™ Lšœ#™#Lšœ<™