|
Functions |
|
package ij.macro;
import ij.*;
import ij.process.*;
import ij.gui.*;
import ij.measure.*;
import ij.plugin.*;
import ij.plugin.filter.*;
import ij.plugin.frame.*;
import ij.text.*;
import ij.io.*;
import ij.util.*;
import java.awt.*;
import java.awt.image.*;
import java.util.*;
import java.io.*;
import java.awt.event.KeyEvent;
import java.lang.reflect.*;
import java.net.URL;
import java.awt.datatransfer.*;
/** This class implements the built-in macro functions. */
public class Functions implements MacroConstants, Measurements {
Interpreter interp;
Program pgm;
boolean updateNeeded;
boolean autoUpdate = true;
ImagePlus defaultImp;
ImageProcessor defaultIP;
int imageType;
boolean colorSet, fontSet;
Color defaultColor;
double defaultValue = Double.NaN;
Plot plot;
static int plotID;
int justification = ImageProcessor.LEFT_JUSTIFY;
Font font;
GenericDialog gd;
PrintWriter writer;
boolean altKeyDown, shiftKeyDown;
boolean antialiasedText;
StringBuffer buffer;
RoiManager roiManager;
Properties props;
boolean saveSettingsCalled;
boolean usePointerCursor, hideProcessStackDialog;
float divideByZeroValue;
int jpegQuality;
int lineWidth;
boolean doScaling;
boolean weightedColor;
double[] weights;
boolean interpolateScaledImages, open100Percent, blackCanvas;
boolean useJFileChooser,debugMode;
Color foregroundColor, backgroundColor, roiColor;
boolean pointAutoMeasure, requireControlKey, useInvertingLut;
boolean doubleBuffer, disablePopup;
int measurements;
int decimalPlaces;
boolean blackBackground;
static Dialog waitForUserDialog;
Functions(Interpreter interp, Program pgm) {
this.interp = interp;
this.pgm = pgm;
}
void doFunction(int type) {
switch (type) {
case RUN: doRun(); break;
case SELECT: IJ.selectWindow(getStringArg()); resetImage(); break;
case WAIT: IJ.wait((int)getArg()); break;
case BEEP: interp.getParens(); IJ.beep(); break;
case RESET_MIN_MAX: interp.getParens(); IJ.resetMinAndMax(); resetImage(); break;
case RESET_THRESHOLD: interp.getParens(); IJ.resetThreshold(); resetImage(); break;
case PRINT: print(); break;
case WRITE: IJ.write(getStringArg()); break;
case DO_WAND: IJ.doWand((int)getFirstArg(), (int)getLastArg()); resetImage(); break;
case SET_MIN_MAX: IJ.setMinAndMax(getFirstArg(), getLastArg()); resetImage(); break;
case SET_THRESHOLD: setThreshold(); break;
case SET_TOOL: setTool(); break;
case SET_FOREGROUND: setForegroundColor(); break;
case SET_BACKGROUND: setBackgroundColor(); break;
case SET_COLOR: setColor(); break;
case MAKE_LINE: makeLine(); break;
case MAKE_OVAL: makeOval(); break;
case MAKE_RECTANGLE: makeRectangle(); break;
case DUMP: interp.dump(); break;
case LINE_TO: lineTo(); break;
case MOVE_TO: moveTo(); break;
case DRAW_LINE: drawLine(); break;
case REQUIRES: requires(); break;
case AUTO_UPDATE: autoUpdate = getBooleanArg(); break;
case UPDATE_DISPLAY: interp.getParens(); updateDisplay(); break;
case DRAW_STRING: drawString(); break;
case SET_PASTE_MODE: IJ.setPasteMode(getStringArg()); break;
case DO_COMMAND: doCommand(); break;
case SHOW_STATUS: IJ.showStatus(getStringArg()); interp.statusUpdated=true; break;
case SHOW_PROGRESS: showProgress(); break;
case SHOW_MESSAGE: showMessage(false); break;
case SHOW_MESSAGE_WITH_CANCEL: showMessage(true); break;
case SET_PIXEL: case PUT_PIXEL: setPixel(); break;
case SNAPSHOT: case RESET: case FILL: doIPMethod(type); break;
case SET_LINE_WIDTH: getProcessor().setLineWidth((int)getArg()); break;
case CHANGE_VALUES: changeValues(); break;
case SELECT_IMAGE: selectImage(); break;
case EXIT: exit(); break;
case SET_LOCATION: setLocation(); break;
case GET_CURSOR_LOC: getCursorLoc(); break;
case GET_LINE: getLine(); break;
case GET_VOXEL_SIZE: getVoxelSize(); break;
case GET_HISTOGRAM: getHistogram(); break;
case GET_BOUNDING_RECT: case GET_BOUNDS: getBounds(); break;
case GET_LUT: getLut(); break;
case SET_LUT: setLut(); break;
case GET_COORDINATES: getCoordinates(); break;
case MAKE_SELECTION: makeSelection(); break;
case SET_RESULT: setResult(); break;
case UPDATE_RESULTS: updateResults(); break;
case SET_BATCH_MODE: setBatchMode(); break;
case PLOT: doPlot(); break;
case SET_JUSTIFICATION: setJustification(); break;
case SET_Z_COORDINATE: setZCoordinate(); break;
case GET_THRESHOLD: getThreshold(); break;
case GET_PIXEL_SIZE: getPixelSize(); break;
case SETUP_UNDO: interp.getParens(); Undo.setup(Undo.TRANSFORM, getImage()); break;
case SAVE_SETTINGS: saveSettings(); break;
case RESTORE_SETTINGS: restoreSettings(); break;
case SET_KEY_DOWN: setKeyDown(); break;
case OPEN: open(); break;
case SET_FONT: setFont(); break;
case GET_MIN_AND_MAX: getMinAndMax(); break;
case CLOSE: close(); break;
case SET_SLICE: setSlice(); break;
case NEW_IMAGE: newImage(); break;
case SAVE: IJ.save(getStringArg()); break;
case SAVE_AS: saveAs(); break;
case SET_AUTO_THRESHOLD: setAutoThreshold(); break;
case RENAME: resetImage(); getImage().setTitle(getStringArg()); break;
case GET_STATISTICS: getStatistics(true); break;
case GET_RAW_STATISTICS: getStatistics(false); break;
case FLOOD_FILL: floodFill(); break;
case RESTORE_PREVIOUS_TOOL: restorePreviousTool(); break;
case SET_VOXEL_SIZE: setVoxelSize(); break;
case GET_LOCATION_AND_SIZE: getLocationAndSize(); break;
case GET_DATE_AND_TIME: getDateAndTime(); break;
case SET_METADATA: setMetadata(); break;
case CALCULATOR: imageCalculator(); break;
case SET_RGB_WEIGHTS: setRGBWeights(); break;
case MAKE_POLYGON: makePolygon(); break;
case SET_SELECTION_NAME: setSelectionName(); break;
case DRAW_RECT: case FILL_RECT: case DRAW_OVAL: case FILL_OVAL: drawOrFill(type); break;
case SET_OPTION: setOption(); break;
case SHOW_TEXT: showText(); break;
case SET_SELECTION_LOC: setSelectionLocation(); break;
case GET_DIMENSIONS: getDimensions(); break;
case WAIT_FOR_USER: waitForUser(); break;
case MAKE_POINT: makePoint(); break;
}
}
final double getFunctionValue(int type) {
double value = 0.0;
switch (type) {
case GET_PIXEL: value = getPixel(); break;
case ABS: case COS: case EXP: case FLOOR: case LOG: case ROUND:
case SIN: case SQRT: case TAN: case ATAN: case ASIN: case ACOS:
value = math(type);
break;
case MAX_OF: case MIN_OF: case POW: case ATAN2: value=math2(type); break;
case GET_TIME: interp.getParens(); value=System.currentTimeMillis(); break;
case GET_WIDTH: interp.getParens(); value=getImage().getWidth(); break;
case GET_HEIGHT: interp.getParens(); value=getImage().getHeight(); break;
case RANDOM: value=random(); break;
case GET_COUNT: case NRESULTS: value=getResultsCount(); break;
case GET_RESULT: value=getResult(); break;
case GET_NUMBER: value=getNumber(); break;
case NIMAGES: value=getImageCount(); break;
case NSLICES: value=getStackSize(); break;
case LENGTH_OF: value=lengthOf(); break;
case GET_ID: interp.getParens(); resetImage(); value=getImage().getID(); break;
case BIT_DEPTH: interp.getParens(); value = getImage().getBitDepth(); break;
case SELECTION_TYPE: value=getSelectionType(); break;
case IS_OPEN: value=isOpen(); break;
case IS_ACTIVE: value=isActive(); break;
case INDEX_OF: value=indexOf(); break;
case LAST_INDEX_OF: value=getFirstString().lastIndexOf(getLastString()); break;
case CHAR_CODE_AT: value=getFirstString().charAt((int)getLastArg()); break;
case GET_BOOLEAN: value=getBoolean(); break;
case STARTS_WITH: case ENDS_WITH: value = startsWithEndsWith(type); break;
case IS_NAN: value = Double.isNaN(getArg())?1:0; break;
case GET_ZOOM: value = getZoom(); break;
case PARSE_FLOAT: value = parseDouble(getStringArg()); break;
case PARSE_INT: value = parseInt(); break;
case IS_KEY_DOWN: value=isKeyDown(); break;
case GET_SLICE_NUMBER: interp.getParens(); value=getImage().getCurrentSlice(); break;
case SCREEN_WIDTH: case SCREEN_HEIGHT: value = getScreenDimension(type); break;
case CALIBRATE: value = getImage().getCalibration().getCValue(getArg()); break;
case ROI_MANAGER: value = roiManager(); break;
case TOOL_ID: interp.getParens(); value = Toolbar.getToolId(); break;
case IS: value = is(); break;
case GET_VALUE: value = getValue(); break;
case STACK: value = doStack(); break;
case MATCHES: value = matches(); break;
case GET_STRING_WIDTH: value = getStringWidth(); break;
default:
interp.error("Numeric function expected");
}
return value;
}
String getStringFunction(int type) {
String str;
switch (type) {
case D2S: str = d2s(); break;
case TO_HEX: str = toString(16); break;
case TO_BINARY: str = toString(2); break;
case GET_TITLE: interp.getParens(); resetImage(); str=getImage().getTitle(); break;
case GET_STRING: str = getStringDialog(); break;
case SUBSTRING: str = substring(); break;
case FROM_CHAR_CODE: str = fromCharCode(); break;
case GET_INFO: str = getInfo(); break;
case GET_IMAGE_INFO: interp.getParens(); str = getImageInfo(); break;
case GET_DIRECTORY: str = getDirectory(); break;
case GET_ARGUMENT: interp.getParens(); str=interp.argument!=null?interp.argument:""; break;
case TO_LOWER_CASE: str = getStringArg().toLowerCase(Locale.US); break;
case TO_UPPER_CASE: str = getStringArg().toUpperCase(Locale.US); break;
case RUN_MACRO: str = runMacro(false); break;
case EVAL: str = runMacro(true); break;
case TO_STRING: str = doToString(); break;
case REPLACE: str = replace(); break;
case DIALOG: str = doDialog(); break;
case GET_METADATA: str = getMetadata(); break;
case FILE: str = doFile(); break;
case SELECTION_NAME: str = selectionName(); break;
case GET_VERSION: interp.getParens(); str = IJ.getVersion(); break;
case GET_RESULT_LABEL: str = getResultLabel(); break;
case CALL: str = call(); break;
case STRING: str = doString(); break;
case EXT: str = doExt(); break;
case EXEC: str = exec(); break;
case LIST: str = doList(); break;
default:
str="";
interp.error("String function expected");
}
return str;
}
Variable[] getArrayFunction(int type) {
Variable[] array;
switch (type) {
case GET_PROFILE: array=getProfile(); break;
case NEW_ARRAY: array = newArray(); break;
case SPLIT: array = split(); break;
case GET_FILE_LIST: array = getFileList(); break;
case GET_FONT_LIST: array = getFontList(); break;
case NEW_MENU: array = newMenu(); break;
case GET_LIST: array = getList(); break;
default:
array = null;
interp.error("Array function expected");
}
return array;
}
final double math(int type) {
double arg = getArg();
switch (type) {
case ABS: return Math.abs(arg);
case COS: return Math.cos(arg);
case EXP: return Math.exp(arg);
case FLOOR: return Math.floor(arg);
case LOG: return Math.log(arg);
case ROUND: return Math.floor(arg + 0.5);
case SIN: return Math.sin(arg);
case SQRT: return Math.sqrt(arg);
case TAN: return Math.tan(arg);
case ATAN: return Math.atan(arg);
case ASIN: return Math.asin(arg);
case ACOS: return Math.acos(arg);
default: return 0.0;
}
}
final double math2(int type) {
double a1 = getFirstArg();
double a2 = getLastArg();
switch (type) {
case MIN_OF: return Math.min(a1, a2);
case MAX_OF: return Math.max(a1, a2);
case POW: return Math.pow(a1, a2);
case ATAN2: return Math.atan2(a1, a2);
default: return 0.0;
}
}
final String getString() {
String str = interp.getStringTerm();
while (true) {
interp.getToken();
if (interp.token=='+')
str += interp.getStringTerm();
else {
interp.putTokenBack();
break;
}
};
return str;
}
final boolean isStringFunction() {
Symbol symbol = pgm.table[interp.tokenAddress];
return symbol.type==D2S;
}
final double getArg() {
interp.getLeftParen();
double arg = interp.getExpression();
interp.getRightParen();
return arg;
}
final double getFirstArg() {
interp.getLeftParen();
return interp.getExpression();
}
final double getNextArg() {
interp.getComma();
return interp.getExpression();
}
final double getLastArg() {
interp.getComma();
double arg = interp.getExpression();
interp.getRightParen();
return arg;
}
String getStringArg() {
interp.getLeftParen();
String arg = getString();
interp.getRightParen();
return arg;
}
final String getFirstString() {
interp.getLeftParen();
return getString();
}
final String getNextString() {
interp.getComma();
return getString();
}
final String getLastString() {
interp.getComma();
String arg = getString();
interp.getRightParen();
return arg;
}
boolean getBooleanArg() {
interp.getLeftParen();
double arg = interp.getBooleanExpression();
interp.checkBoolean(arg);
interp.getRightParen();
return arg==0?false:true;
}
final Variable getVariableArg() {
interp.getLeftParen();
Variable v = getVariable();
interp.getRightParen();
return v;
}
final Variable getFirstVariable() {
interp.getLeftParen();
return getVariable();
}
final Variable getNextVariable() {
interp.getComma();
return getVariable();
}
final Variable getLastVariable() {
interp.getComma();
Variable v = getVariable();
interp.getRightParen();
return v;
}
final Variable getVariable() {
interp.getToken();
if (interp.token!=WORD)
interp.error("Variable expected");
Variable v = interp.lookupLocalVariable(interp.tokenAddress);
if (v==null)
v = interp.push(interp.tokenAddress, 0.0, null, interp);
Variable[] array = v.getArray();
if (array!=null) {
int index = interp.getIndex();
checkIndex(index, 0, array.length-1);
v = array[index];
}
return v;
}
final Variable getFirstArrayVariable() {
interp.getLeftParen();
return getArrayVariable();
}
final Variable getNextArrayVariable() {
interp.getComma();
return getArrayVariable();
}
final Variable getLastArrayVariable() {
interp.getComma();
Variable v = getArrayVariable();
interp.getRightParen();
return v;
}
final Variable getArrayVariable() {
interp.getToken();
if (interp.token!=WORD)
interp.error("Variable expected");
Variable v = interp.lookupLocalVariable(interp.tokenAddress);
if (v==null)
v = interp.push(interp.tokenAddress, 0.0, null, interp);
return v;
}
final double[] getFirstArray() {
interp.getLeftParen();
return getNumericArray();
}
final double[] getNextArray() {
interp.getComma();
return getNumericArray();
}
final double[] getLastArray() {
interp.getComma();
double[] a = getNumericArray();
interp.getRightParen();
return a;
}
double[] getNumericArray() {
Variable[] a1 = getArray();
double[] a2 = new double[a1.length];
for (int i=0; i<a1.length; i++)
a2[i] = a1[i].getValue();
return a2;
}
String[] getStringArray() {
Variable[] a1 = getArray();
String[] a2 = new String[a1.length];
for (int i=0; i<a1.length; i++) {
String s = a1[i].getString();
if (s==null) s = "" + a1[i].getValue();
a2[i] = s;
}
return a2;
}
Variable[] getArray() {
interp.getToken();
boolean newArray = interp.token==ARRAY_FUNCTION && pgm.table[interp.tokenAddress].type==NEW_ARRAY;
if (!(interp.token==WORD||newArray))
interp.error("Array expected");
Variable[] a;
if (newArray)
a = getArrayFunction(NEW_ARRAY);
else {
Variable v = interp.lookupVariable();
a= v.getArray();
}
if (a==null)
interp.error("Array expected");
return a;
}
Color getColor() {
String color = getString();
color = color.toLowerCase(Locale.US);
if (color.equals("black"))
return Color.black;
else if (color.equals("white"))
return Color.white;
else if (color.equals("red"))
return Color.red;
else if (color.equals("green"))
return Color.green;
else if (color.equals("blue"))
return Color.blue;
else if (color.equals("cyan"))
return Color.cyan;
else if (color.equals("darkgray"))
return Color.darkGray;
else if (color.equals("gray"))
return Color.gray;
else if (color.equals("lightgray"))
return Color.lightGray;
else if (color.equals("magenta"))
return Color.magenta;
else if (color.equals("orange"))
return Color.orange;
else if (color.equals("yellow"))
return Color.yellow;
else if (color.equals("pink"))
return Color.pink;
else
interp.error("'red', 'green', etc. expected");
return null;
}
void checkIndex(int index, int lower, int upper) {
if (index<lower || index>upper)
interp.error("Index ("+index+") is outside of the "+lower+"-"+upper+" range");
}
void doRun() {
interp.getLeftParen();
String arg1 = getString();
interp.getToken();
if (!(interp.token==')' || interp.token==','))
interp.error("',' or ')' expected");
String arg2 = null;
if (interp.token==',') {
arg2 = getString();
interp.getRightParen();
}
if (arg2!=null)
IJ.run(arg1, arg2);
else
IJ.run(arg1);
resetImage();
IJ.setKeyUp(IJ.ALL_KEYS);
shiftKeyDown = altKeyDown = false;
}
void setForegroundColor() {
IJ.setForegroundColor((int)getFirstArg(), (int)getNextArg(), (int)getLastArg());
resetImage();
defaultColor = null;
defaultValue = Double.NaN;
}
void setBackgroundColor() {
IJ.setBackgroundColor((int)getFirstArg(), (int)getNextArg(), (int)getLastArg());
resetImage();
}
void setColor() {
colorSet = true;
interp.getLeftParen();
if (isStringArg()) {
defaultColor = getColor();
getProcessor().setColor(defaultColor);
defaultValue = Double.NaN;
interp.getRightParen();
return;
}
double arg1 = interp.getExpression();
if (interp.nextToken()==')')
{interp.getRightParen(); setColor(arg1); return;}
int red=(int)arg1, green=(int)getNextArg(), blue=(int)getLastArg();
if (red<0) red=0; if (green<0) green=0; if (blue<0) blue=0;
if (red>255) red=255; if (green>255) green=255; if (blue>255) blue=255;
defaultColor = new Color(red, green, blue);
getProcessor().setColor(defaultColor);
defaultValue = Double.NaN;
}
void setColor(double value) {
ImageProcessor ip = getProcessor();
ImagePlus imp = getImage();
switch (imp.getBitDepth()) {
case 8:
if (value<0 || value>255)
interp.error("Argument out of 8-bit range (0-255)");
ip.setValue(value);
break;
case 16:
if (imp.getLocalCalibration().isSigned16Bit())
value += 32768;
if (value<0 || value>65535)
interp.error("Argument out of 16-bit range (0-65535)");
ip.setValue(value);
break;
default:
ip.setValue(value);
break;
}
defaultValue = value;
defaultColor = null;
}
void makeLine() {
double x1d = getFirstArg();
double y1d = getNextArg();
double x2d = getNextArg();
interp.getComma();
double y2d = interp.getExpression();
interp.getToken();
if (interp.token==')')
IJ.makeLine(x1d, y1d, x2d, y2d);
else {
int x1 = (int)Math.round(x1d);
int y1 = (int)Math.round(y1d);
int x2 = (int)Math.round(x2d);
int y2 = (int)Math.round(y2d);
int max = 200;
int[] x = new int[max];
int[] y = new int[max];
x[0]=x1; y[0]=y1; x[1]=x2; y[1]=y2;
int n = 2;
while (interp.token==',' && n<max) {
x[n] = (int)Math.round(interp.getExpression());
if (n==2 && interp.nextToken()==')') {
interp.getRightParen();
Line.setWidth((int)x[n]);
IJ.makeLine(x1, y1, x2, y2);
return;
}
interp.getComma();
y[n] = (int)Math.round(interp.getExpression());
interp.getToken();
n++;
}
if (n==max && interp.token!=')')
interp.error("More than "+max+" points");
getImage().setRoi(new PolygonRoi(x, y, n, Roi.POLYLINE));
}
resetImage();
}
void makeOval() {
Roi previousRoi = getImage().getRoi();
if (shiftKeyDown||altKeyDown) getImage().saveRoi();
IJ.makeOval((int)getFirstArg(), (int)getNextArg(), (int)getNextArg(), (int)getLastArg());
Roi roi = getImage().getRoi();
if (previousRoi!=null && roi!=null)
updateRoi(roi);
resetImage();
}
void makeRectangle() {
Roi previousRoi = getImage().getRoi();
if (shiftKeyDown||altKeyDown) getImage().saveRoi();
IJ.makeRectangle((int)getFirstArg(), (int)getNextArg(), (int)getNextArg(), (int)getLastArg());
Roi roi = getImage().getRoi();
if (previousRoi!=null && roi!=null)
updateRoi(roi);
resetImage();
}
ImagePlus getImage() {
if (defaultImp==null)
defaultImp = IJ.getImage();
if (defaultImp==null)
{interp.error("No image"); return null;}
if (defaultImp.getWindow()==null && IJ.getInstance()!=null && !interp.isBatchMode() && WindowManager.getTempCurrentImage()==null)
throw new RuntimeException(Macro.MACRO_CANCELED);
return defaultImp;
}
void resetImage() {
defaultImp = null;
defaultIP = null;
colorSet = fontSet = false;
}
ImageProcessor getProcessor() {
if (defaultIP==null) {
defaultImp = getImage();
defaultIP = defaultImp.getProcessor();
}
return defaultIP;
}
int getType() {
if (defaultImp==null)
defaultImp = IJ.getImage();
imageType = defaultImp.getType();
return imageType;
}
void setPixel() {
interp.getLeftParen();
int a1 = (int)interp.getExpression();
interp.getComma();
double a2 = interp.getExpression();
interp.getToken();
if (interp.token==',') {
double a3 = interp.getExpression();
interp.getRightParen();
if (getType()==ImagePlus.GRAY32)
getProcessor().putPixelValue(a1, (int)a2, a3);
else
getProcessor().putPixel(a1, (int)a2, (int)a3);
} else {
if (interp.token!=')') interp.error("')' expected");
getProcessor().setf(a1, (float)a2);
}
updateNeeded = true;
}
double getPixel() {
interp.getLeftParen();
int a1 = (int)interp.getExpression();
ImageProcessor ip = getProcessor();
double value = 0.0;
interp.getToken();
if (interp.token==',') {
int a2 = (int)interp.getExpression();
interp.getRightParen();
if (getType()==ImagePlus.GRAY32)
value = ip.getPixelValue(a1, a2);
else
value = ip.getPixel(a1, a2);
} else {
if (interp.token!=')') interp.error("')' expected");
value = ip.getf(a1);
}
return value;
}
void setZCoordinate() {
int z = (int)getArg();
ImagePlus imp = getImage();
ImageStack stack = imp.getStack();
int size = stack.getSize();
if (z<0 || z>=size)
interp.error("Z coordinate ("+z+") is out of 0-"+(size-1)+ " range");
this.defaultIP = stack.getProcessor(z+1);
}
void moveTo() {
interp.getLeftParen();
int a1 = (int)(interp.getExpression()+0.5);
interp.getComma();
int a2 = (int)(interp.getExpression()+0.5);
interp.getRightParen();
getProcessor().moveTo(a1, a2);
}
void lineTo() {
interp.getLeftParen();
int a1 = (int)(interp.getExpression()+0.5);
interp.getComma();
int a2 = (int)(interp.getExpression()+0.5);
interp.getRightParen();
ImageProcessor ip = getProcessor();
if (!colorSet) setForegroundColor(ip);
ip.lineTo(a1, a2);
updateAndDraw(defaultImp);
}
void drawLine() {
interp.getLeftParen();
int x1 = (int)(interp.getExpression()+0.5);
interp.getComma();
int y1 = (int)(interp.getExpression()+0.5);
interp.getComma();
int x2 = (int)(interp.getExpression()+0.5);
interp.getComma();
int y2 = (int)(interp.getExpression()+0.5);
interp.getRightParen();
ImageProcessor ip = getProcessor();
if (!colorSet) setForegroundColor(ip);
ip.drawLine(x1, y1, x2, y2);
updateAndDraw(defaultImp);
}
void setForegroundColor(ImageProcessor ip) {
if (defaultColor!=null)
ip.setColor(defaultColor);
else if (!Double.isNaN(defaultValue))
ip.setValue(defaultValue);
else
ip.setColor(Toolbar.getForegroundColor());
colorSet = true;
}
void doIPMethod(int type) {
interp.getParens();
ImageProcessor ip = getProcessor();
switch (type) {
case SNAPSHOT: ip.snapshot(); break;
case RESET:
ip.reset();
updateNeeded = true;
break;
case FILL:
ImagePlus imp = getImage();
Roi roi = imp.getRoi();
if (!colorSet) setForegroundColor(ip);
if (roi==null) {
ip.resetRoi();
ip.fill();
} else {
ip.setRoi(roi);
ip.fill(ip.getMask());
}
updateAndDraw(imp);
break;
}
}
void updateAndDraw(ImagePlus imp) {
if (autoUpdate)
imp.updateChannelAndDraw();
else
updateNeeded = true;
}
void updateDisplay() {
if (updateNeeded && WindowManager.getImageCount()>0) {
ImagePlus imp = getImage();
imp.updateAndDraw();
updateNeeded = false;
}
}
void drawString() {
interp.getLeftParen();
String str = getString();
interp.getComma();
int x = (int)(interp.getExpression()+0.5);
interp.getComma();
int y = (int)(interp.getExpression()+0.5);
interp.getRightParen();
ImageProcessor ip = getProcessor();
if (!colorSet)
setForegroundColor(ip);
setFont(ip);
ip.setJustification(justification);
ip.setAntialiasedText(antialiasedText);
ip.drawString(str, x, y);
updateAndDraw(defaultImp);
}
void setFont(ImageProcessor ip) {
if (font!=null && !fontSet)
ip.setFont(font);
fontSet = true;
}
void setJustification() {
String str = getStringArg().toLowerCase(Locale.US);
int just = ImageProcessor.LEFT_JUSTIFY;
if (str.equals("center"))
just = ImageProcessor.CENTER_JUSTIFY;
else if (str.equals("right"))
just = ImageProcessor.RIGHT_JUSTIFY;
justification = just;
}
void changeValues() {
double darg1 = getFirstArg();
double darg2 = getNextArg();
double darg3 = getLastArg();
ImagePlus imp = getImage();
ImageProcessor ip = getProcessor();
Roi roi = imp.getRoi();
ImageProcessor mask = null;
if (roi==null || !roi.isArea()) {
ip.resetRoi();
roi = null;
} else {
ip.setRoi(roi);
mask = ip.getMask();
if (mask!=null) ip.snapshot();
}
int xmin=0, ymin=0, xmax=imp.getWidth(), ymax=imp.getHeight();
if (roi!=null) {
Rectangle r = roi.getBounds();
xmin=r.x; ymin=r.y; xmax=r.x+r.width; ymax=r.y+r.height;
}
boolean isFloat = getType()==ImagePlus.GRAY32;
if (imp.getBitDepth()==24) {
darg1 = (int)darg1&0xffffff;
darg2 = (int)darg2&0xffffff;
}
double v;
for (int y=ymin; y<ymax; y++) {
for (int x=xmin; x<xmax; x++) {
v = isFloat?ip.getPixelValue(x,y):ip.getPixel(x,y)&0xffffff;
if (v>=darg1 && v<=darg2) {
if (isFloat)
ip.putPixelValue(x, y, darg3);
else
ip.putPixel(x, y, (int)darg3);
}
}
}
if (mask!=null) ip.reset(mask);
if (imp.getType()==ImagePlus.GRAY16 || imp.getType()==ImagePlus.GRAY32)
ip.resetMinAndMax();
imp.updateAndDraw();
updateNeeded = false;
}
void requires() {
if (IJ.versionLessThan(getStringArg()))
interp.done = true;
}
Random ran;
double random() {
interp.getParens();
if (ran==null)
ran = new Random();
return ran.nextDouble();
}
//void setSeed() {
// long seed = (long)getArg();
// if (ran==null)
// ran = new Random(seed);
// else
// ran.setSeed(seed);
//}
double getResult() {
interp.getLeftParen();
String column = getString();
int row = -1;
if (interp.nextNonEolToken()==',') {
interp.getComma();
row = (int)interp.getExpression();
}
interp.getRightParen();
ResultsTable rt = Analyzer.getResultsTable();
int counter = rt.getCounter();
if (counter==0)
interp.error("\"Results\" table empty");
if (row==-1) row = counter-1;
if (row<0 || row>=counter)
interp.error("Row ("+row+") out of range");
int col = rt.getColumnIndex(column);
if (!rt.columnExists(col))
return Double.NaN;
else
return rt.getValueAsDouble(col, row);
}
String getResultLabel() {
int row = (int)getArg();
ResultsTable rt = Analyzer.getResultsTable();
int counter = rt.getCounter();
if (counter==0)
interp.error("\"Results\" table empty");
if (row<0 || row>=counter)
interp.error("Row ("+row+") out of range");
String label = rt.getLabel(row);
return label!=null?label:"";
}
void setResult() {
interp.getLeftParen();
String column = getString();
interp.getComma();
int row = (int)interp.getExpression();
interp.getComma();
double value = 0.0;
String label = null;
if (column.equals("Label"))
label = getString();
else
value = interp.getExpression();
interp.getRightParen();
ResultsTable rt = Analyzer.getResultsTable();
if (row<0 || row>rt.getCounter())
interp.error("Row ("+row+") out of range");
if (row==rt.getCounter())
rt.incrementCounter();
try {
if (label!=null)
rt.setLabel(label, row);
else
rt.setValue(column, row, value);
} catch (Exception e) {
interp.error(""+e.getMessage());
}
}
void updateResults() {
interp.getParens();
ResultsTable rt = Analyzer.getResultsTable();
rt.show("Results");
}
double getNumber() {
String prompt = getFirstString();
double defaultValue = getLastArg();
String title = interp.macroName!=null?interp.macroName:"";
if (title.endsWith(" Options"))
title = title.substring(0, title.length()-8);
GenericDialog gd = new GenericDialog(title);
int decimalPlaces = (int)defaultValue==defaultValue?0:2;
gd.addNumericField(prompt, defaultValue, decimalPlaces);
gd.showDialog();
if (gd.wasCanceled()) {
interp.done = true;
return defaultValue;
}
double v = gd.getNextNumber();
if (gd.invalidNumber())
return defaultValue;
else
return v;
}
double getBoolean() {
String prompt = getStringArg();
String title = interp.macroName!=null?interp.macroName:"";
if (title.endsWith(" Options"))
title = title.substring(0, title.length()-8);
YesNoCancelDialog d = new YesNoCancelDialog(IJ.getInstance(), title, prompt);
if (d.cancelPressed()) {
interp.done = true;
return 0.0;
} else if (d.yesPressed())
return 1.0;
else
return 0.0;
}
double getBoolean2() {
String prompt = getFirstString();
interp.getComma();
double defaultValue = interp.getBooleanExpression();
interp.checkBoolean(defaultValue);
interp.getRightParen();
String title = interp.macroName!=null?interp.macroName:"";
if (title.endsWith(" Options"))
title = title.substring(0, title.length()-8);
GenericDialog gd = new GenericDialog(title);
gd.addCheckbox(prompt, defaultValue==1.0?true:false);
gd.showDialog();
if (gd.wasCanceled()) {
interp.done = true;
return 0.0;
}
return gd.getNextBoolean()?1.0:0.0;
}
String getStringDialog() {
interp.getLeftParen();
String prompt = getString();
interp.getComma();
String defaultStr = getString();
interp.getRightParen();
String title = interp.macroName!=null?interp.macroName:"";
if (title.endsWith(" Options"))
title = title.substring(0, title.length()-8);
GenericDialog gd = new GenericDialog(title);
gd.addStringField(prompt, defaultStr, 20);
gd.showDialog();
String str = "";
if (gd.wasCanceled())
interp.done = true;
else
str = gd.getNextString();
return str;
}
String d2s() {
return IJ.d2s(getFirstArg(), (int)getLastArg());
}
String toString(int base) {
int arg = (int)getArg();
if (base==2)
return Integer.toBinaryString(arg);
else
return Integer.toHexString(arg);
}
double getStackSize() {
interp.getParens();
return getImage().getStackSize();
}
double getImageCount() {
interp.getParens();
return WindowManager.getImageCount();
}
double getResultsCount() {
interp.getParens();
return Analyzer.getResultsTable().getCounter();
}
void getCoordinates() {
Variable xCoordinates = getFirstArrayVariable();
Variable yCoordinates = getLastArrayVariable();
resetImage();
ImagePlus imp = getImage();
Roi roi = imp.getRoi();
if (roi==null)
interp.error("Selection required");
Polygon p = roi.getPolygon();
FloatPolygon fp = roi.getFloatPolygon();
Variable[] xa = new Variable[p.npoints];
Variable[] ya = new Variable[p.npoints];
if (fp!=null) { //spline fit polygon
for (int i=0; i<p.npoints; i++)
xa[i] = new Variable(fp.xpoints[i]);
for (int i=0; i<p.npoints; i++)
ya[i] = new Variable(fp.ypoints[i]);
} else {
for (int i=0; i<p.npoints; i++)
xa[i] = new Variable(p.xpoints[i]);
for (int i=0; i<p.npoints; i++)
ya[i] = new Variable(p.ypoints[i]);
}
xCoordinates.setArray(xa);
yCoordinates.setArray(ya);
}
Variable[] getProfile() {
interp.getParens();
ImagePlus imp = getImage();
if (imp.getRoi()==null)
interp.error("Selection required");
ProfilePlot pp = new ProfilePlot(imp, IJ.altKeyDown());
double[] array = pp.getProfile();
if (array==null)
{interp.done=true; return null;}
else
return new Variable(array).getArray();
}
Variable[] newArray() {
interp.getLeftParen();
int next = interp.nextNonEolToken();
if (next==STRING_CONSTANT || interp.nextNextNonEolToken()==','
|| next=='-' || next==PI)
return initNewArray();
int size = (int)interp.getExpression();
interp.getRightParen();
Variable[] array = new Variable[size];
for (int i=0; i<size; i++)
array[i] = new Variable();
return array;
}
Variable[] split() {
String s1 = getFirstString();
String s2 = null;
if (interp.nextToken()==')')
interp.getRightParen();
else
s2 = getLastString();
if (s1==null) return null;
String[] strings = (s2==null||s2.equals(""))?Tools.split(s1):Tools.split(s1, s2);
Variable[] array = new Variable[strings.length];
for (int i=0; i<strings.length; i++)
array[i] = new Variable(0, 0.0, strings[i]);
return array;
}
Variable[] getFileList() {
String dir = getStringArg();
File f = new File(dir);
if (!f.exists() || !f.isDirectory())
return new Variable[0];
String[] list = f.list();
if (list==null)
return new Variable[0];
if (System.getProperty("os.name").indexOf("Linux")!=-1)
ij.util.StringSorter.sort(list);
File f2;
int hidden = 0;
for (int i=0; i<list.length; i++) {
if (list[i].startsWith(".")) {
list[i] = null;
hidden++;
} else {
f2 = new File(dir, list[i]);
if (f2.isDirectory())
list[i] = list[i] + "/";
}
}
int n = list.length-hidden;
if (n<=0)
return new Variable[0];
if (hidden>0) {
String[] list2 = new String[n];
int j = 0;
for (int i=0; i<list.length; i++) {
if (list[i]!=null)
list2[j++] = list[i];
}
list = list2;
}
Variable[] array = new Variable[n];
for (int i=0; i<n; i++)
array[i] = new Variable(0, 0.0, list[i]);
return array;
}
Variable[] initNewArray() {
Vector vector = new Vector();
int size = 0;
boolean stringArray = false;
do {
Variable v = new Variable();
int tok = interp.nextNonEolToken();
if (tok==STRING_CONSTANT||tok==STRING_FUNCTION||(tok==WORD&&stringArray)) {
v.setString(getString());
stringArray = true;
} else
v.setValue(interp.getExpression());
vector.addElement(v);
size++;
interp.getToken();
} while (interp.token==',');
if (interp.token!=')')
interp.error("';' expected");
Variable[] array = new Variable[size];
vector.copyInto((Variable[])array);
return array;
}
String fromCharCode() {
char[] chars = new char[100];
int count = 0;
interp.getLeftParen();
while(interp.nextToken()!=')') {
int value = (int)interp.getExpression();
if (value<0 || value>65535)
interp.error("Value (" + value + ") out of 0-65535 range");
chars[count++] = (char)value;
if (interp.nextToken()==',')
interp.getToken();
}
interp.getRightParen();
return new String(chars, 0, count);
}
String getInfo() {
if (interp.nextNextNonEolToken()==STRING_CONSTANT
|| (interp.nextNonEolToken()=='('&&interp.nextNextNonEolToken()!=')'))
return getInfo(getStringArg());
else {
interp.getParens();
return getWindowContents();
}
}
String getInfo(String key) {
if (key.equals("image.subtitle")) {
ImagePlus imp = getImage();
ImageWindow win = imp.getWindow();
return win!=null?win.createSubtitle():"";
} else if (key.equals("slice.label")) {
ImagePlus imp = getImage();
if (imp.getStackSize()==1) return "";
String label = imp.getStack().getShortSliceLabel(imp.getCurrentSlice());
return label!=null?label:"";
} else if (key.equals("window.contents")) {
return getWindowContents();
} else if (key.equals("image.description")) {
String description = "";
FileInfo fi = getImage().getOriginalFileInfo();
if (fi!=null) description = fi.description;
if (description==null) description = "";
return description;
} else {
String value = "";
try {value = System.getProperty(key);}
catch (Exception e) {};
return value!=null?value:"";
}
}
String getWindowContents() {
Frame frame = WindowManager.getFrontWindow();
if (frame!=null && frame instanceof TextWindow) {
TextPanel tp = ((TextWindow)frame).getTextPanel();
return tp.getText();
} else if (frame!=null && frame instanceof Editor) {
return ((Editor)frame).getText();
} else if (frame!=null && frame instanceof Recorder) {
return ((Recorder)frame).getText();
} else
return getImageInfo();
}
String getImageInfo() {
ImagePlus imp = getImage();
Info infoPlugin = new Info();
return infoPlugin.getImageInfo(imp, getProcessor());
}
public String getDirectory() {
String dir = IJ.getDirectory(getStringArg());
if (dir==null) dir = "";
return dir;
}
double getSelectionType() {
interp.getParens();
double type = -1;
ImagePlus imp = getImage();
Roi roi = imp.getRoi();
if (roi!=null)
type = roi.getType();
return type;
}
void showMessage(boolean withCancel) {
String message;
interp.getLeftParen();
String title = getString();
if (interp.nextToken()==',') {
interp.getComma();
message = getString();
} else {
message = title;
title = "";
}
interp.getRightParen();
if (withCancel)
IJ.showMessageWithCancel(title, message);
else
IJ.showMessage(title, message);
}
double lengthOf() {
int length = 0;
interp.getLeftParen();
switch (interp.nextToken()) {
case STRING_CONSTANT:
case STRING_FUNCTION:
case USER_FUNCTION:
length = getString().length();
break;
case WORD:
if (pgm.code[interp.pc+2]=='[') {
length = getString().length();
break;
}
interp.getToken();
Variable v = interp.lookupVariable();
if (v==null) return 0.0;
String s = v.getString();
if (s!=null)
length = s.length();
else {
Variable[] array = v.getArray();
if (array!=null)
length = array.length;
else
interp.error("String or array expected");
}
break;
default:
interp.error("String or array expected");
}
interp.getRightParen();
return length;
}
void getCursorLoc() {
Variable x = getFirstVariable();
Variable y = getNextVariable();
Variable z = getNextVariable();
Variable flags = getLastVariable();
ImagePlus imp = getImage();
ImageCanvas ic = imp.getCanvas();
if (ic==null) return;
Point p = ic.getCursorLoc();
x.setValue(p.x);
y.setValue(p.y);
z.setValue(imp.getCurrentSlice()-1);
flags.setValue(ic.getModifiers());
}
void getLine() {
Variable vx1 = getFirstVariable();
Variable vy1 = getNextVariable();
Variable vx2 = getNextVariable();
Variable vy2 = getNextVariable();
Variable lineWidth = getLastVariable();
resetImage();
ImagePlus imp = getImage();
double x1=-1, y1=-1, x2=-1, y2=-1;
Roi roi = imp.getRoi();
if (roi!=null && roi.getType()==Roi.LINE) {
Line line = (Line)roi;
x1=line.x1d; y1=line.y1d; x2=line.x2d; y2=line.y2d;
}
vx1.setValue(x1);
vy1.setValue(y1);
vx2.setValue(x2);
vy2.setValue(y2);
lineWidth.setValue(Line.getWidth());
}
void getVoxelSize() {
Variable width = getFirstVariable();
Variable height = getNextVariable();
Variable depth = getNextVariable();
Variable unit = getLastVariable();
resetImage();
ImagePlus imp = getImage();
Calibration cal = imp.getCalibration();
width.setValue(cal.pixelWidth);
height.setValue(cal.pixelHeight);
depth.setValue(cal.pixelDepth);
unit.setString(cal.getUnits());
}
void getHistogram() {
interp.getLeftParen();
Variable values = null;
if (interp.nextToken()==NUMBER)
interp.getExpression();
else
values = getArrayVariable();
Variable counts = getNextArrayVariable();
interp.getComma();
int nBins = (int)interp.getExpression();
ImagePlus imp = getImage();
double histMin=0.0, histMax=0.0;
boolean setMinMax = false;
int bitDepth = imp.getBitDepth();
if (interp.nextToken()==',') {
histMin = getNextArg();
histMax = getLastArg();
if (bitDepth==8 || bitDepth==24)
interp.error("16 or 32-bit image required to set histMin and histMax");
setMinMax = true;
} else
interp.getRightParen();
if ((bitDepth==8||bitDepth==24) && nBins!=256)
interp.error("Bin count ("+nBins+") must be 256 for 8-bit and RGB images");
if (nBins==65536 && bitDepth==16) {
Variable[] array = counts.getArray();
int[] hist = getProcessor().getHistogram();
if (array!=null && array.length==nBins) {
for (int i=0; i<nBins; i++)
array[i].setValue(hist[i]);
} else
counts.setArray(new Variable(hist).getArray());
return;
}
ImageStatistics stats;
if (setMinMax)
stats = imp.getStatistics(AREA+MEAN+MODE+MIN_MAX, nBins, histMin, histMax);
else
stats = imp.getStatistics(AREA+MEAN+MODE+MIN_MAX, nBins);
if (values!=null) {
Calibration cal = imp.getCalibration();
double[] array = new double[nBins];
double value = cal.getCValue(stats.histMin);
double inc = 1.0;
if (bitDepth==16 || bitDepth==32 || cal.calibrated())
inc = (cal.getCValue(stats.histMax) - cal.getCValue(stats.histMin))/stats.nBins;
for (int i=0; i<nBins; i++) {
array[i] = value;
value += inc;
}
values.setArray(new Variable(array).getArray());
}
Variable[] array = counts.getArray();
if (array!=null && array.length==nBins) {
for (int i=0; i<nBins; i++)
array[i].setValue(stats.histogram[i]);
} else
counts.setArray(new Variable(stats.histogram).getArray());
}
void getLut() {
Variable reds = getFirstArrayVariable();
Variable greens = getNextArrayVariable();
Variable blues = getLastArrayVariable();
resetImage();
ImagePlus imp = getImage();
IndexColorModel cm = null;
if (imp.isComposite())
cm = ((CompositeImage)imp).getChannelLut();
else {
ImageProcessor ip = imp.getProcessor();
if (ip instanceof ColorProcessor)
interp.error("Non-RGB image expected");
cm = (IndexColorModel)ip.getColorModel();
}
int mapSize = cm.getMapSize();
byte[] rLUT = new byte[mapSize];
byte[] gLUT = new byte[mapSize];
byte[] bLUT = new byte[mapSize];
cm.getReds(rLUT);
cm.getGreens(gLUT);
cm.getBlues(bLUT);
reds.setArray(new Variable(rLUT).getArray());
greens.setArray(new Variable(gLUT).getArray());
blues.setArray(new Variable(bLUT).getArray());
}
void setLut() {
double[] reds = getFirstArray();
double[] greens = getNextArray();
double[] blues = getLastArray();
int length = reds.length;
if (greens.length!=length || blues.length!=length)
interp.error("Arrays are not the same length");
resetImage();
ImagePlus imp = getImage();
if (imp.getBitDepth()==24)
interp.error("Non-RGB image expected");
ImageProcessor ip = getProcessor();
byte[] r = new byte[length];
byte[] g = new byte[length];
byte[] b = new byte[length];
for (int i=0; i<length; i++) {
r[i] = (byte)reds[i];
g[i] = (byte)greens[i];
b[i] = (byte)blues[i];
}
LUT lut = new LUT(8, length, r, g, b);
if (imp.isComposite())
((CompositeImage)imp).setChannelLut(lut);
else
ip.setColorModel(lut);
imp.updateAndDraw();
updateNeeded = false;
}
void getThreshold() {
Variable lower = getFirstVariable();
Variable upper = getLastVariable();
ImagePlus imp = getImage();
ImageProcessor ip = getProcessor();
double t1 = ip.getMinThreshold();
double t2 = ip.getMaxThreshold();
if (t1==ImageProcessor.NO_THRESHOLD) {
t1 = -1;
t2 = -1;
} else if (imp.getBitDepth()==16) {
Calibration cal = imp.getCalibration();
t1 = cal.getCValue(t1);
t2 = cal.getCValue(t2);
}
lower.setValue(t1);
upper.setValue(t2);
}
void getPixelSize() {
Variable unit = getFirstVariable();
Variable width = getNextVariable();
Variable height = getNextVaria