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; CurveFitter fitter; 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; case FIT: value = fit(); 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; iupper) 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() { int lineWidth = getProcessor().getLineWidth(); IJ.setForegroundColor((int)getFirstArg(), (int)getNextArg(), (int)getLastArg()); resetImage(); getProcessor().setLineWidth(lineWidth); 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=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=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