All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ij.macro.Functions Maven / Gradle / Ivy

Go to download

ImageJ is an open source Java image processing program inspired by NIH Image for the Macintosh.

There is a newer version: 1.54m
Show newest version
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.*;
import java.awt.geom.*;


/** This class implements the built-in macro functions. */
public class Functions implements MacroConstants, Measurements {
	Interpreter interp;
	Program pgm;
	boolean updateNeeded;
	boolean autoUpdate = true;
	ImageProcessor defaultIP;
	ImagePlus defaultImp;
	int imageType;
	boolean fontSet;
	Color globalColor;
	double globalValue = Double.NaN;
	int globalLineWidth;
	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 showFitDialog;
	boolean logFitResults;
	boolean resultsPending;
	Overlay offscreenOverlay;
	Overlay overlayClipboard;
	Roi roiClipboard;
	GeneralPath overlayPath;
	boolean overlayDrawLabels;
	ResultsTable currentTable;
	ResultsTable unUpdatedTable;

	// save/restore settings
	boolean saveSettingsCalled;
	boolean usePointerCursor, hideProcessStackDialog;
	float divideByZeroValue;
	int jpegQuality;
	int saveLineWidth;
	boolean doScaling;
	boolean weightedColor;
	double[] weights;
	boolean interpolateScaledImages, open100Percent, blackCanvas;
	boolean useJFileChooser,debugMode;
	Color foregroundColor, backgroundColor, roiColor;
	boolean pointAutoMeasure, requireControlKey, useInvertingLut;
	boolean disablePopup;
	int measurements;
	int decimalPlaces;
	boolean blackBackground;
	boolean autoContrast;
	static WaitForUserDialog waitForUserDialog;
	int pasteMode;
	boolean expandableArrays;
	int plotWidth;
	int plotHeight;
	int plotFontSize;
	boolean plotInterpolate;
	boolean plotNoGridLines;
	boolean plotNoTicks;
	boolean profileVerticalProfile;
	boolean profileSubPixelResolution;
	boolean waitForCompletion = true;


	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(); interp.selectCount++; 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: case WRITE: print(); break;
			case DO_WAND: doWand(); break;
			case SET_MIN_MAX: setMinAndMax(); 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_ARROW: makeArrow(); break;
			case MAKE_OVAL: makeOval(); break;
			case MAKE_RECTANGLE: makeRectangle(); break;
			case MAKE_ROTATED_RECT: makeRotatedRectangle(); 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: showStatus(); 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: 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(null); break;
			case UPDATE_RESULTS: updateResults(); break;
			case SET_BATCH_MODE: setBatchMode(); 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.MACRO, 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: 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;
			case MAKE_TEXT: makeText(); break;
			case MAKE_ELLIPSE: makeEllipse(); break;
			case GET_DISPLAYED_AREA: getDisplayedArea(); break;
			case TO_SCALED: toScaled(); break;
			case TO_UNSCALED: toUnscaled(); 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 MATH: value = doMath(); 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(null); 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(); 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(null); break;
			case LAST_INDEX_OF: value=getFirstString().lastIndexOf(getLastString()); break;
			case CHAR_CODE_AT: value=charCodeAt(); 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(null); break;
			case GET_STRING_WIDTH: value = getStringWidth(); break;
			case FIT: value = fit(); break;
			case OVERLAY: value = overlay(); break;
			case SELECTION_CONTAINS: value = selectionContains(); break;
			case PLOT: value = doPlot(); 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(); str=getImage().getTitle(); break;
			case GET_STRING: str = getStringDialog(); break;
			case SUBSTRING: str=substring(null); 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: case GET_DIR: 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(null); 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;
			case DEBUG: str = debug(); break;
			case IJ_CALL: str = ijCall(); break;
			case GET_RESULT_STRING: str = getResultString(null); 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;
			case ARRAY_FUNC: array = doArray(); break;
			default:
				array = null;
				interp.error("Array function expected");
		}
		return array;
	}

	// Type must be added to Interpreter.getExpressionType() and
	// Interpreter.isString(), and functions returning a string must
	// be added to isStringFunction().
	Variable getVariableFunction(int type) {
		Variable var = null;
		switch (type) {
			case TABLE: var = doTable(); break;
			case ROI: var = doRoi(); break;
			case ROI_MANAGER2: var = doRoiManager(); break;
			case PROPERTY: var = doProperty(); break;
			default:
				interp.error("Variable function expected");
		}
		if (var==null)
			var = new Variable(Double.NaN);
		return var;
	}

	private void setLineWidth(int width) {
		if (WindowManager.getCurrentImage()!=null) {
			if (overlayPath!=null && width!=globalLineWidth)
				addDrawingToOverlay(getImage());
			getProcessor().setLineWidth(width);
		}
		globalLineWidth = width;
	}

	private double doMath() {
		interp.getToken();
		if (interp.token!='.')
			interp.error("'.' expected");
		interp.getToken();
		if (!(interp.token==WORD||interp.token==NUMERIC_FUNCTION))
			interp.error("Function name expected: ");
		String name = interp.tokenString;
		if (name.equals("min"))
			return Math.min(getFirstArg(), getLastArg());
		else if (name.equals("max"))
			return Math.max(getFirstArg(), getLastArg());
		else if (name.equals("pow"))
			return Math.pow(getFirstArg(), getLastArg());
		else if (name.equals("atan2"))
			return Math.atan2(getFirstArg(), getLastArg());
		double arg = getArg();
		if (name.equals("ceil"))
			return Math.ceil(arg);
		else if (name.equals("abs"))
			return Math.abs(arg);
		else if (name.equals("cos"))
			return Math.cos(arg);
		else if (name.equals("exp"))
			return Math.exp(arg);
		else if (name.equals("floor"))
			return Math.floor(arg);
		else if (name.equals("log"))
			return Math.log(arg);
		else if (name.equals("log10"))
			return Math.log10(arg);
		else if (name.equals("round"))
			return Math.round(arg);
		else if (name.equals("sin"))
			return Math.sin(arg);
		else if (name.equals("sqr"))
			return arg*arg;
		else if (name.equals("sqrt"))
			return Math.sqrt(arg);
		else if (name.equals("tan"))
			return Math.tan(arg);
		else if (name.equals("atan"))
			return Math.atan(arg);
		else if (name.equals("asin"))
			return Math.asin(arg);
		else if (name.equals("acos"))
			return Math.acos(arg);
		else if (name.equals("erf"))
			return IJMath.erf(arg);
		else
			interp.error("Unrecognized function name");
		return Double.NaN;
	}

	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, v.getArraySize()-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();
		}
		IJ.run(this.interp, arg1, arg2);
		resetImage();
		IJ.setKeyUp(IJ.ALL_KEYS);
		shiftKeyDown = altKeyDown = false;
	}

	void setForegroundColor() {
		boolean isImage = WindowManager.getCurrentImage()!=null;
		int lnWidth = 0;
		if (isImage)
			lnWidth = getProcessor().getLineWidth();
		int red=0, green=0, blue=0;
		int arg1 = (int)getFirstArg();
		if (interp.nextToken()==')') {
			interp.getRightParen();
			red = (arg1&0xff0000)>>16;
			green = (arg1&0xff00)>>8;
			blue = arg1&0xff;
		} else {
			red = arg1;
			green = (int)getNextArg();
			blue = (int)getLastArg();
		}
		IJ.setForegroundColor(red, green, blue);
		resetImage();
		if (isImage)
			setLineWidth(lnWidth);
		globalColor = null;
		globalValue = Double.NaN;
	}

	void setBackgroundColor() {
		int red=0, green=0, blue=0;
		int arg1 = (int)getFirstArg();
		if (interp.nextToken()==')') {
			interp.getRightParen();
			red = (arg1&0xff0000)>>16;
			green = (arg1&0xff00)>>8;
			blue = arg1&0xff;
		} else {
			red = arg1;
			green = (int)getNextArg();
			blue = (int)getLastArg();
		}
		IJ.setBackgroundColor(red, green, blue);
		resetImage();
	}

	void setColor() {
		interp.getLeftParen();
		if (isStringArg()) {
			globalColor = getColor();
			globalValue = Double.NaN;
			ImagePlus imp = WindowManager.getCurrentImage();
			if (imp!=null) {
				if (overlayPath!=null)
					addDrawingToOverlay(imp);
				getProcessor().setColor(globalColor);
			}
			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;
		globalColor = new Color(red, green, blue);
		globalValue = Double.NaN;
		if (WindowManager.getCurrentImage()!=null)
			getProcessor().setColor(globalColor);
	}

	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;
		}
		globalValue = value;
		globalColor = 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 {
			Polygon points = new Polygon();
			points.addPoint((int)Math.round(x1d),(int)Math.round(y1d));
			points.addPoint((int)Math.round(x2d),(int)Math.round(y2d));
			while (interp.token==',') {
				int x = (int)Math.round(interp.getExpression());
				if (points.npoints==2 && interp.nextToken()==')') {
					interp.getRightParen();
					Roi line = new Line(x1d, y1d, x2d, y2d);
					line.updateWideLine((float)x);
					getImage().setRoi(line);
					return;
				}
				interp.getComma();
				int y = (int)Math.round(interp.getExpression());
				points.addPoint(x,y);
				interp.getToken();
			}
			getImage().setRoi(new PolygonRoi(points, Roi.POLYLINE));
		}
		resetImage();
	}

	void makeArrow() {
		String options = "";
		double x1 = getFirstArg();
		double y1 = getNextArg();
		double x2 = getNextArg();
		double y2 = getNextArg();
		if (interp.nextToken()==',')
			options = getNextString();
		interp.getRightParen();
		Arrow arrow = new Arrow(x1, y1, x2, y2);
		arrow.setStyle(options);
		getImage().setRoi(arrow);
	}

	void makeOval() {
		Roi previousRoi = getImage().getRoi();
		if (shiftKeyDown||altKeyDown) getImage().saveRoi();
		IJ.makeOval(getFirstArg(), getNextArg(), getNextArg(), getLastArg());
		Roi roi = getImage().getRoi();
		if (previousRoi!=null && roi!=null)
			updateRoi(roi);
		resetImage();
		shiftKeyDown = altKeyDown = false;
		IJ.setKeyUp(IJ.ALL_KEYS);
	}

	void makeRectangle() {
		Roi previousRoi = getImage().getRoi();
		if (shiftKeyDown||altKeyDown) getImage().saveRoi();
		double x = getFirstArg();
		double y = getNextArg();
		double w = getNextArg();
		double h = getNextArg();
		int arcSize = 0;
		if (interp.nextToken()==',') {
			interp.getComma();
			arcSize = (int)interp.getExpression();
		}
		interp.getRightParen();
		if (arcSize<1)
			IJ.makeRectangle(x, y, w, h);
		else {
			ImagePlus imp = getImage();
			imp.setRoi(new Roi(x,y,w,h,arcSize));
		}
		Roi roi = getImage().getRoi();
		if (previousRoi!=null && roi!=null)
			updateRoi(roi);
		resetImage();
		shiftKeyDown = altKeyDown = false;
		IJ.setKeyUp(IJ.ALL_KEYS);
	}

	void makeRotatedRectangle() {
		getImage().setRoi(new RotatedRectRoi(getFirstArg(), getNextArg(), getNextArg(), getNextArg(), getLastArg()));
		resetImage();
	}

	ImagePlus getImage() {
		ImagePlus imp = IJ.getImage(interp);
		if (imp.getWindow()==null && IJ.getInstance()!=null && !interp.isBatchMode() && WindowManager.getTempCurrentImage()==null)
			throw new RuntimeException(Macro.MACRO_CANCELED);
		defaultIP = null;
		defaultImp = imp;
		return imp;
	}

	void resetImage() {
		defaultImp = null;
		defaultIP = null;
		fontSet = false;
	}

	ImageProcessor getProcessor() {
		if (defaultIP==null) {
			defaultIP = getImage().getProcessor();
			if (globalLineWidth>0)
				defaultIP.setLineWidth(globalLineWidth);
			if (globalColor!=null)
				defaultIP.setColor(globalColor);
			else if (!Double.isNaN(globalValue))
				defaultIP.setValue(globalValue);
			else
				defaultIP.setColor(Toolbar.getForegroundColor());
		}
		return defaultIP;
	}

	int getType() {
		imageType = getImage().getType();
		return imageType;
	}

	void setPixel() {
		interp.getLeftParen();
		int a1 = (int)interp.getExpression();
		interp.getComma();
		double a2 = interp.getExpression();
		interp.getToken();
		ImageProcessor ip = getProcessor();
		if (interp.token==',') {
			double a3 = interp.getExpression();
			interp.getRightParen();
			if (ip instanceof FloatProcessor)
				ip.putPixelValue(a1, (int)a2, a3);
			else
				ip.putPixel(a1, (int)a2, (int)a3);
		} else {
			if (interp.token!=')') interp.error("')' expected");
			if (ip instanceof ColorProcessor)
				ip.set(a1, (int)a2);
			else
				ip.setf(a1, (float)a2);
		}
		updateNeeded = true;
	}

	double getPixel() {
		interp.getLeftParen();
		double a1 = interp.getExpression();
		ImageProcessor ip = getProcessor();
		double value = 0.0;
		interp.getToken();
		if (interp.token==',') {
			double a2 = interp.getExpression();
			interp.getRightParen();
			int ia1 = (int)a1;
			int ia2 = (int)a2;
			if (a1==ia1 && a2==ia2) {
				if (ip instanceof FloatProcessor)
					value = ip.getPixelValue(ia1, ia2);
				else
					value = ip.getPixel(ia1, ia2);
			} else {
				if (ip instanceof ColorProcessor)
					value = ip.getPixelInterpolated(a1, a2);
				else {
					ImagePlus imp = getImage();
					Calibration cal = imp.getCalibration();
					imp.setCalibration(null);
					ip = imp.getProcessor();
					value = ip.getInterpolatedValue(a1, a2);
					imp.setCalibration(cal);
				}
			}
		} else {
			if (interp.token!=')') interp.error("')' expected");
			if (ip instanceof ColorProcessor)
				value = ip.get((int)a1);
			else
				value = ip.getf((int)a1);
		}
		return value;
	}

	void setZCoordinate() {
		int z = (int)getArg();
		int n = z + 1;
		ImagePlus imp = getImage();
		ImageStack stack = imp.getStack();
		int size = stack.size();
		if (z<0 || z>=size)
			interp.error("Z coordinate ("+z+") is out of 0-"+(size-1)+ " range");
		this.defaultIP = stack.getProcessor(n);
	}

	void moveTo() {
		interp.getLeftParen();
		int a1 = (int)Math.round(interp.getExpression());
		interp.getComma();
		int a2 = (int)Math.round(interp.getExpression());
		interp.getRightParen();
		getProcessor().moveTo(a1, a2);
	}

	void lineTo() {
		interp.getLeftParen();
		int a1 = (int)Math.round(interp.getExpression());
		interp.getComma();
		int a2 = (int)Math.round(interp.getExpression());
		interp.getRightParen();
		ImageProcessor ip = getProcessor();
		ip.lineTo(a1, a2);
		updateAndDraw();
	}

	void drawLine() {
		interp.getLeftParen();
		int x1 = (int)Math.round(interp.getExpression());
		interp.getComma();
		int y1 = (int)Math.round(interp.getExpression());
		interp.getComma();
		int x2 = (int)Math.round(interp.getExpression());
		interp.getComma();
		int y2 = (int)Math.round(interp.getExpression());
		interp.getRightParen();
		ImageProcessor ip = getProcessor();
		ip.drawLine(x1, y1, x2, y2);
		updateAndDraw();
	}

	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 (roi==null) {
					ip.resetRoi();
					ip.fill();
				} else {
					ip.setRoi(roi);
					ip.fill(ip.getMask());
				}
				imp.updateAndDraw();
				break;
		}
	}

	void updateAndDraw() {
		if (autoUpdate) {
			ImagePlus imp = defaultImp;
			if (imp==null)
				imp = getImage();
			imp.updateChannelAndDraw();
			imp.changes = true;
		} 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);
		Color background = null;
		if (interp.nextToken()==',') {
			interp.getComma();
			background = getColor();
		}
		interp.getRightParen();
		ImageProcessor ip = getProcessor();
		setFont(ip);
		ip.setJustification(justification);
		ip.setAntialiasedText(antialiasedText);
		if (background!=null)
			ip.drawString(str, x, y, background);
		else
			ip.drawString(str, x, y);
		updateAndDraw();
	}

	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 (Double.isNaN(darg1) && Double.isNaN(darg2) && Double.isNaN(v))
					replace = true;
				if (replace) {
					if (isFloat)
						ip.putPixelValue(x, y, darg3);
					else
						ip.putPixel(x, y, (int)darg3);
				}
			}
		}
		if (mask!=null) ip.reset(mask);
		imp.updateAndDraw();
		updateNeeded = false;
	}

	void requires() {
		if (IJ.versionLessThan(getStringArg()))
			interp.done = true;
	}

	Random ran;
	double random() {
		double dseed = Double.NaN;
		boolean gaussian = false;
		if (interp.nextToken()=='(') {
			interp.getLeftParen();
			if (isStringArg()) {
				String arg = getString().toLowerCase(Locale.US);
				if (arg.equals("seed")) {
					interp.getComma();
					dseed = interp.getExpression();
					long seed = (long)dseed;
					if (seed!=dseed)
						interp.error("Seed not integer");
					ran = new Random(seed);
					ImageProcessor.setRandomSeed(seed);
				} else if (arg.equals("gaussian"))
					gaussian = true;
				else
					interp.error("'seed' or ''gaussian' expected");
			}
			interp.getRightParen();
			if (!Double.isNaN(dseed)) return Double.NaN;
		}
		ImageProcessor.setRandomSeed(Double.NaN);
		interp.getParens();
 		if (ran==null)
			ran = new Random();
		if (gaussian)
			return ran.nextGaussian();
		else
			return ran.nextDouble();
	}

	double getResult(ResultsTable rt) {
		interp.getLeftParen();
		String column = getString();
		int row = -1;
		if (interp.nextToken()==',') {
			interp.getComma();
			row = (int)interp.getExpression();
		}
		if (interp.nextToken()==',') {
			interp.getComma();
			String title = getString();
			rt = getResultsTable(title);
		}
		if (rt==null)
			rt = getResultsTable(true);
		interp.getRightParen();
		int counter = rt.size();
		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 {
			double value = rt.getValueAsDouble(col, row);
			if (Double.isNaN(value)) {
				String s = rt.getStringValue(col, row);
				if (s!=null && !s.equals("NaN"))
					value = Tools.parseDouble(s);
			}
			return value;
		}
	}

	String getResultString(ResultsTable rt) {
		interp.getLeftParen();
		String column = getString();
		int row = -1;
		if (interp.nextToken()==',') {
			interp.getComma();
			row = (int)interp.getExpression();
		}
		if (interp.nextToken()==',') {
			interp.getComma();
			String title = getString();
			rt = getResultsTable(title);
		}
		interp.getRightParen();
		if (rt==null)
			rt = getResultsTable(true);
		int counter = rt.size();
		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 rt.getStringValue(col, row);
		else {
			String label = null;
			if ("Label".equals(column))
				label = rt.getLabel(row);
			return label!=null?label:"null";
		}
	}

	String getResultLabel() {
		int row = (int)getArg();
		ResultsTable rt = getResultsTable(true);
		int counter = rt.size();
		if (row<0 || row>=counter)
			interp.error("Row ("+row+") out of range");
		String label = rt.getLabel(row);
		if (label!=null)
			return label;
		else {
			label = rt.getStringValue("Label", row);
			return label!=null?label:"";
		}
	}

	private ResultsTable getResultsTable(boolean reportErrors) {
		ResultsTable rt = Analyzer.getResultsTable();
		int size = rt.size();
		if (size==0) {
			Frame frame = WindowManager.getFrontWindow();
			if (frame==null || (frame instanceof Editor))
				frame = WindowManager.getFrame("Results");
			if (frame!=null && (frame instanceof TextWindow)) {
				TextPanel tp = ((TextWindow)frame).getTextPanel();
				rt = tp.getOrCreateResultsTable();
				size = rt!=null?rt.size():0;
			}
		}
		if (size==0) {
			Window win = WindowManager.getActiveTable();
			if (win!=null && (win instanceof TextWindow)) {
				TextPanel tp = ((TextWindow)win).getTextPanel();
				rt = tp.getOrCreateResultsTable();
				size = rt!=null?rt.size():0;
			}
		}
		if (size==0 && reportErrors)
			interp.error("No results found");
		return rt;
	}

	void setResult(ResultsTable rt) {
		interp.getLeftParen();
		String column = getString();
		interp.getComma();
		int row = (int)interp.getExpression();
		interp.getComma();
		double value = 0.0;
		String stringValue = null;
		boolean isLabel = column.equals("Label");
		if (isStringArg() || isLabel)
			stringValue = getString();
		else
			value = interp.getExpression();
		if (interp.nextToken()==',') {
			interp.getComma();
			String title = getString();
			rt = getResultsTable(title);
		}
		interp.getRightParen();
		if (rt==null) {
			rt = Analyzer.getResultsTable();
			resultsPending = true;
		} else
			unUpdatedTable = rt;
		if (row<0 || row>rt.size())
			interp.error("Row ("+row+") out of range");
		if (row==rt.size())
			rt.incrementCounter();
		try {
			if (stringValue!=null) {
				if (isLabel)
					rt.setLabel(stringValue, row);
				else
					rt.setValue(column, row, stringValue);
			} else
				rt.setValue(column, row, value);
		} catch (Exception e) {
			interp.error(""+e.getMessage());
		}
	}

	void updateResults() {
		interp.getParens();
		ResultsTable rt = Analyzer.getResultsTable();
		rt.show("Results");
		resultsPending = false;
	}

	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() {
		interp.getLeftParen();
		String prompt = getString();
		String yesButton = "  Yes  ";
		String noButton = "  No  ";
		if (interp.nextToken()==',') {
			yesButton = getNextString();
			noButton = getNextString();
		}
		interp.getRightParen();
		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, yesButton, noButton);
		if (d.cancelPressed()) {
			interp.done = true;
			return 0.0;
		} else if (d.yesPressed())
			return 1.0;
		else
			return 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();
		ImagePlus imp = getImage();
		Roi roi = imp.getRoi();
		if (roi==null)
			interp.error("Selection required");
		Variable[] xa, ya;
		if (roi.getType()==Roi.LINE) {
			xa = new Variable[2];
			ya = new Variable[2];
			Line line = (Line)roi;
			xa[0] = new Variable(line.x1d);
			ya[0] = new Variable(line.y1d);
			xa[1] = new Variable(line.x2d);
			ya[1] = new Variable(line.y2d);
		} else {
			FloatPolygon fp = roi.getFloatPolygon();
			if (fp!=null) {
				xa = new Variable[fp.npoints];
				ya = new Variable[fp.npoints];
				for (int i=0; i0 && s2!=null && (s2.equals(",")||s2.equals(";")))
			strings = s1.split(s2,-1);
		else if (s1.length()>0 && s2!=null && s2.length()>=3 && s2.startsWith("(")&&s2.endsWith(")")) {
			s2 = s2.substring(1,s2.length()-1);
			strings = s1.split(s2,-1);
		} else
			strings = (s2==null||s2.equals(""))?Tools.split(s1):Tools.split(s1, s2);
    	Variable[] array = new Variable[strings.length];
    	for (int i=0; i




© 2015 - 2024 Weber Informatics LLC | Privacy Policy