Syntax Highlighing:
comments, key words, predefined symbols, class members & methods, functions & classes
#
# LayoutView MacroScript
#
# This script renders a layout as a grayscale image and binary overlay TIFF files.
# User is prompted for destination directory folder, image resolution and overlay resolution.
#
# Assumptions
# 1. All image layers are assumed to be grayscale.
# 2. All non-image layers are assumed to be overlays.
# 3. No "partial transparency" is used in any layer.
# 4. The overlay only uses black, white, yellow, cyan and red-brown.
# A check is made for this condition during processing.
#
# Results:
# 1. Grayscale TIFF in 58600 subfolder under user specified folder.
# Cells in image corresponding to non-background and non-black pixels in the
# overlay will be masked (changed to white).
# 2. 4 Binary TIFFs in subfolders named according to ink color.
# 3. TIFF files are named according to client-provided naming conventions.
#
# Variables for testing.
numeric KeepWorkFiles = false; # Set to 'true' to retain RVC work files for testing
# Declare variables.
numeric errcode;
numeric imageres;
numeric overlayres;
numeric resratio;
numeric imagecellsize;
numeric overlaycellsize;
numeric imageviewnum = 21;
numeric overlayviewnum = 22;
numeric hardcopyviewnum = 31;
numeric imagenumlins;
numeric imagenumcols;
numeric overlaynumlins;
numeric overlaynumcols;
numeric numBadColors; # Number of unknown-color pixels in overlay
numeric isimage;
string targetdir$;
string inkname$;
string filename$;
string msg$;
Raster ImageRaster;
Raster OverlayRaster;
Raster GrayscaleRaster;
class GROUP group;
class LAYER layer;
class FILEPATH imagefilename;
class FILEPATH overlayfilename;
class FILEPATH grayscalefilename;
class FILEPATH binaryfilename;
class FILEPATH targetpath;
class STATUSDIALOG statusdialog;
class STATUSCONTEXT statuscontext;
class COLOR overlaybgcolor;
class MIETIFF tiffexp;
class COLORMAP colormap;
class TIMER timer;
string log$;
# Function to determine RGB raster value from separate R, G, B.
#func rgbValue (r, g, b) {
# return (((b * 256) + g) * 256 + r);
# }
# Determine raster values for ink colors.
# These were used when overlays were rendered to 24-bit raster
#numeric ink58600 = rgbValue(0,0,0); # Black
#numeric ink48253 = rgbValue(0,255,255); # Cyan
#numeric ink57377 = rgbValue(255,255,0); # Yellow
#numeric ink61121 = rgbValue(165,0,0); # Red-Brown
#numeric inkWhite = rgbValue(255,255,255);
#numeric inkBG = rgbValue(0,0,255);
# These are used when overlays are rendered to 4-bit colormapped raster
numeric inkBG = 0;
numeric ink58600 = 1;
numeric inkWhite = 2;
numeric ink48253 = 3;
numeric ink57377 = 4;
numeric ink61121 = 5;
ColorMapSetColorRGB(colormap, inkBG, 0, 0, 255); # background blue
ColorMapSetColorRGB(colormap, ink58600, 0, 0, 0); # Black
ColorMapSetColorRGB(colormap, inkWhite, 255, 255, 255); # White
ColorMapSetColorRGB(colormap, ink48253, 0, 255, 255); # Cyan
ColorMapSetColorRGB(colormap, ink57377, 255, 255, 0); # Yellow
ColorMapSetColorRGB(colormap, ink61121, 165, 0, 0); # Red-Brown
# Any overlay colors in this range (inclusive) will cause the underlying
# image raster pixel to be held out (becomes white)
numeric maskRangeLow = inkWhite;
numeric maskRangeHigh = ink61121;
# Any color above this value will be flagged as "invalid"
numeric maxValidInk = ink61121;
# Function to clean up temporary files.
func cleanup () {
CloseRaster(ImageRaster);
CloseRaster(OverlayRaster);
if (!KeepWorkFiles) {
imagefilename.Delete();
overlayfilename.Delete();
}
statusdialog.Destroy();
log$ = "";
}
# Function to export binary TIFF for specified ink color.
func ExportBinary (numeric inkcolor, string inkname$, string filename$) {
msg$ = "Creating binary mask for " + inkname$;
statuscontext.TextUpdate(msg$,2);
if (KeepWorkFiles) {
binaryfilename = grayscalefilename;
}
else {
binaryfilename = CreateTempFileName();
}
string binaryrastname$ = "B_" + inkname$;
timer.Value = 0;
timer.Running = 1;
CreateRasterBinaryMask(OverlayRaster,binaryfilename,binaryrastname$,inkcolor);
log$ = log$ + "Time to create binary mask for " + inkname$ + ": " + timer.LongString + "\n";
targetpath = targetdir$;
targetpath.Append(inkname$);
targetpath.Make();
targetpath.Append(filename$);
timer.Value = 0;
timer.Running = 1;
msg$ = "Exporting binary TIFF for " + inkname$;
statuscontext.TextUpdate(msg$,2);
ExportRaster(tiffexp,targetpath,binaryfilename,binaryrastname$);
log$ = log$ + "Time to export binary mask for " + inkname$ + ": " + timer.LongString + "\n";
if (!KeepWorkFiles) {
binaryfilename.Delete();
}
}
# Prompt user for target directory folder.
targetdir$ = GetDirectory("c:/temp","Select destination folder for TIFF separates:");
if (targetdir$ == "") Exit();
# Determine image and overlay resolutions.
imageres = PopupNum("Image resolution in DPI?",300,50,1200,0);
if (imageres < 0) Exit();
overlayres = PopupNum("Overlay resolution in DPI?",1200,imageres,2400,0);
if (overlayres < 0) Exit();
# Create progress dialog
statusdialog.Create(View.Form);
statuscontext = statusdialog.CreateContext();
statuscontext.Message = "Rendering Color Separations";
#StatusSetDefaultHandle(statusdialog);
# Resolution ratio between overlay and image
resratio = overlayres / imageres;
# Compute raster cell sizes in meters
imagecellsize = Layout.MapScale / imageres * .0254;
overlaycellsize = imagecellsize * resratio;
# Set layer visibility based on whether image or not.
# If layer not visible in 'hardcopy' view then don't draw in either.
group = Layout.Firstgroup;
while (group != 0) {
layer = group.FirstLayer;
while (layer != 0) {
if (layer.IsVisibleInView(hardcopyviewnum)) {
isimage = (layer.Type == "Raster");
layer.SetVisibleInView(imageviewnum,isimage);
layer.SetVisibleInView(overlayviewnum,!isimage);
}
else {
layer.SetVisibleInView(imageviewnum,0);
layer.SetVisibleInView(overlayviewnum,0);
}
layer = layer.NextLayer;
}
group = group.NextGroup;
}
# Render image raster.
if (KeepWorkFiles) {
imagefilename = targetdir$;
imagefilename.Append("image.rvc");
imagefilename.Delete();
}
else {
imagefilename = CreateTempFileName();
}
statuscontext.TextUpdate("Rendering images",2);
timer.Value = 0;
timer.Running = 1;
errcode = Layout.RenderToRaster(imagefilename,"Image",imageviewnum,imagecellsize);
statusdialog.SetSelfAsDefault();
log$ = log$ + "Time to render images: " + timer.LongString + "\n";
if (errcode < 0) {
PopupError(errcode);
Exit();
}
# Open image raster and determine size.
OpenRaster(ImageRaster,imagefilename,"Image");
imagenumcols = NumCols(ImageRaster);
imagenumlins = NumLins(ImageRaster);
# Make overlay raster exact multiple of image raster in size.
overlaynumcols = imagenumcols * resratio;
overlaynumlins = imagenumlins * resratio;
# Render the overlay raster.
if (KeepWorkFiles) {
overlayfilename = targetdir$;
overlayfilename.Append("overlay.rvc");
overlayfilename.Delete();
}
else {
overlayfilename = CreateTempFileName();
}
statuscontext.TextUpdate("Rendering overlays",2);
# Use blue for initial overlay background so pixels rendered in white
# can be separated and masked out of the image raster.
# Any color could be used here as long as it is guaranteed not to occur in the overlay.
# If the background color is changed the 'inkBG' value below must also be changed.
overlaybgcolor.red = 0;
overlaybgcolor.green = 0;
overlaybgcolor.blue = 100;
timer.Value = 0;
timer.Running = 1;
errcode = Layout.RenderToRaster(overlayfilename,"Overlay",overlayviewnum,overlaycellsize,overlaynumlins,overlaynumcols,4,overlaybgcolor,colormap);
statusdialog.SetSelfAsDefault();
log$ = log$ + "Time to render overlays: " + timer.LongString + "\n";
if (errcode < 0) {
PopupError(errcode);
Exit();
}
OpenRaster(OverlayRaster,overlayfilename,"Overlay");
# Convert Image to grayscale.
statuscontext.TextUpdate("Converting image to grayscale",2);
grayscalefilename = CreateTempFileName();
if (KeepWorkFiles) {
grayscalefilename = targetdir$;
grayscalefilename.Append("separates.rvc");
grayscalefilename.Delete();
}
else {
grayscalefilename = CreateTempFileName();
}
CreateRaster(GrayscaleRaster,grayscalefilename,"grayscale","",imagenumlins,imagenumcols,"8-bit unsigned");
timer.Value = 0;
timer.Running = 1;
numeric row, col;
foreach ImageRaster[row,col] {
GrayscaleRaster[row,col] = ImageRaster[row,col] % 256;
}
log$ = log$ + "Time to convert image to grayscale: " + timer.LongString + "\n";
statuscontext.BarClear(2);
CloseRaster(ImageRaster);
# Change cells in image to white if covered by color cell in overlay.
# Also verifies that overlay only contains valid colors.
statuscontext.TextUpdate("Masking image cells",2);
numeric cellval;
timer.Value = 0;
timer.Running = 1;
foreach OverlayRaster[row,col] {
cellval = OverlayRaster;
if (cellval >= maskRangeLow) {
# 99% of the time this is false, so check it first. We can avoid all
# other checks in that case.
if (cellval > maxValidInk) {
numBadColors += 1;
}
else {
# Set cell in image to white.
GrayscaleRaster[floor(row/resratio),floor(col/resratio)] = 255;
}
}
}
log$ = log$ + "Time to mask cells: " + timer.LongString + "\n";
statuscontext.BarClear(2);
if (numBadColors > 0) {
# Tell the user and exit if they want.
msg$ = sprintf("Warning, overlay contains %d pixels with unknown ink colors.\nDo you want to continue?",numBadColors);
if (!PopupYesNo(msg$)) Exit();
}
CloseRaster(GrayscaleRaster);
# Set general TIFF export values.
tiffexp.ExportGeoTags = false;
tiffexp.ResolutionUnit = "inch";
# Export grayscale to TIFF.
statuscontext.TextUpdate("Exporting grayscale TIFF",2);
tiffexp.Resolution = imageres;
tiffexp.CompressionType = "LZW";
targetpath = targetdir$;
targetpath.Append("58600");
targetpath.Make();
targetpath.Append("99991.XXX"); # Was not sure what name to use for grayscale
timer.Value = 0;
timer.Running = 1;
ExportRaster(tiffexp,targetpath,grayscalefilename,"grayscale");
log$ = log$ + "Time to export grayscale: " + timer.LongString + "\n";
if (!KeepWorkFiles) {
grayscalefilename.Delete();
}
# Convert each overlay color to binary and export to TIFF.
tiffexp.Resolution = overlayres;
tiffexp.CompressionType = "CCITTFAX4";
ExportBinary(ink58600, "58600", "99991.A29");
ExportBinary(ink48253, "48253", "99991.F07");
ExportBinary(ink57377, "57377", "99991.G80");
ExportBinary(ink61121, "61121", "99991.B66");
PopupMessage(log$);
log$ = "";