File: SVImageImpl.mesa
Last edited by Bier on August 17, 1985 10:10:54 pm PDT
Copyright © 1984 by Xerox Corporation. All rights reserved.
Contents: Routines for manipulating 24 bit per pixel color images
DIRECTORY
AIS,
FS,
Imager,
ImagerColorOperator,
ImagerColorPrivate,
ImagerPixelArray,
ImagerTransformation,
ReadAIS,
Real,
Rope,
SV2d,
SVError,
SVFiles,
SVImage,
SVModelTypes,
SVVector2d;
SVImageImpl:
PROGRAM
IMPORTS AIS, FS, Imager, ImagerColorOperator, ImagerColorPrivate, ImagerPixelArray, ImagerTransformation, ReadAIS, Real, Rope, SVError, SVFiles, SVVector2d
EXPORTS SVImage =
BEGIN
Image: TYPE = REF ImageObj;
ImageObj: TYPE = SVImage.ImageObj;
BoundBox: TYPE = REF BoundBoxObj;
BoundBoxObj: TYPE = SVModelTypes.BoundBoxObj;
Color: TYPE = Imager.Color;
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] = {
find the largest integer less than r (or equal to if r is positive).
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] = {
find the smallest integer greater than r (or equal to if r is negative).
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
] = {
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 <number of inter-sample distances> + 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.
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, commentString: Rope.
ROPE]
RETURNS [
I: Image, numberOfSamplesX, numberOfSamplesY:
NAT] = {
Bound box is in camera coordinates
f: AIS.FRef;
raster: AIS.Raster;
I ← NEW[ImageObj];
[numberOfSamplesX, numberOfSamplesY] ← CountSamples[realMinX, realMinY, realMaxX, realMaxY, resolution];
raster ← NEW[AIS.RasterPart ← [numberOfSamplesY, numberOfSamplesX, rd, 8, -1, 65535]];
IF bAndWOnly
THEN {
I.bAndWOnly ← TRUE;
f ← ReadAIS.CreateFile[aisRope, raster, commentString, TRUE, 0, resolution];
I.bwWindow ← AIS.OpenWindow[f];
SVError.Append[" New "];
SVError.Append[aisRope];
SVError.Append[" created.", FALSE, TRUE];
}
ELSE {
redRope: Rope.ROPE ← Rope.Concat[SVFiles.FilenameMinusExtension[aisRope], "-red.ais"];
greenRope: Rope.ROPE ← Rope.Concat[SVFiles.FilenameMinusExtension[aisRope], "-grn.ais"];
blueRope: Rope.ROPE ← Rope.Concat[SVFiles.FilenameMinusExtension[aisRope], "-blu.ais"];
bwRope: Rope.ROPE ← aisRope;
I.bAndWOnly ← FALSE;
f ← ReadAIS.CreateFile[redRope, raster, commentString, TRUE, 0, resolution];
I.redWindow ← AIS.OpenWindow[f];
f ← ReadAIS.CreateFile[greenRope, raster, commentString, TRUE, 0, resolution];
I.greenWindow ← AIS.OpenWindow[f];
f ← ReadAIS.CreateFile[blueRope, raster, commentString, TRUE, 0, resolution];
I.blueWindow ← AIS.OpenWindow[f];
f ← ReadAIS.CreateFile[bwRope, raster, commentString, TRUE, 0, resolution];
I.bwWindow ← AIS.OpenWindow[f];
SVError.Append[" New color "];
SVError.Append[aisRope];
SVError.Append["'s created.", FALSE, TRUE];
};
}; -- end of OpenImage
DeleteFile:
PRIVATE
PROC [name: Rope.
ROPE] = {
AIS.DeleteFile[name];
SVError.Append[name];
SVError.Append["... "];
}; -- end of DeleteFile
Truncate:
PROC [value:
REAL]
RETURNS [m:
CARDINAL] = {
Truncate the REAL value to 0-255
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] = {
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.
intRed, intGreen, intBlue, intIntensity: CARDINAL;
red, green, blue, intensity: REAL;
red ← ImagerColorPrivate.ComponentFromColor[NARROW[color], $Red];
green ← ImagerColorPrivate.ComponentFromColor[NARROW[color], $Green];
blue ← ImagerColorPrivate.ComponentFromColor[NARROW[color], $Blue];
intensity ← ImagerColorPrivate.ComponentFromColor[NARROW[color], $Intensity];
intRed ← Truncate[red*255.0];
intGreen ← Truncate[green*255.0];
intBlue ← Truncate[blue*255.0];
intIntensity ← Truncate[intensity*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] = {
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.
IF I.bAndWOnly
THEN {
intIntensity: CARDINAL;
intensity: REAL;
intensity ← ImagerColorPrivate.ComponentFromColor[NARROW[color], $Intensity];
intIntensity ← Truncate[intensity*255.0];
AIS.WriteSample[I.bwWindow, intIntensity, ySamples-i, j];
}
ELSE {
intRed, intGreen, intBlue, intIntensity: CARDINAL;
red, green, blue, intensity: REAL;
red ← ImagerColorPrivate.ComponentFromColor[NARROW[color], $Red];
green ← ImagerColorPrivate.ComponentFromColor[NARROW[color], $Green];
blue ← ImagerColorPrivate.ComponentFromColor[NARROW[color], $Blue];
intensity ← ImagerColorPrivate.ComponentFromColor[NARROW[color], $Intensity];
intRed ← Truncate[red*255.0];
intGreen ← Truncate[green*255.0];
intBlue ← Truncate[blue*255.0];
intIntensity ← Truncate[intensity*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];
SVError.Append[aisRope];
SVError.Append[" now closed", FALSE, TRUE];
SVError.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];
SVError.Append[" (red grn blu BandW) "];
SVError.Append[aisRope];
SVError.Append[" now closed", FALSE, TRUE];
SVError.Blink[];
};
}; -- end of CloseImage
BoundBoxOfImage:
PRIVATE
PROC [image: ImagerPixelArray.PixelArray, resolution:
REAL ← 72.0]
RETURNS [boundBox: BoundBox] = {
xExtent, yExtent: REAL;
xExtent, yExtent 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;
xExtent ← (image.fSize/resolution)*72.0;
yExtent ← (image.sSize/resolution)*72.0;
boundBox ← NEW[BoundBoxObj];
boundBox.minVert ← [0,0,0];
boundBox.maxVert ← [xExtent,yExtent, 0];
};
NewBlackAndWhiteImage:
PUBLIC
PROC [imageName: Rope.
ROPE]
RETURNS [image: ImagerPixelArray.PixelArray, success:
BOOL] = {
bwName: Rope.ROPE ← Rope.Concat[SVFiles.FilenameMinusExtension[imageName],".ais"];
success ← TRUE;
image ← ImagerPixelArray.FromAIS[imageName
!FS.Error => {success ← FALSE; CONTINUE}];
IF
NOT success
THEN {
SVError.Append["Open AIS file failed", TRUE, TRUE];
SVError.Blink[];
RETURN};
};
NewColorImage:
PUBLIC
PROC [imageName: Rope.
ROPE]
RETURNS [image: ImagerPixelArray.PixelArray, success:
BOOL] = {
redName: Rope.ROPE ← Rope.Concat[SVFiles.FilenameMinusExtension[imageName],"-red.ais"];
greenName: Rope.ROPE ← Rope.Concat[SVFiles.FilenameMinusExtension[imageName],"-grn.ais"];
blueName: Rope.ROPE ← Rope.Concat[SVFiles.FilenameMinusExtension[imageName],"-blu.ais"];
success ← TRUE;
image ← ImagerPixelArray.Join3AIS[redName, greenName, blueName
!FS.Error => {success ← FALSE; CONTINUE}];
IF
NOT success
THEN {
SVError.Append["Open AIS file failed", TRUE, TRUE];
SVError.Blink[];
RETURN};
};
DrawAlignedBlackAndWhiteImage:
PUBLIC
PROC [dc: Imager.Context, imageName: Rope.
ROPE, resolution:
REAL, screenWRTCamera: Point2d, boundBox: BoundBox] = {
Count how many samples there are in the x and y directions of the image. Look at the resolution (samples per inch. default is 72.0). This gives the actual size of the image, in inches. Frame it evenly around the clipBox. The clipBox is in Camera coordinates. Strategy: Find the center of the clipBox in camera coordinates. Convert to screen coordinates. Find the width of the ais image (in screen coordinates -- just use 72.0 as a magic number). Find the origin (xStart, yStart) in screen coordinates.
stepSize, xStart, yStart: REAL;
samplesX, samplesY: NAT;
aisFile: AIS.FRef;
raster: AIS.Raster;
originScreen, screenExtent: Point2d;
originCameraX, originCameraY: REAL;
DrawAlignedBlackAndWhiteImageAux:
SAFE
PROC =
TRUSTED {
Imager.TranslateT[dc, [xStart, yStart]];
DrawBlackAndWhiteImage[dc, imageName, screenExtent, resolution];
};
aisFile ← AIS.OpenFile[imageName, FALSE];
raster ← AIS.ReadRaster[aisFile];
AIS.CloseFile[aisFile];
resolution ← ReadAIS.ResolutionFromInfo[info]; -- for now, receive as argument
Compute xStart and yStart.
samplesX ← raster.scanLength;
samplesY ← raster.scanCount;
stepSize ← 72.0/resolution; -- in screen dots per sample
IF boundBox = NIL THEN {
originCameraX ← 0.0;
originCameraY ← 0.0;
}
ELSE {
originCameraX ← (boundBox.maxVert[1] + boundBox.minVert[1])/2.0;
originCameraY ← (boundBox.maxVert[2] + boundBox.minVert[2])/2.0;
};
originScreen ← SVVector2d.Sub[[originCameraX, originCameraY], screenWRTCamera];
screenExtent[1] ← Real.Float[samplesX-1]*stepSize; -- screen dots
screenExtent[2] ← Real.Float[samplesY-1]*stepSize; -- screen dots
xStart ← originScreen[1] - screenExtent[1]/2.0;
yStart ← originScreen[2] - screenExtent[2]/2.0;
xStart ← xStart - stepSize/2.0;
yStart ← yStart - stepSize/2.0;
Imager.DoSaveAll[dc, DrawAlignedBlackAndWhiteImageAux];
};
DrawAlignedColorImage:
PUBLIC
PROC [dc: Imager.Context, imageName: Rope.
ROPE, resolution:
REAL, screenWRTCamera: Point2d, boundBox: BoundBox] = {
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.
stepSize, xStart, yStart: REAL;
samplesX, samplesY: NAT;
aisFile: AIS.FRef;
raster: AIS.Raster;
originScreen, screenExtent: Point2d;
originCameraX, originCameraY: REAL;
redName: Rope.ROPE ← Rope.Concat[SVFiles.FilenameMinusExtension[imageName],"-red.ais"];
DrawAlignedColorImageAux:
SAFE
PROC =
TRUSTED {
Imager.TranslateT[dc, [xStart, yStart]];
DrawColorImage[dc, imageName, screenExtent, resolution];
};
aisFile ← AIS.OpenFile[redName, FALSE];
raster ← AIS.ReadRaster[aisFile];
AIS.CloseFile[aisFile];
resolution ← ReadAIS.ResolutionFromInfo[info];
Compute xStart and yStart.
samplesX ← raster.scanLength;
samplesY ← raster.scanCount;
stepSize ← 72.0/resolution; -- in screen dots per sample
IF boundBox =
NIL
THEN {
originCameraX ← 0.0;
originCameraY ← 0.0;
}
ELSE {
originCameraX ← (boundBox.maxVert[1] + boundBox.minVert[1])/2.0;
originCameraY ← (boundBox.maxVert[2] + boundBox.minVert[2])/2.0;
};
originScreen ← SVVector2d.Sub[[originCameraX, originCameraY], screenWRTCamera];
screenExtent[1] ← Real.Float[samplesX-1]*stepSize; -- screen dots
screenExtent[2] ← Real.Float[samplesY-1]*stepSize; -- screen dots
xStart ← originScreen[1] - screenExtent[1]/2.0;
yStart ← originScreen[2] - screenExtent[2]/2.0;
Imager.DoSaveAll[dc, DrawAlignedColorImageAux];
};
DrawAndScaleBlackAndWhiteImage: PUBLIC PROC [dc: Imager.Context, imageName: Rope.ROPE, screenWRTCamera: Point2d, realMinX, realMinY, realMaxX, realMaxY: REAL] = {
minX, maxX, minY, maxY: INTEGER;
clipPath: ImagerPath.Trajectory;
lowerLeft, upperRight: Point2d;
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.
screenOrigin: Point2d;
success: BOOL ← TRUE;
image: ImageRef;
imageXmin, imageYmin, imageXmax, imageYmax, xScale, yScale: REAL;
DrawAndScaleBlackAndWhiteImageAux: PROC = {
[image, success] ← NewBlackAndWhiteImage[imageName];
IF NOT success THEN RETURN;
Substitute for NIL parameters
lowerLeft ← SVVector2d.Sub[[realMinX, realMinY], screenWRTCamera];
upperRight ← SVVector2d.Sub[[realMaxX, realMaxY], screenWRTCamera];
Box bounds in screen coordinates
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
Now find the bounding box of the ais file and scale the ais file to fit in the viewport.
[imageXmin, imageYmin, imageXmax, imageYmax] ← GraphicsOps.ImageBox[image];
xScale ← (maxX-minX)/(imageXmax-imageXmin);
yScale ← (maxY-minY)/(imageYmax-imageYmin);
clipPath ← ImagerPath.MoveTo[[screenOrigin[1], screenOrigin[2]]];
clipPath ← ImagerPath.LineTo[clipPath, [screenOrigin[1], screenOrigin[2]+maxY-minY]];
clipPath ← ImagerPath.LineTo[clipPath, [screenOrigin[1] + maxX-minX, screenOrigin[2]+maxY-minY]];
clipPath ← ImagerPath.LineTo[clipPath, [screenOrigin[1] + maxX-minX, screenOrigin[2]]];
Imager.ClipArea[dc, clipPath];
Imager.Translate[dc, screenOrigin[1], screenOrigin[2]];
Imager.SetCP[dc, 0, 0];
Imager.Scale[dc, xScale, yScale];
Imager.SetColor[dc, ImagerColor.white];
Imager.DrawImage[dc, image, TRUE];
};
Imager.DoSaveAll[dc, DrawAndScaleBlackAndWhiteImageAux];
};
DrawAndScaleColorImage: PUBLIC PROC [dc: Imager.Context, imageName: Rope.ROPE, screenWRTCamera: Point2d, realMinX, realMinY, realMaxX, realMaxY: REAL] = {
minX, maxX, minY, maxY: INTEGER;
lowerLeft, upperRight: Point2d;
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.
screenOrigin: Point2d;
redimage, greenimage, blueimage: ImageRef;
success: BOOL;
imageXmin, imageYmin, imageXmax, imageYmax, xScale, yScale: REAL;
clipPath: ImagerPath.Trajectory;
DrawAndScaleColorImageAux: PROC = {
[redimage, greenimage, blueimage, success] ← NewColorImage[imageName];
IF NOT success THEN RETURN;
lowerLeft ← SVVector2d.Sub[[realMinX, realMinY], screenWRTCamera];
upperRight ← SVVector2d.Sub[[realMaxX, realMaxY], screenWRTCamera];
Box bounds in screen coordinates
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
Now find the bounding box of the ais file and scale the ais file to fit in the viewport
[imageXmin, imageYmin, imageXmax, imageYmax] ← GraphicsOps.ImageBox[redimage];
xScale ← (maxX-minX)/(imageXmax-imageXmin);
yScale ← (maxY-minY)/(imageYmax-imageYmin);
clipPath ← ImagerPath.MoveTo[[screenOrigin[1], screenOrigin[2]]];
clipPath ← ImagerPath.LineTo[clipPath, [screenOrigin[1], screenOrigin[2]+maxY-minY]];
clipPath ← ImagerPath.LineTo[clipPath, [screenOrigin[1] + maxX-minX, screenOrigin[2]+maxY-minY]];
clipPath ← ImagerPath.LineTo[clipPath, [screenOrigin[1] + maxX-minX, screenOrigin[2]]];
Imager.ClipArea[dc, clipPath];
Imager.Translate[dc, screenOrigin[1], screenOrigin[2]];
Imager.SetCP[dc, 0, 0];
Imager.Scale[dc, xScale, yScale];
[] ← Imager.SetPaintMode[dc, opaque];
Imager.SetColor[dc, ImagerColor.ColorFromAtom[$Red]];
Imager.DrawImage[dc, redimage];
[] ← Imager.SetPaintMode[dc, transparent];
Imager.SetColor[dc, ImagerColor.ColorFromAtom[$Green]];
Imager.DrawImage[dc, greenimage];
Imager.SetColor[dc, ImagerColor.ColorFromAtom[$Blue]];
Imager.DrawImage[dc, blueimage];
};
Imager.DoSaveAll[dc, DrawAndScaleColorImageAux];
}; -- end of DrawAndScaleColorImage
OldDrawBlackAndWhiteImage:
PUBLIC
PROC [dc: Imager.Context, imageName: Rope.
ROPE, clipBox: BoundBox ←
NIL, resolution:
REAL ← 72.0, raw:
BOOL] = {
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.
minX, maxX, minY, maxY: REAL;
lowerLeft, upperRight: Point2d;
image: ImagerPixelArray.PixelArray;
success: BOOL;
scale: REAL;
colors: Imager.ColorOperator ← ImagerColorOperator.GrayLinearColorModel[255, 0, 255];
DrawBlackAndWhiteImageAux:
SAFE PROC = TRUSTED {
Create the bounding box we have just calculated
If lowerLeft were not [0,0], we would perform this translate
Imager.SetXY[dc, [0, 0]]; -- put lower left corner of image at this new origin
Imager.SetSampledColor[dc, image, ImagerTransformation.Scale[scale], colors];
Imager.MaskBox[dc, [minX, minY, maxX, maxY]];
};
OPEN THE IMAGE
[image, success] ← NewBlackAndWhiteImage[imageName];
IF
NOT success
THEN
RETURN;
Substitute for NIL parameters.
IF clipBox =
NIL
THEN clipBox ← BoundBoxOfImage[image, resolution];
BoundBoxOfImage in screen dots relative to lower left corner of image.
Find clipBox in screen coordinates (ie its lowerLeft and upperRight points)
lowerLeft ← [0,0];-- screen coords
upperRight ← SVVector2d.Add[[clipBox.maxVert[1], clipBox.maxVert[2]],
lowerLeft];
-- screen coords
Now find the scaling factors for the given resolution.
scale ← 72.0/resolution;
box bounds in screen coordinates
minX ← lowerLeft[1];
minY ← lowerLeft[2];
maxX ← upperRight[1]*scale +1;
maxY ← upperRight[2]*scale +1;
Imager.DoSaveAll[dc, DrawBlackAndWhiteImageAux];
};
DrawBlackAndWhiteAtOrigin:
PUBLIC
PROC [dc: Imager.Context, imageName: Rope.
ROPE, resolution:
REAL ← 72.0] = {
stepSize: REAL;
samplesX, samplesY: NAT;
aisFile: AIS.FRef;
raster: AIS.Raster;
screenExtent: Point2d;
aisFile ← AIS.OpenFile[imageName, FALSE];
raster ← AIS.ReadRaster[aisFile];
AIS.CloseFile[aisFile];
samplesX ← raster.scanLength;
samplesY ← raster.scanCount;
stepSize ← 72.0/resolution; -- in screen dots per sample
screenExtent[1] ← Real.Float[samplesX-1]*stepSize; -- screen dots
screenExtent[2] ← Real.Float[samplesY-1]*stepSize; -- screen dots
DrawBlackAndWhiteImage[dc, imageName, screenExtent, resolution];
};
DrawColorImageAtOrigin:
PUBLIC
PROC [dc: Imager.Context, imageName: Rope.
ROPE, resolution:
REAL ← 72.0] = {
stepSize: REAL;
samplesX, samplesY: NAT;
aisFile: AIS.FRef;
redName: Rope.ROPE ← Rope.Concat[SVFiles.FilenameMinusExtension[imageName],"-red.ais"];
raster: AIS.Raster;
screenExtent: Point2d;
aisFile ← AIS.OpenFile[redName, FALSE];
raster ← AIS.ReadRaster[aisFile];
AIS.CloseFile[aisFile];
samplesX ← raster.scanLength;
samplesY ← raster.scanCount;
stepSize ← 72.0/resolution; -- in screen dots per sample
screenExtent[1] ← Real.Float[samplesX-1]*stepSize; -- screen dots
screenExtent[2] ← Real.Float[samplesY-1]*stepSize; -- screen dots
DrawColorImage[dc, imageName, screenExtent, resolution];
};
DrawBlackAndWhiteImage:
PROC [dc: Imager.Context, imageName: Rope.
ROPE, screenExtent: Point2d, resolution:
REAL ← 72.0] = {
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.
minX, maxX, minY, maxY: REAL;
image: ImagerPixelArray.PixelArray;
success: BOOL;
scale: REAL;
colors: Imager.ColorOperator ← ImagerColorOperator.GrayLinearColorModel[255, 0, 255];
DrawBlackAndWhiteImageAux:
SAFE PROC = TRUSTED {
Imager.SetSampledColor[dc, image, ImagerTransformation.Scale[scale], colors];
Imager.MaskBox[dc, [minX, minY, maxX, maxY]];
};
OPEN THE IMAGE
[image, success] ← NewBlackAndWhiteImage[imageName];
IF
NOT success
THEN
RETURN;
Now find the scaling factors for the given resolution.
scale ← 72.0/resolution;
box bounds in screen coordinates
minX ← 0.0;
minY ← 0.0;
maxX ← screenExtent[1];
maxY ← screenExtent[2];
Imager.DoSaveAll[dc, DrawBlackAndWhiteImageAux];
};
DrawColorImage:
PROC [dc: Imager.Context, imageName: Rope.
ROPE, screenExtent: Point2d, resolution:
REAL ← 72.0] = {
See comment for DrawBlackAndWhiteImage
minX, maxX, minY, maxY: REAL;
image: ImagerPixelArray.PixelArray;
success: BOOL;
scale: REAL;
colors: Imager.ColorOperator ← ImagerColorOperator.RGBLinearColorModel[255];
DrawColorImageAux:
SAFE PROC = TRUSTED {
Imager.SetSampledColor[dc, image, ImagerTransformation.Scale[scale], colors];
Imager.MaskBox[dc, [minX, minY, maxX, maxY]];
};
OPEN THE IMAGE
[image, success] ← NewColorImage[imageName];
IF
NOT success
THEN
RETURN;
Now find the scaling factors for the given resolution.
scale ← 72.0/resolution;
box bounds in screen coordinates
minX ← 0.0;
minY ← 0.0;
maxX ← screenExtent[1];
maxY ← screenExtent[2];
Imager.DoSaveAll[dc, DrawColorImageAux];
};
END.