package ij;
import ij.gui.*;
import ij.process.*;
import ij.text.*;
import ij.io.*;
import ij.plugin.*;
import ij.plugin.filter.*;
import ij.util.Tools;
import ij.plugin.frame.Recorder;
import ij.plugin.frame.ThresholdAdjuster;
import ij.macro.Interpreter;
import ij.macro.MacroRunner;
import ij.measure.Calibration;
import ij.measure.ResultsTable;
import ij.measure.Measurements;
import java.awt.event.*;
import java.text.*;
import java.util.*;
import java.awt.*;
import java.applet.Applet;
import java.io.*;
import java.lang.reflect.*;
import java.net.*;
import javax.net.ssl.*;
import java.security.cert.*;
import java.security.KeyStore;
import java.nio.ByteBuffer;
import java.math.RoundingMode;
public class IJ {
public static Font font10 = new Font("SansSerif", Font.PLAIN, 10);
public static Font font12 = ImageJ.SansSerif12;
public static Font font14 = ImageJ.SansSerif14;
public static final int COMPOSITE=1, COLOR=2, GRAYSCALE=3;
public static final String URL = "http://imagej.nih.gov/ij";
public static final int ALL_KEYS = -1;
public static boolean debugMode;
public static boolean hideProcessStackDialog;
public static final char micronSymbol = '\u00B5';
public static final char angstromSymbol = '\u00C5';
public static final char degreeSymbol = '\u00B0';
private static ImageJ ij;
private static java.applet.Applet applet;
private static ProgressBar progressBar;
private static TextPanel textPanel;
private static String osname, osarch;
private static boolean isMac, isWin, isLinux, is64Bit;
private static int javaVersion;
private static boolean controlDown, altDown, spaceDown, shiftDown;
private static boolean macroRunning;
private static Thread previousThread;
private static TextPanel logPanel;
private static ClassLoader classLoader;
private static boolean memMessageDisplayed;
private static long maxMemory;
private static boolean escapePressed;
private static boolean redirectErrorMessages;
private static boolean suppressPluginNotFoundError;
private static Hashtable commandTable;
private static Vector eventListeners = new Vector();
private static String lastErrorMessage;
private static Properties properties; private static DecimalFormat[] df;
private static DecimalFormat[] sf;
private static DecimalFormatSymbols dfs;
private static boolean trustManagerCreated;
private static String smoothMacro;
private static Interpreter macroInterpreter;
private static boolean protectStatusBar;
private static Thread statusBarThread;
static {
osname = System.getProperty("os.name");
isWin = osname.startsWith("Windows");
isMac = !isWin && osname.startsWith("Mac");
isLinux = osname.startsWith("Linux");
String version = System.getProperty("java.version");
if (version==null || version.length()<2)
version = "1.8";
if (version.startsWith("1.8"))
javaVersion = 8;
else if (version.charAt(0)=='1' && Character.isDigit(version.charAt(1)))
javaVersion = 10 + (version.charAt(1) - '0');
else if (version.charAt(0)=='2' && Character.isDigit(version.charAt(1)))
javaVersion = 20 + (version.charAt(1) - '0');
else if (version.startsWith("1.6"))
javaVersion = 6;
else if (version.startsWith("1.9")||version.startsWith("9"))
javaVersion = 9;
else if (version.startsWith("1.7"))
javaVersion = 7;
else
javaVersion = 8;
dfs = new DecimalFormatSymbols(Locale.US);
df = new DecimalFormat[10];
df[0] = new DecimalFormat("0", dfs);
df[1] = new DecimalFormat("0.0", dfs);
df[2] = new DecimalFormat("0.00", dfs);
df[3] = new DecimalFormat("0.000", dfs);
df[4] = new DecimalFormat("0.0000", dfs);
df[5] = new DecimalFormat("0.00000", dfs);
df[6] = new DecimalFormat("0.000000", dfs);
df[7] = new DecimalFormat("0.0000000", dfs);
df[8] = new DecimalFormat("0.00000000", dfs);
df[9] = new DecimalFormat("0.000000000", dfs);
df[0].setRoundingMode(RoundingMode.HALF_UP);
}
static void init(ImageJ imagej, Applet theApplet) {
ij = imagej;
applet = theApplet;
progressBar = ij.getProgressBar();
}
static void cleanup() {
ij=null; applet=null; progressBar=null; textPanel=null;
}
public static ImageJ getInstance() {
return ij;
}
public static void setDebugMode(boolean b) {
debugMode = b;
LogStream.redirectSystem(debugMode);
}
public static String runMacro(String macro) {
return runMacro(macro, "");
}
public static String runMacro(String macro, String arg) {
Macro_Runner mr = new Macro_Runner();
return mr.runMacro(macro, arg);
}
public static String runMacroFile(String name, String arg) {
Macro_Runner mr = new Macro_Runner();
return mr.runMacroFile(name, arg);
}
public static String runMacroFile(String name) {
return runMacroFile(name, null);
}
public static Object runPlugIn(ImagePlus imp, String className, String arg) {
if (imp!=null) {
ImagePlus temp = WindowManager.getTempCurrentImage();
WindowManager.setTempCurrentImage(imp);
Object o = runPlugIn("", className, arg);
WindowManager.setTempCurrentImage(temp);
return o;
} else
return runPlugIn(className, arg);
}
public static Object runPlugIn(String className, String arg) {
return runPlugIn("", className, arg);
}
public static Object runPlugIn(String commandName, String className, String arg) {
if (arg==null) arg = "";
if (IJ.debugMode)
IJ.log("runPlugIn: "+className+argument(arg));
if (!className.startsWith("ij.") && applet==null)
return runUserPlugIn(commandName, className, arg, false);
Object thePlugIn=null;
try {
Class c = Class.forName(className);
thePlugIn = c.newInstance();
if (thePlugIn instanceof PlugIn)
((PlugIn)thePlugIn).run(arg);
else
new PlugInFilterRunner(thePlugIn, commandName, arg);
} catch (ClassNotFoundException e) {
if (!(className!=null && className.startsWith("ij.plugin.MacAdapter"))) {
log("Plugin or class not found: \"" + className + "\"\n(" + e+")");
String path = Prefs.getCustomPropsPath();
if (path!=null);
log("Error may be due to custom properties at " + path);
}
}
catch (InstantiationException e) {log("Unable to load plugin (ins)");}
catch (IllegalAccessException e) {log("Unable to load plugin, possibly \nbecause it is not public.");}
redirectErrorMessages = false;
return thePlugIn;
}
static Object runUserPlugIn(String commandName, String className, String arg, boolean createNewLoader) {
if (IJ.debugMode)
IJ.log("runUserPlugIn: "+className+", arg="+argument(arg));
if (applet!=null) return null;
if (createNewLoader)
classLoader = null;
ClassLoader loader = getClassLoader();
Object thePlugIn = null;
try {
thePlugIn = (loader.loadClass(className)).newInstance();
if (thePlugIn instanceof PlugIn)
((PlugIn)thePlugIn).run(arg);
else if (thePlugIn instanceof PlugInFilter)
new PlugInFilterRunner(thePlugIn, commandName, arg);
}
catch (ClassNotFoundException e) {
if (className.startsWith("macro:"))
runMacro(className.substring(6));
else if (className.contains("_") && !suppressPluginNotFoundError)
error("Plugin or class not found: \"" + className + "\"\n(" + e+")");
}
catch (NoClassDefFoundError e) {
int dotIndex = className.indexOf('.');
if (dotIndex>=0 && className.contains("_")) {
if (debugMode) IJ.log("runUserPlugIn: rerunning "+className);
return runUserPlugIn(commandName, className.substring(dotIndex+1), arg, createNewLoader);
}
if (className.contains("_") && !suppressPluginNotFoundError)
error("Run User Plugin", "Class not found while attempting to run \"" + className + "\"\n \n " + e);
}
catch (InstantiationException e) {error("Unable to load plugin (ins)");}
catch (IllegalAccessException e) {error("Unable to load plugin, possibly \nbecause it is not public.");}
if (thePlugIn!=null && !"HandleExtraFileTypes".equals(className))
redirectErrorMessages = false;
suppressPluginNotFoundError = false;
return thePlugIn;
}
private static String argument(String arg) {
return arg!=null && !arg.equals("") && !arg.contains("\n")?"(\""+arg+"\")":"";
}
static void wrongType(int capabilities, String cmd) {
String s = "\""+cmd+"\" requires an image of type:\n \n";
if ((capabilities&PlugInFilter.DOES_8G)!=0) s += " 8-bit grayscale\n";
if ((capabilities&PlugInFilter.DOES_8C)!=0) s += " 8-bit color\n";
if ((capabilities&PlugInFilter.DOES_16)!=0) s += " 16-bit grayscale\n";
if ((capabilities&PlugInFilter.DOES_32)!=0) s += " 32-bit (float) grayscale\n";
if ((capabilities&PlugInFilter.DOES_RGB)!=0) s += " RGB color\n";
error(s);
}
public static void doCommand(String command) {
new Executer(command, null);
}
public static void doCommand(ImagePlus imp, String command) {
new Executer(command, imp);
}
public static void run(String command) {
run(command, null);
}
public static void run(String command, String options) {
if (ij==null && Menus.getCommands()==null)
init();
Macro.abort = false;
Macro.setOptions(options);
Thread thread = Thread.currentThread();
if (previousThread==null || thread!=previousThread) {
String name = thread.getName();
if (!name.startsWith("Run$_"))
thread.setName("Run$_"+name);
}
command = convert(command);
previousThread = thread;
macroRunning = true;
Executer e = new Executer(command);
e.run();
macroRunning = false;
Macro.setOptions(null);
testAbort();
macroInterpreter = null;
}
public static void run(Interpreter interpreter, String command, String options) {
macroInterpreter = interpreter;
run(command, options);
macroInterpreter = null;
}
private static String convert(String command) {
if (commandTable==null) {
commandTable = new Hashtable(30);
commandTable.put("New...", "Image...");
commandTable.put("Threshold", "Make Binary");
commandTable.put("Display...", "Appearance...");
commandTable.put("Start Animation", "Start Animation [\\]");
commandTable.put("Convert Images to Stack", "Images to Stack");
commandTable.put("Convert Stack to Images", "Stack to Images");
commandTable.put("Convert Stack to RGB", "Stack to RGB");
commandTable.put("Convert to Composite", "Make Composite");
commandTable.put("RGB Split", "Split Channels");
commandTable.put("RGB Merge...", "Merge Channels...");
commandTable.put("Channels...", "Channels Tool...");
commandTable.put("New... ", "Table...");
commandTable.put("Arbitrarily...", "Rotate... ");
commandTable.put("Measurements...", "Results... ");
commandTable.put("List Commands...", "Find Commands...");
commandTable.put("Capture Screen ", "Capture Screen");
commandTable.put("Add to Manager ", "Add to Manager");
commandTable.put("In", "In [+]");
commandTable.put("Out", "Out [-]");
commandTable.put("Enhance Contrast", "Enhance Contrast...");
commandTable.put("XY Coodinates... ", "XY Coordinates... ");
commandTable.put("Statistics...", "Statistics");
commandTable.put("Channels Tool... ", "Channels Tool...");
commandTable.put("Profile Plot Options...", "Plots...");
commandTable.put("AuPbSn 40 (56K)", "AuPbSn 40");
commandTable.put("Bat Cochlea Volume (19K)", "Bat Cochlea Volume");
commandTable.put("Bat Cochlea Renderings (449K)", "Bat Cochlea Renderings");
commandTable.put("Blobs (25K)", "Blobs");
commandTable.put("Boats (356K)", "Boats");
commandTable.put("Cardio (768K, RGB DICOM)", "Cardio (RGB DICOM)");
commandTable.put("Cell Colony (31K)", "Cell Colony");
commandTable.put("Clown (14K)", "Clown");
commandTable.put("Confocal Series (2.2MB)", "Confocal Series");
commandTable.put("CT (420K, 16-bit DICOM)", "CT (16-bit DICOM)");
commandTable.put("Dot Blot (7K)", "Dot Blot");
commandTable.put("Embryos (42K)", "Embryos");
commandTable.put("Fluorescent Cells (400K)", "Fluorescent Cells");
commandTable.put("Fly Brain (1MB)", "Fly Brain");
commandTable.put("Gel (105K)", "Gel");
commandTable.put("HeLa Cells (1.3M, 48-bit RGB)", "HeLa Cells (48-bit RGB)");
commandTable.put("Leaf (36K)", "Leaf");
commandTable.put("Line Graph (21K)", "Line Graph");
commandTable.put("Mitosis (26MB, 5D stack)", "Mitosis (5D stack)");
commandTable.put("MRI Stack (528K)", "MRI Stack");
commandTable.put("M51 Galaxy (177K, 16-bits)", "M51 Galaxy (16-bits)");
commandTable.put("Neuron (1.6M, 5 channels)", "Neuron (5 channels)");
commandTable.put("Nile Bend (1.9M)", "Nile Bend");
commandTable.put("Organ of Corti (2.8M, 4D stack)", "Organ of Corti (4D stack)");
commandTable.put("Particles (75K)", "Particles");
commandTable.put("T1 Head (2.4M, 16-bits)", "T1 Head (16-bits)");
commandTable.put("T1 Head Renderings (736K)", "T1 Head Renderings");
commandTable.put("TEM Filter (112K)", "TEM Filter");
commandTable.put("Tree Rings (48K)", "Tree Rings");
}
String command2 = (String)commandTable.get(command);
if (command2!=null)
return command2;
else
return command;
}
public static void run(ImagePlus imp, String command, String options) {
if (ij==null && Menus.getCommands()==null)
init();
if (imp!=null) {
ImagePlus temp = WindowManager.getTempCurrentImage();
WindowManager.setTempCurrentImage(imp);
run(command, options);
WindowManager.setTempCurrentImage(temp);
} else
run(command, options);
}
static void init() {
Menus m = new Menus(null, null);
Prefs.load(m, null);
m.addMenuBar();
}
private static void testAbort() {
if (Macro.abort)
abort();
}
public static boolean macroRunning() {
return macroRunning;
}
public static boolean isMacro() {
return macroRunning || Interpreter.getInstance()!=null;
}
public static java.applet.Applet getApplet() {
return applet;
}
public static void showStatus(String s) {
if ((Interpreter.getInstance()==null&&statusBarThread==null)
|| (statusBarThread!=null&&Thread.currentThread()!=statusBarThread))
protectStatusBar(false);
boolean doProtect = s.startsWith("!"); if (doProtect) {
protectStatusBar(true);
statusBarThread = Thread.currentThread();
s = s.substring(1);
}
if (doProtect || !protectStatusBar) {
if (ij!=null)
ij.showStatus(s);
ImagePlus imp = WindowManager.getCurrentImage();
ImageCanvas ic = imp!=null?imp.getCanvas():null;
if (ic!=null)
ic.setShowCursorStatus(s.length()==0?true:false);
}
}
public static void showStatus(String message, String options) {
showStatus(message);
if (options==null)
return;
options = options.replace("flash", "");
options = options.replace("ms", "");
Color optionalColor = null;
int index1 = options.indexOf("#");
if (index1>=0) { int index2 = options.indexOf(" ", index1);
if (index2==-1) index2 = options.length();
String hexColor = options.substring(index1, index2);
optionalColor = Colors.decode(hexColor, null);
options = options.replace(hexColor, "");
}
if (optionalColor==null) { for (String c : Colors.colors) {
if (options.contains(c)) {
optionalColor = Colors.getColor(c, ImageJ.backgroundColor);
options = options.replace(c, "");
break;
}
}
}
boolean flashImage = options.contains("image");
Color defaultColor = new Color(255,255,245);
int defaultDelay = 500;
ImagePlus imp = WindowManager.getCurrentImage();
if (flashImage) {
options = options.replace("image", "");
if (imp!=null && imp.getWindow()!=null) {
defaultColor = Color.black;
defaultDelay = 100;
}
else
flashImage = false;
}
Color color = optionalColor!=null?optionalColor:defaultColor;
int delay = (int)Tools.parseDouble(options, defaultDelay);
if (delay>8000)
delay = 8000;
String colorString = null;
ImageJ ij = IJ.getInstance();
if (flashImage) {
Color previousColor = imp.getWindow().getBackground();
imp.getWindow().setBackground(color);
if (delay>0) {
wait(delay);
imp.getWindow().setBackground(previousColor);
}
} else if (ij!=null) {
ij.getStatusBar().setBackground(color);
wait(delay);
ij.getStatusBar().setBackground(ij.backgroundColor);
}
}
public static void write(String s) {
if (textPanel==null && ij!=null)
showResults();
if (textPanel!=null)
textPanel.append(s);
else
System.out.println(s);
}
private static void showResults() {
TextWindow resultsWindow = new TextWindow("Results", "", 400, 250);
textPanel = resultsWindow.getTextPanel();
textPanel.setResultsTable(Analyzer.getResultsTable());
}
public static synchronized void log(String s) {
if (s==null) return;
if (logPanel==null && ij!=null) {
TextWindow logWindow = new TextWindow("Log", "", 400, 250);
logPanel = logWindow.getTextPanel();
logPanel.setFont(new Font("SansSerif", Font.PLAIN, 16));
}
if (logPanel!=null) {
if (s.startsWith("\\"))
handleLogCommand(s);
else {
if (s.endsWith("\n")) {
if (s.equals("\n\n"))
s= "\n \n ";
else if (s.endsWith("\n\n"))
s = s.substring(0, s.length()-2)+"\n \n ";
else
s = s+" ";
}
logPanel.append(s);
}
} else {
LogStream.redirectSystem(false);
System.out.println(s);
}
}
static void handleLogCommand(String s) {
if (s.equals("\\Closed"))
logPanel = null;
else if (s.startsWith("\\Update:")) {
int n = logPanel.getLineCount();
String s2 = s.substring(8, s.length());
if (n==0)
logPanel.append(s2);
else
logPanel.setLine(n-1, s2);
} else if (s.startsWith("\\Update")) {
int cindex = s.indexOf(":");
if (cindex==-1)
{logPanel.append(s); return;}
String nstr = s.substring(7, cindex);
int line = (int)Tools.parseDouble(nstr, -1);
if (line<0 || line>25)
{logPanel.append(s); return;}
int count = logPanel.getLineCount();
while (line>=count) {
log("");
count++;
}
String s2 = s.substring(cindex+1, s.length());
logPanel.setLine(line, s2);
} else if (s.equals("\\Clear")) {
logPanel.clear();
} else if (s.startsWith("\\Heading:")) {
logPanel.updateColumnHeadings(s.substring(10));
} else if (s.equals("\\Close")) {
Frame f = WindowManager.getFrame("Log");
if (f!=null && (f instanceof TextWindow))
((TextWindow)f).close();
} else
logPanel.append(s);
}
public static synchronized String getLog() {
if (logPanel==null || ij==null)
return null;
else
return logPanel.getText();
}
public static void setColumnHeadings(String headings) {
if (textPanel==null && ij!=null)
showResults();
if (textPanel!=null)
textPanel.setColumnHeadings(headings);
else
System.out.println(headings);
}
public static boolean isResultsWindow() {
return textPanel!=null;
}
public static void renameResults(String title) {
Frame frame = WindowManager.getFrontWindow();
if (frame!=null && (frame instanceof TextWindow)) {
TextWindow tw = (TextWindow)frame;
if (tw.getResultsTable()==null) {
IJ.error("Rename", "\""+tw.getTitle()+"\" is not a results table");
return;
}
tw.rename(title);
} else if (isResultsWindow()) {
TextPanel tp = getTextPanel();
TextWindow tw = (TextWindow)tp.getParent();
tw.rename(title);
}
}
public static void renameResults(String oldTitle, String newTitle) {
Frame frame = WindowManager.getFrame(oldTitle);
if (frame==null) {
error("Rename", "\""+oldTitle+"\" not found");
return;
} else if (frame instanceof TextWindow) {
TextWindow tw = (TextWindow)frame;
if (tw.getResultsTable()==null) {
error("Rename", "\""+oldTitle+"\" is not a table");
return;
}
tw.rename(newTitle);
} else
error("Rename", "\""+oldTitle+"\" is not a table");
}
public static void deleteRows(int row1, int row2) {
ResultsTable rt = Analyzer.getResultsTable();
int tableSize = rt.size();
rt.deleteRows(row1, row2);
ImagePlus imp = WindowManager.getCurrentImage();
if (imp!=null)
Overlay.updateTableOverlay(imp, row1, row2, tableSize);
rt.show("Results");
}
public static double getValue(ImagePlus imp, String measurement) {
String options = "";
int index = measurement.indexOf(" ");
if (index>0) {
if (index<measurement.length()-1)
options = measurement.substring(index+1, measurement.length());
measurement = measurement.substring(0, index);
}
int measurements = Measurements.ALL_STATS + Measurements.SLICE;
if (options.contains("limit"))
measurements += Measurements.LIMIT;
Calibration cal = null;
if (options.contains("raw")) {
cal = imp.getCalibration();
imp.setCalibration(null);
}
ResultsTable rt = new ResultsTable();
Analyzer analyzer = new Analyzer(imp, measurements, rt);
analyzer.measure();
double value = Double.NaN;
try {
value = rt.getValue(measurement, 0);
} catch (Exception e) {};
if (cal!=null)
imp.setCalibration(cal);
return value;
}
public static TextPanel getTextPanel() {
if (textPanel==null && ij!=null)
showResults();
return textPanel;
}
public static void setTextPanel(TextPanel tp) {
textPanel = tp;
}
public static void noImage() {
String msg = "There are no images open";
if (macroInterpreter!=null) {
macroInterpreter.abort(msg);
macroInterpreter = null;
} else
error("No Image", msg);
}
public static void outOfMemory(String name) {
Undo.reset();
System.gc();
lastErrorMessage = "out of memory";
String tot = Runtime.getRuntime().maxMemory()/1048576L+"MB";
if (!memMessageDisplayed)
log(">>>>>>>>>>>>>>>>>>>>>>>>>>>");
log("<Out of memory>");
if (!memMessageDisplayed) {
log("<All available memory ("+tot+") has been>");
log("<used. To make more available, use the>");
log("<Edit>Options>Memory & Threads command.>");
log(">>>>>>>>>>>>>>>>>>>>>>>>>>>");
memMessageDisplayed = true;
}
Macro.abort();
}
public static void showProgress(double progress) {
if (progressBar!=null) progressBar.show(progress, false);
}
public static void showProgress(int currentIndex, int finalIndex) {
if (progressBar!=null) {
progressBar.show(currentIndex, finalIndex);
if (currentIndex==finalIndex)
progressBar.setBatchMode(false);
}
}
public static void showMessage(String msg) {
showMessage("Message", msg);
}
public static void showMessage(String title, String msg) {
if (ij!=null) {
if (msg!=null && (msg.startsWith("<html>")||msg.startsWith("<HTML>"))) {
HTMLDialog hd = new HTMLDialog(title, msg);
if (isMacro() && hd.escapePressed())
throw new RuntimeException(Macro.MACRO_CANCELED);
} else {
MessageDialog md = new MessageDialog(ij, title, msg);
if (isMacro() && md.escapePressed())
throw new RuntimeException(Macro.MACRO_CANCELED);
}
} else
System.out.println(msg);
}
public static void error(String msg) {
error(null, msg);
if (Thread.currentThread().getName().endsWith("JavaScript"))
throw new RuntimeException(Macro.MACRO_CANCELED);
else
Macro.abort();
}
public static void error(String title, String msg) {
if (macroInterpreter!=null) {
macroInterpreter.abort(msg);
macroInterpreter = null;
return;
}
if (msg!=null && msg.endsWith(Macro.MACRO_CANCELED))
return;
String title2 = title!=null?title:"ImageJ";
boolean abortMacro = title!=null;
lastErrorMessage = msg;
if (redirectErrorMessages) {
IJ.log(title2 + ": " + msg);
if (abortMacro && (title.contains("Open")||title.contains("Reader")))
abortMacro = false;
} else
showMessage(title2, msg);
redirectErrorMessages = false;
if (abortMacro)
Macro.abort();
}
public static void exit() {
if (Thread.currentThread().getName().endsWith("JavaScript"))
throw new RuntimeException(Macro.MACRO_CANCELED);
}
public static String getErrorMessage() {
String msg = lastErrorMessage;
lastErrorMessage = null;
return msg;
}
public static boolean showMessageWithCancel(String title, String msg) {
GenericDialog gd = new GenericDialog(title);
gd.addMessage(msg);
gd.showDialog();
return !gd.wasCanceled();
}
public static final int CANCELED = Integer.MIN_VALUE;
public static double getNumber(String prompt, double defaultValue) {
GenericDialog gd = new GenericDialog("");
int decimalPlaces = (int)defaultValue==defaultValue?0:2;
gd.addNumericField(prompt, defaultValue, decimalPlaces);
gd.showDialog();
if (gd.wasCanceled())
return CANCELED;
double v = gd.getNextNumber();
if (gd.invalidNumber())
return defaultValue;
else
return v;
}
public static String getString(String prompt, String defaultString) {
GenericDialog gd = new GenericDialog("");
gd.addStringField(prompt, defaultString, 20);
gd.showDialog();
if (gd.wasCanceled())
return "";
return gd.getNextString();
}
public static void wait(int msecs) {
try {Thread.sleep(msecs);}
catch (InterruptedException e) { }
}
public static void beep() {
java.awt.Toolkit.getDefaultToolkit().beep();
}
public static String freeMemory() {
long inUse = currentMemory();
String inUseStr = inUse<10000*1024?inUse/1024L+"K":inUse/1048576L+"MB";
String maxStr="";
long max = maxMemory();
if (max>0L) {
double percent = inUse*100/max;
maxStr = " of "+max/1048576L+"MB ("+(percent<1.0?"<1":d2s(percent,0)) + "%)";
}
return inUseStr + maxStr;
}
public static long currentMemory() {
long freeMem = Runtime.getRuntime().freeMemory();
long totMem = Runtime.getRuntime().totalMemory();
return totMem-freeMem;
}
public static long maxMemory() {
if (maxMemory==0L) {
Memory mem = new Memory();
maxMemory = mem.getMemorySetting();
if (maxMemory==0L) maxMemory = mem.maxMemory();
}
return maxMemory;
}
public static void showTime(ImagePlus imp, long start, String str) {
showTime(imp, start, str, 1);
}
public static void showTime(ImagePlus imp, long start, String str, int nslices) {
if (Interpreter.isBatchMode())
return;
double seconds = (System.currentTimeMillis()-start)/1000.0;
if (seconds<=0.5 && macroRunning())
return;
double pixels = (double)imp.getWidth() * imp.getHeight();
double rate = pixels*nslices/seconds;
String str2;
if (rate>1000000000.0)
str2 = "";
else if (rate<1000000.0)
str2 = ", "+d2s(rate,0)+" pixels/second";
else
str2 = ", "+d2s(rate/1000000.0,1)+" million pixels/second";
showStatus(str+seconds+" seconds"+str2);
}
public static String time(ImagePlus imp, long startNanoTime) {
double planes = imp.getStackSize();
double seconds = (System.nanoTime()-startNanoTime)/1000000000.0;
double mpixels = imp.getWidth()*imp.getHeight()*planes/1000000.0;
String time = seconds<1.0?d2s(seconds*1000.0,0)+" ms":d2s(seconds,1)+" seconds";
return time+", "+d2s(mpixels/seconds,1)+" million pixels/second";
}
public static String d2s(double n) {
return d2s(n, 2);
}
public static String d2s(double n, int decimalPlaces) {
if (Double.isNaN(n)||Double.isInfinite(n))
return ""+n;
if (n==Float.MAX_VALUE) return "3.4e38";
double np = n;
if (n<0.0) np = -n;
if (decimalPlaces<0) synchronized(IJ.class) {
decimalPlaces = -decimalPlaces;
if (decimalPlaces>9) decimalPlaces=9;
if (sf==null) {
if (dfs==null)
dfs = new DecimalFormatSymbols(Locale.US);
sf = new DecimalFormat[10];
sf[1] = new DecimalFormat("0.0E0",dfs);
sf[2] = new DecimalFormat("0.00E0",dfs);
sf[3] = new DecimalFormat("0.000E0",dfs);
sf[4] = new DecimalFormat("0.0000E0",dfs);
sf[5] = new DecimalFormat("0.00000E0",dfs);
sf[6] = new DecimalFormat("0.000000E0",dfs);
sf[7] = new DecimalFormat("0.0000000E0",dfs);
sf[8] = new DecimalFormat("0.00000000E0",dfs);
sf[9] = new DecimalFormat("0.000000000E0",dfs);
}
return sf[decimalPlaces].format(n); }
if (decimalPlaces<0) decimalPlaces = 0;
if (decimalPlaces>9) decimalPlaces = 9;
return df[decimalPlaces].format(n);
}
public static String d2s(double x, int significantDigits, int maxDigits) {
double log10 = Math.log10(Math.abs(x));
double roundErrorAtMax = 0.223*Math.pow(10, -maxDigits);
int magnitude = (int)Math.ceil(log10+roundErrorAtMax);
int decimals = x==0 ? 0 : maxDigits - magnitude;
if (decimals<0 || magnitude<significantDigits+1-maxDigits)
return IJ.d2s(x, -significantDigits); else {
if (decimals>significantDigits)
decimals = Math.max(significantDigits, decimals-maxDigits+significantDigits);
return IJ.d2s(x, decimals);
}
}
public static String pad(int n, int digits) {
String str = ""+n;
while (str.length()<digits)
str = "0"+str;
return str;
}
public static String pad(String s, int digits) {
String str = ""+s;
while (str.length()<digits)
str = "0"+str;
return str;
}
public static void register(Class c) {
if (ij!=null) ij.register(c);
}
public static boolean spaceBarDown() {
return spaceDown;
}
public static boolean controlKeyDown() {
return controlDown;
}
public static boolean altKeyDown() {
return altDown;
}
public static boolean shiftKeyDown() {
return shiftDown;
}
public static void setKeyDown(int key) {
switch (key) {
case KeyEvent.VK_CONTROL:
controlDown=true;
break;
case KeyEvent.VK_META:
if (isMacintosh()) controlDown=true;
break;
case KeyEvent.VK_ALT:
altDown=true;
updateStatus();
break;
case KeyEvent.VK_SHIFT:
shiftDown=true;
if (debugMode) beep();
break;
case KeyEvent.VK_SPACE: {
spaceDown=true;
ImageWindow win = WindowManager.getCurrentWindow();
break;
}
case KeyEvent.VK_ESCAPE: {
escapePressed = true;
break;
}
}
}
public static void setKeyUp(int key) {
switch (key) {
case KeyEvent.VK_CONTROL: controlDown=false; break;
case KeyEvent.VK_META: if (isMacintosh()) controlDown=false; break;
case KeyEvent.VK_ALT: altDown=false; updateStatus(); break;
case KeyEvent.VK_SHIFT: shiftDown=false; if (debugMode) beep(); break;
case KeyEvent.VK_SPACE:
spaceDown=false;
ImageWindow win = WindowManager.getCurrentWindow();
break;
case ALL_KEYS:
shiftDown=controlDown=altDown=spaceDown=false;
break;
}
}
private static void updateStatus() {
ImagePlus imp = WindowManager.getCurrentImage();
if (imp!=null) {
Roi roi = imp.getRoi();
if (roi!=null && imp.getCalibration().scaled()) {
roi.showStatus();
}
}
}
public static void setInputEvent(InputEvent e) {
altDown = e.isAltDown();
shiftDown = e.isShiftDown();
}
public static boolean isMacintosh() {
return isMac;
}
public static boolean isMacOSX() {
return isMacintosh();
}
public static boolean isWindows() {
return isWin;
}
public static int javaVersion() {
return javaVersion;
}
public static boolean isJava2() {
return true;
}
public static boolean isJava14() {
return true;
}
public static boolean isJava15() {
return true;
}
public static boolean isJava16() {
return javaVersion >= 6;
}
public static boolean isJava17() {
return javaVersion >= 7;
}
public static boolean isJava18() {
return javaVersion >= 8;
}
public static boolean isJava19() {
return javaVersion >= 9;
}
public static boolean isLinux() {
return isLinux;
}
public static boolean isVista() {
return false;
}
public static boolean is64Bit() {
if (osarch==null)
osarch = System.getProperty("os.arch");
return osarch!=null && osarch.indexOf("64")!=-1;
}
public static boolean versionLessThan(String version) {
boolean lessThan = ImageJ.VERSION.compareTo(version)<0;
if (lessThan)
error("This plugin or macro requires ImageJ "+version+" or later. Use\nHelp>Update ImageJ to upgrade to the latest version.");
return lessThan;
}
public static int setupDialog(ImagePlus imp, int flags) {
if (imp==null || (ij!=null&&ij.hotkey)) {
if (ij!=null) ij.hotkey=false;
return flags;
}
int stackSize = imp.getStackSize();
if (stackSize>1) {
String macroOptions = Macro.getOptions();
if (imp.isComposite() && ((CompositeImage)imp).getMode()==IJ.COMPOSITE) {
if (macroOptions==null || !macroOptions.contains("slice"))
return flags | PlugInFilter.DOES_STACKS;
}
if (macroOptions!=null) {
if (macroOptions.indexOf("stack ")>=0)
return flags | PlugInFilter.DOES_STACKS;
else
return flags;
}
if (hideProcessStackDialog)
return flags;
String note = ((flags&PlugInFilter.NO_CHANGES)==0)?" There is\nno Undo if you select \"Yes\".":"";
YesNoCancelDialog d = new YesNoCancelDialog(getInstance(),
"Process Stack?", "Process all "+stackSize+" images?"+note);
if (d.cancelPressed())
return PlugInFilter.DONE;
else if (d.yesPressed()) {
if (imp.getStack().isVirtual() && ((flags&PlugInFilter.NO_CHANGES)==0)) {
int size = (stackSize*imp.getWidth()*imp.getHeight()*imp.getBytesPerPixel()+524288)/1048576;
String msg =
"Use the Process>Batch>Virtual Stack command\n"+
"to process a virtual stack or convert it into a\n"+
"normal stack using Image>Duplicate, which\n"+
"will require "+size+"MB of additional memory.";
error(msg);
return PlugInFilter.DONE;
}
if (Recorder.record)
Recorder.recordOption("stack");
return flags | PlugInFilter.DOES_STACKS;
}
if (Recorder.record)
Recorder.recordOption("slice");
}
return flags;
}
public static void makeRectangle(int x, int y, int width, int height) {
if (width<=0 || height<0)
getImage().deleteRoi();
else {
ImagePlus img = getImage();
if (Interpreter.isBatchMode())
img.setRoi(new Roi(x,y,width,height), false);
else
img.setRoi(x, y, width, height);
}
}
public static void makeRectangle(double x, double y, double width, double height) {
if (width<=0 || height<0)
getImage().deleteRoi();
else
getImage().setRoi(new Roi(x,y,width,height), !Interpreter.isBatchMode());
}
public static void makeOval(int x, int y, int width, int height) {
if (width<=0 || height<0)
getImage().deleteRoi();
else {
ImagePlus img = getImage();
img.setRoi(new OvalRoi(x, y, width, height));
}
}
public static void makeOval(double x, double y, double width, double height) {
if (width<=0 || height<0)
getImage().deleteRoi();
else
getImage().setRoi(new OvalRoi(x, y, width, height));
}
public static void makeLine(int x1, int y1, int x2, int y2) {
getImage().setRoi(new Line(x1, y1, x2, y2));
}
public static void makeLine(double x1, double y1, double x2, double y2) {
getImage().setRoi(new Line(x1, y1, x2, y2));
}
public static void makePoint(int x, int y) {
ImagePlus img = getImage();
Roi roi = img.getRoi();
if (shiftKeyDown() && roi!=null && roi.getType()==Roi.POINT) {
Polygon p = roi.getPolygon();
p.addPoint(x, y);
img.setRoi(new PointRoi(p.xpoints, p.ypoints, p.npoints));
IJ.setKeyUp(KeyEvent.VK_SHIFT);
} else if (altKeyDown() && roi!=null && roi.getType()==Roi.POINT) {
((PolygonRoi)roi).deleteHandle(x, y);
IJ.setKeyUp(KeyEvent.VK_ALT);
} else
img.setRoi(new PointRoi(x, y));
}
public static void makePoint(double x, double y) {
ImagePlus img = getImage();
Roi roi = img.getRoi();
if (shiftKeyDown() && roi!=null && roi.getType()==Roi.POINT) {
Polygon p = roi.getPolygon();
p.addPoint((int)Math.round(x), (int)Math.round(y));
img.setRoi(new PointRoi(p.xpoints, p.ypoints, p.npoints));
IJ.setKeyUp(KeyEvent.VK_SHIFT);
} else if (altKeyDown() && roi!=null && roi.getType()==Roi.POINT) {
((PolygonRoi)roi).deleteHandle(x, y);
IJ.setKeyUp(KeyEvent.VK_ALT);
} else
img.setRoi(new PointRoi(x, y));
}
public static Roi Roi(double x, double y, double width, double height) {
return new Roi(x, y, width, height);
}
public static OvalRoi OvalRoi(double x, double y, double width, double height) {
return new OvalRoi(x, y, width, height);
}
public static void setMinAndMax(double min, double max) {
setMinAndMax(getImage(), min, max, 7);
}
public static void setMinAndMax(ImagePlus img, double min, double max) {
setMinAndMax(img, min, max, 7);
}
public static void setMinAndMax(double min, double max, int channels) {
setMinAndMax(getImage(), min, max, channels);
}
private static void setMinAndMax(ImagePlus img, double min, double max, int channels) {
Calibration cal = img.getCalibration();
min = cal.getRawValue(min);
max = cal.getRawValue(max);
if (channels==7)
img.setDisplayRange(min, max);
else
img.setDisplayRange(min, max, channels);
img.updateAndDraw();
}
public static void resetMinAndMax() {
resetMinAndMax(getImage());
}
public static void resetMinAndMax(ImagePlus img) {
img.resetDisplayRange();
img.updateAndDraw();
}
public static void setThreshold(double lowerThreshold, double upperThresold) {
setThreshold(lowerThreshold, upperThresold, null);
}
public static void setThreshold(double lowerThreshold, double upperThreshold, String displayMode) {
setThreshold(getImage(), lowerThreshold, upperThreshold, displayMode);
}
public static void setThreshold(ImagePlus img, double lowerThreshold, double upperThreshold) {
setThreshold(img, lowerThreshold, upperThreshold, "Red");
}
public static void setThreshold(ImagePlus img, double lowerThreshold, double upperThreshold, String displayMode) {
Calibration cal = img.getCalibration();
if (displayMode==null || !displayMode.contains("raw")) {
lowerThreshold = cal.getRawValue(lowerThreshold);
upperThreshold = cal.getRawValue(upperThreshold);
}
setRawThreshold(img, lowerThreshold, upperThreshold, displayMode);
}
public static void setRawThreshold(ImagePlus img, double lowerThreshold, double upperThreshold) {
setRawThreshold(img, lowerThreshold, upperThreshold, null);
}
public static void setRawThreshold(ImagePlus img, double lowerThreshold, double upperThreshold, String displayMode) {
int mode = ImageProcessor.RED_LUT;
if (displayMode!=null) {
displayMode = displayMode.toLowerCase(Locale.US);
if (displayMode.contains("black"))
mode = ImageProcessor.BLACK_AND_WHITE_LUT;
else if (displayMode.contains("over"))
mode = ImageProcessor.OVER_UNDER_LUT;
else if (displayMode.contains("no"))
mode = ImageProcessor.NO_LUT_UPDATE;
}
img.getProcessor().setThreshold(lowerThreshold, upperThreshold, mode);
if (mode!=ImageProcessor.NO_LUT_UPDATE && img.getWindow()!=null) {
img.getProcessor().setLutAnimation(true);
img.updateAndDraw();
ThresholdAdjuster.update();
}
}
public static void setAutoThreshold(ImagePlus imp, String method) {
ImageProcessor ip = imp.getProcessor();
if (ip instanceof ColorProcessor)
throw new IllegalArgumentException("Non-RGB image required");
ip.setRoi(imp.getRoi());
if (method!=null) {
try {
if (method.indexOf("stack")!=-1)
setStackThreshold(imp, ip, method);
else
ip.setAutoThreshold(method);
} catch (Exception e) {
log(e.getMessage());
}
} else
ip.setAutoThreshold(ImageProcessor.ISODATA2, ImageProcessor.RED_LUT);
imp.updateAndDraw();
}
private static void setStackThreshold(ImagePlus imp, ImageProcessor ip, String method) {
boolean darkBackground = method.indexOf("dark")!=-1;
int measurements = Analyzer.getMeasurements();
Analyzer.setMeasurements(Measurements.AREA+Measurements.MIN_MAX);
ImageStatistics stats = new StackStatistics(imp);
Analyzer.setMeasurements(measurements);
AutoThresholder thresholder = new AutoThresholder();
double min=0.0, max=255.0;
if (imp.getBitDepth()!=8) {
min = stats.min;
max = stats.max;
}
int threshold = thresholder.getThreshold(method, stats.histogram);
double lower, upper;
if (darkBackground) {
if (ip.isInvertedLut())
{lower=0.0; upper=threshold;}
else
{lower=threshold+1; upper=255.0;}
} else {
if (ip.isInvertedLut())
{lower=threshold+1; upper=255.0;}
else
{lower=0.0; upper=threshold;}
}
if (lower>255) lower = 255;
if (max>min) {
lower = min + (lower/255.0)*(max-min);
upper = min + (upper/255.0)*(max-min);
} else
lower = upper = min;
ip.setMinAndMax(min, max);
ip.setThreshold(lower, upper, ImageProcessor.RED_LUT);
imp.updateAndDraw();
}
public static void resetThreshold() {
resetThreshold(getImage());
}
public static void resetThreshold(ImagePlus img) {
ImageProcessor ip = img.getProcessor();
ip.resetThreshold();
ip.setLutAnimation(true);
img.updateAndDraw();
ThresholdAdjuster.update();
}
public static void selectWindow(int id) {
if (id>0)
id = WindowManager.getNthImageID(id);
ImagePlus imp = WindowManager.getImage(id);
if (imp==null)
error("Macro Error", "Image "+id+" not found or no images are open.");
if (Interpreter.isBatchMode()) {
ImagePlus impT = WindowManager.getTempCurrentImage();
ImagePlus impC = WindowManager.getCurrentImage();
if (impC!=null && impC!=imp && impT!=null)
impC.saveRoi();
WindowManager.setTempCurrentImage(imp);
Interpreter.activateImage(imp);
WindowManager.setWindow(null);
} else {
if (imp==null)
return;
ImageWindow win = imp.getWindow();
if (win!=null) {
win.toFront();
win.setState(Frame.NORMAL);
WindowManager.setWindow(win);
}
long start = System.currentTimeMillis();
String thread = Thread.currentThread().getName();
int timeout = thread!=null&&thread.indexOf("EventQueue")!=-1?0:1000;
if (IJ.isMacOSX() && IJ.isJava18() && timeout>0)
timeout = 250; while (true) {
wait(10);
imp = WindowManager.getCurrentImage();
if (imp!=null && imp.getID()==id)
return; if ((System.currentTimeMillis()-start)>timeout && win!=null) {
WindowManager.setCurrentWindow(win);
return;
}
}
}
}
public static void selectWindow(String title) {
if (title.equals("ImageJ")&&ij!=null) {
ij.toFront();
return;
}
long start = System.currentTimeMillis();
while (System.currentTimeMillis()-start<3000) { Window win = WindowManager.getWindow(title);
if (win!=null && !(win instanceof ImageWindow)) {
selectWindow(win);
return;
}
int[] wList = WindowManager.getIDList();
int len = wList!=null?wList.length:0;
for (int i=0; i<len; i++) {
ImagePlus imp = WindowManager.getImage(wList[i]);
if (imp!=null) {
if (imp.getTitle().equals(title)) {
selectWindow(imp.getID());
return;
}
}
}
wait(10);
}
error("Macro Error", "No window with the title \""+title+"\" found.");
}
static void selectWindow(Window win) {
if (win instanceof Frame) {
((Frame)win).toFront();
((Frame)win).setState(Frame.NORMAL);
} else
((Dialog)win).toFront();
long start = System.currentTimeMillis();
while (true) {
wait(10);
if (WindowManager.getActiveWindow()==win)
return; if ((System.currentTimeMillis()-start)>1000) {
WindowManager.setWindow(win);
return; }
}
}
public static void setForegroundColor(int red, int green, int blue) {
setColor(red, green, blue, true);
}
public static void setBackgroundColor(int red, int green, int blue) {
setColor(red, green, blue, false);
}
static void setColor(int red, int green, int blue, boolean foreground) {
Color c = Colors.toColor(red, green, blue);
if (foreground) {
Toolbar.setForegroundColor(c);
ImagePlus img = WindowManager.getCurrentImage();
if (img!=null)
img.getProcessor().setColor(c);
} else
Toolbar.setBackgroundColor(c);
}
public static void setTool(int id) {
Toolbar.getInstance().setTool(id);
}
public static boolean setTool(String name) {
return Toolbar.getInstance().setTool(name);
}
public static String getToolName() {
return Toolbar.getToolName();
}
public static int doWand(int x, int y) {
return doWand(getImage(), x, y, 0, null);
}
public static int doWand(int x, int y, double tolerance, String mode) {
return doWand(getImage(), x, y, tolerance, mode);
}
public static int doWand(ImagePlus img, int x, int y, double tolerance, String mode) {
ImageProcessor ip = img.getProcessor();
if ((img.getType()==ImagePlus.GRAY32) && Double.isNaN(ip.getPixelValue(x,y)))
return 0;
int imode = Wand.LEGACY_MODE;
boolean smooth = false;
if (mode!=null) {
if (mode.startsWith("4"))
imode = Wand.FOUR_CONNECTED;
else if (mode.startsWith("8"))
imode = Wand.EIGHT_CONNECTED;
smooth = mode.contains("smooth");
}
Wand w = new Wand(ip);
double t1 = ip.getMinThreshold();
if (t1==ImageProcessor.NO_THRESHOLD || (ip.getLutUpdateMode()==ImageProcessor.NO_LUT_UPDATE&& tolerance>0.0)) {
w.autoOutline(x, y, tolerance, imode);
smooth = false;
} else
w.autoOutline(x, y, t1, ip.getMaxThreshold(), imode);
if (w.npoints>0) {
Roi previousRoi = img.getRoi();
Roi roi = new PolygonRoi(w.xpoints, w.ypoints, w.npoints, Roi.TRACED_ROI);
img.deleteRoi();
img.setRoi(roi);
if (previousRoi!=null)
roi.update(shiftKeyDown(), altKeyDown()); Roi roi2 = img.getRoi();
if (smooth && roi2!=null && roi2.getType()==Roi.TRACED_ROI) {
Rectangle bounds = roi2.getBounds();
if (bounds.width>1 && bounds.height>1) {
if (smoothMacro==null)
smoothMacro = BatchProcessor.openMacroFromJar("SmoothWandTool.txt");
if (EventQueue.isDispatchThread())
new MacroRunner(smoothMacro); else
Macro.eval(smoothMacro);
}
}
}
return w.npoints;
}
public static void setPasteMode(String mode) {
Roi.setPasteMode(stringToPasteMode(mode));
}
public static int stringToPasteMode(String mode) {
if (mode==null)
return Blitter.COPY;
mode = mode.toLowerCase(Locale.US);
int m = Blitter.COPY;
if (mode.startsWith("ble") || mode.startsWith("ave"))
m = Blitter.AVERAGE;
else if (mode.startsWith("diff"))
m = Blitter.DIFFERENCE;
else if (mode.indexOf("zero")!=-1)
m = Blitter.COPY_ZERO_TRANSPARENT;
else if (mode.startsWith("tran"))
m = Blitter.COPY_TRANSPARENT;
else if (mode.startsWith("and"))
m = Blitter.AND;
else if (mode.startsWith("or"))
m = Blitter.OR;
else if (mode.startsWith("xor"))
m = Blitter.XOR;
else if (mode.startsWith("sub"))
m = Blitter.SUBTRACT;
else if (mode.startsWith("add"))
m = Blitter.ADD;
else if (mode.startsWith("div"))
m = Blitter.DIVIDE;
else if (mode.startsWith("mul"))
m = Blitter.MULTIPLY;
else if (mode.startsWith("min"))
m = Blitter.MIN;
else if (mode.startsWith("max"))
m = Blitter.MAX;
return m;
}
public static ImagePlus getImage() {
ImagePlus img = WindowManager.getCurrentImage();
if (img==null) {
IJ.noImage();
if (ij==null)
System.exit(0);
else
abort();
}
return img;
}
public static ImagePlus getImage(Interpreter interpreter) {
macroInterpreter = interpreter;
ImagePlus imp = getImage();
macroInterpreter = null;
return imp;
}
public static ImageProcessor getProcessor() {
ImagePlus imp = IJ.getImage();
return imp.getProcessor();
}
public static void setSlice(int slice) {
getImage().setSlice(slice);
}
public static String getVersion() {
return ImageJ.VERSION;
}
public static String getFullVersion() {
String build = ImageJ.BUILD;
if (build.length()==0)
build = "99";
else if (build.length()==1)
build = "0" + build;
return ImageJ.VERSION+build;
}
public static String getDirectory(String title) {
String dir = null;
String title2 = title.toLowerCase(Locale.US);
if (title2.equals("plugins"))
dir = Menus.getPlugInsPath();
else if (title2.equals("macros"))
dir = Menus.getMacrosPath();
else if (title2.equals("luts")) {
String ijdir = Prefs.getImageJDir();
if (ijdir!=null)
dir = ijdir + "luts" + File.separator;
else
dir = null;
} else if (title2.equals("home"))
dir = System.getProperty("user.home");
else if (title2.equals("downloads"))
dir = System.getProperty("user.home")+File.separator+"Downloads";
else if (title2.equals("startup"))
dir = Prefs.getImageJDir();
else if (title2.equals("imagej"))
dir = Prefs.getImageJDir();
else if (title2.equals("current") || title2.equals("default"))
dir = OpenDialog.getDefaultDirectory();
else if (title2.equals("preferences"))
dir = Prefs.getPrefsDir();
else if (title2.equals("temp")) {
dir = System.getProperty("java.io.tmpdir");
if (isMacintosh()) dir = "/tmp/";
} else if (title2.equals("image")) {
ImagePlus imp = WindowManager.getCurrentImage();
FileInfo fi = imp!=null?imp.getOriginalFileInfo():null;
if (fi!=null && fi.directory!=null) {
dir = fi.directory;
} else
dir = null;
} else if (title2.equals("file"))
dir = OpenDialog.getLastDirectory();
else if (title2.equals("cwd"))
dir = System.getProperty("user.dir");
else {
DirectoryChooser dc = new DirectoryChooser(title);
dir = dc.getDirectory();
if (dir==null) Macro.abort();
}
dir = addSeparator(dir);
return dir;
}
public static String addSeparator(String path) {
if (path==null)
return null;
if (path.length()>0 && !(path.endsWith(File.separator)||path.endsWith("/"))) {
if (IJ.isWindows()&&path.contains(File.separator))
path += File.separator;
else
path += "/";
}
return path;
}
public static String getDir(String title) {
return getDirectory(title);
}
public static String getFilePath(String dialogTitle) {
OpenDialog od = new OpenDialog(dialogTitle);
return od.getPath();
}
public static void open() {
open(null);
}
public static void open(String path) {
if (ij==null && Menus.getCommands()==null)
init();
Opener o = new Opener();
macroRunning = true;
if (path==null || path.equals(""))
o.open();
else
o.open(path);
macroRunning = false;
}
public static void open(String path, int n) {
if (ij==null && Menus.getCommands()==null)
init();
ImagePlus imp = openImage(path, n);
if (imp!=null) imp.show();
}
public static ImagePlus openImage(String path) {
macroRunning = true;
ImagePlus imp = (new Opener()).openImage(path);
macroRunning = false;
return imp;
}
public static ImagePlus openImage(String path, int n) {
return (new Opener()).openImage(path, n);
}
public static ImagePlus openVirtual(String path) {
return FileInfoVirtualStack.openVirtual(path);
}
public static ImagePlus openImage() {
return openImage(null);
}
public static String openUrlAsString(String url) {
url = Opener.updateUrl(url);
if (debugMode) log("OpenUrlAsString: "+url);
StringBuffer sb = null;
url = url.replaceAll(" ", "%20");
try {
URL u = new URL(url);
URLConnection uc = u.openConnection();
long len = uc.getContentLength();
if (len>5242880L)
return "<Error: file is larger than 5MB>";
InputStream in = u.openStream();
BufferedReader br = new BufferedReader(new InputStreamReader(in,"UTF-8"));
sb = new StringBuffer() ;
String line;
while ((line=br.readLine()) != null)
sb.append (line + "\n");
in.close ();
} catch (Exception e) {
return("<Error: "+e+">");
}
if (sb!=null)
return new String(sb);
else
return "";
}
public static void save(String path) {
save(null, path);
}
public static void save(ImagePlus imp, String path) {
ImagePlus imp2 = imp;
if (imp2==null)
imp2 = WindowManager.getCurrentImage();
int dotLoc = path.lastIndexOf('.');
if (dotLoc==-1 && imp2!=null) {
path = path + ".tif"; dotLoc = path.lastIndexOf('.');
}
if (dotLoc!=-1) {
String title = imp2!=null?imp2.getTitle():null;
saveAs(imp, path.substring(dotLoc+1), path);
if (title!=null)
imp2.setTitle(title);
} else
error("The file path passed to IJ.save() method or save()\nmacro function is missing the required extension.\n \n\""+path+"\"");
}
public static void saveAs(String format, String path) {
saveAs(null, format, path);
}
public static void saveAs(ImagePlus imp, String format, String path) {
if (format==null)
return;
if (path!=null && path.length()==0)
path = null;
format = format.toLowerCase(Locale.US);
Roi roi2 = imp!=null?imp.getRoi():null;
if (roi2!=null)
roi2.endPaste();
if (format.indexOf("tif")!=-1) {
saveAsTiff(imp, path);
return;
} else if (format.indexOf("jpeg")!=-1 || format.indexOf("jpg")!=-1) {
path = updateExtension(path, ".jpg");
JpegWriter.save(imp, path, FileSaver.getJpegQuality());
return;
} else if (format.indexOf("gif")!=-1) {
path = updateExtension(path, ".gif");
GifWriter.save(imp, path);
return;
} else if (format.indexOf("text image")!=-1) {
path = updateExtension(path, ".txt");
format = "Text Image...";
} else if (format.indexOf("text")!=-1 || format.indexOf("txt")!=-1) {
if (path!=null && !path.endsWith(".xls") && !path.endsWith(".csv") && !path.endsWith(".tsv"))
path = updateExtension(path, ".txt");
format = "Text...";
} else if (format.indexOf("zip")!=-1) {
path = updateExtension(path, ".zip");
format = "ZIP...";
} else if (format.indexOf("raw")!=-1) {
format = "Raw Data...";
} else if (format.indexOf("avi")!=-1) {
path = updateExtension(path, ".avi");
format = "AVI... ";
} else if (format.indexOf("bmp")!=-1) {
path = updateExtension(path, ".bmp");
format = "BMP...";
} else if (format.indexOf("fits")!=-1) {
path = updateExtension(path, ".fits");
format = "FITS...";
} else if (format.indexOf("png")!=-1) {
path = updateExtension(path, ".png");
format = "PNG...";
} else if (format.indexOf("pgm")!=-1) {
path = updateExtension(path, ".pgm");
format = "PGM...";
} else if (format.indexOf("lut")!=-1) {
path = updateExtension(path, ".lut");
format = "LUT...";
} else if (format.contains("results") || format.contains("measurements") || format.contains("table")) {
format = "Results...";
} else if (format.contains("selection") || format.contains("roi")) {
path = updateExtension(path, ".roi");
format = "Selection...";
} else if (format.indexOf("xy")!=-1 || format.indexOf("coordinates")!=-1) {
path = updateExtension(path, ".txt");
format = "XY Coordinates...";
} else
error("Unsupported save() or saveAs() file format: \""+format+"\"\n \n\""+path+"\"");
if (path==null)
run(format);
else {
if (path.contains(" "))
run(imp, format, "save=["+path+"]");
else
run(imp, format, "save="+path);
}
}
public static boolean saveAsTiff(ImagePlus imp, String path) {
if (imp==null)
imp = getImage();
if (path==null || path.equals(""))
return (new FileSaver(imp)).saveAsTiff();
if (!path.endsWith(".tiff"))
path = updateExtension(path, ".tif");
FileSaver fs = new FileSaver(imp);
boolean ok;
if (imp.getStackSize()>1)
ok = fs.saveAsTiffStack(path);
else
ok = fs.saveAsTiff(path);
if (ok)
fs.updateImagePlus(path, FileInfo.TIFF);
return ok;
}
static String updateExtension(String path, String extension) {
if (path==null) return null;
int dotIndex = path.lastIndexOf(".");
int separatorIndex = path.lastIndexOf(File.separator);
if (dotIndex>=0 && dotIndex>separatorIndex && (path.length()-dotIndex)<=5) {
if (dotIndex+1<path.length() && Character.isDigit(path.charAt(dotIndex+1)))
path += extension;
else
path = path.substring(0, dotIndex) + extension;
} else
path += extension;
return path;
}
public static String saveString(String string, String path) {
return write(string, path, false);
}
public static String append(String string, String path) {
return write(string+"\n", path, true);
}
private static String write(String string, String path, boolean append) {
if (path==null || path.equals("")) {
String msg = append?"Append String...":"Save String...";
SaveDialog sd = new SaveDialog(msg, "Untitled", ".txt");
String name = sd.getFileName();
if (name==null) return null;
path = sd.getDirectory() + name;
}
try {
BufferedWriter out = new BufferedWriter(new FileWriter(path, append));
out.write(string);
out.close();
} catch (IOException e) {
return ""+e;
}
return null;
}
public static String openAsString(String path) {
if (path==null || path.equals("")) {
OpenDialog od = new OpenDialog("Open Text File", "");
String directory = od.getDirectory();
String name = od.getFileName();
if (name==null) return null;
path = directory + name;
}
String str = "";
File file = new File(path);
if (!file.exists())
return "Error: file not found";
try {
StringBuffer sb = new StringBuffer(5000);
BufferedReader r = new BufferedReader(new FileReader(file));
while (true) {
String s=r.readLine();
if (s==null)
break;
else
sb.append(s+"\n");
}
r.close();
str = new String(sb);
}
catch (Exception e) {
str = "Error: "+e.getMessage();
}
return str;
}
public static ByteBuffer openAsByteBuffer(String path) {
if (path==null || path.equals("")) {
OpenDialog od = new OpenDialog("Open as ByteBuffer", "");
String directory = od.getDirectory();
String name = od.getFileName();
if (name==null) return null;
path = directory + name;
}
File file = new File(path);
if (!file.exists()) {
error("OpenAsByteBuffer", "File not found");
return null;
}
int len = (int)file.length();
byte[] buffer = new byte[len];
try {
InputStream in = new BufferedInputStream(new FileInputStream(path));
DataInputStream dis = new DataInputStream(in);
dis.readFully(buffer);
dis.close();
}
catch (Exception e) {
error("OpenAsByteBuffer", e.getMessage());
return null;
}
return ByteBuffer.wrap(buffer);
}
public static ImagePlus createImage(String title, int width, int height, int depth, int bitdepth) {
return NewImage.createImage(title, width, height, depth, bitdepth, NewImage.FILL_BLACK);
}
public static ImagePlus createImage(String title, String type, int width, int height, int depth) {
type = type.toLowerCase(Locale.US);
int bitDepth = 8;
if (type.contains("16"))
bitDepth = 16;
boolean signedInt = type.contains("32-bit int");
if (type.contains("32"))
bitDepth = 32;
if (type.contains("24") || type.contains("rgb") || signedInt)
bitDepth = 24;
int options = NewImage.FILL_WHITE;
if (bitDepth==16 || bitDepth==32)
options = NewImage.FILL_BLACK;
if (type.contains("white"))
options = NewImage.FILL_WHITE;
else if (type.contains("black"))
options = NewImage.FILL_BLACK;
else if (type.contains("ramp"))
options = NewImage.FILL_RAMP;
else if (type.contains("noise") || type.contains("random"))
options = NewImage.FILL_NOISE;
options += NewImage.CHECK_AVAILABLE_MEMORY;
if (signedInt)
options += NewImage.SIGNED_INT;
return NewImage.createImage(title, width, height, depth, bitDepth, options);
}
public static ImagePlus createImage(String title, String type, int width, int height, int channels, int slices, int frames) {
if (type.contains("label"))
type += "ramp";
if (!(type.contains("white")||type.contains("ramp")))
type += "black";
ImagePlus imp = IJ.createImage(title, type, width, height, channels*slices*frames);
imp.setDimensions(channels, slices, frames);
int mode = IJ.COLOR;
if (type.contains("composite"))
mode = IJ.COMPOSITE;
if (type.contains("grayscale"))
mode = IJ.GRAYSCALE;
if (channels>1 && imp.getBitDepth()!=24)
imp = new CompositeImage(imp, mode);
imp.setOpenAsHyperStack(true);
if (type.contains("label"))
HyperStackMaker.labelHyperstack(imp);
return imp;
}
public static ImagePlus createHyperStack(String title, int width, int height, int channels, int slices, int frames, int bitdepth) {
ImagePlus imp = createImage(title, width, height, channels*slices*frames, bitdepth);
imp.setDimensions(channels, slices, frames);
if (channels>1 && bitdepth!=24)
imp = new CompositeImage(imp, IJ.COMPOSITE);
imp.setOpenAsHyperStack(true);
return imp;
}
public static void newImage(String title, String type, int width, int height, int depth) {
ImagePlus imp = createImage(title, type, width, height, depth);
if (imp!=null) {
macroRunning = true;
imp.show();
macroRunning = false;
}
}
public static boolean escapePressed() {
return escapePressed;
}
public static void resetEscape() {
escapePressed = false;
}
public static void redirectErrorMessages() {
redirectErrorMessages = true;
lastErrorMessage = null;
}
public static void redirectErrorMessages(boolean redirect) {
redirectErrorMessages = redirect;
lastErrorMessage = null;
}
public static boolean redirectingErrorMessages() {
return redirectErrorMessages;
}
public static void suppressPluginNotFoundError() {
suppressPluginNotFoundError = true;
}
public static ClassLoader getClassLoader() {
if (classLoader==null) {
String pluginsDir = Menus.getPlugInsPath();
if (pluginsDir==null) {
String home = System.getProperty("plugins.dir");
if (home!=null) {
if (!home.endsWith(Prefs.separator)) home+=Prefs.separator;
pluginsDir = home+"plugins"+Prefs.separator;
if (!(new File(pluginsDir)).isDirectory())
pluginsDir = home;
}
}
if (pluginsDir==null)
return IJ.class.getClassLoader();
else {
if (Menus.jnlp)
classLoader = new PluginClassLoader(pluginsDir, true);
else
classLoader = new PluginClassLoader(pluginsDir);
}
}
return classLoader;
}
public static Dimension getScreenSize() {
Rectangle bounds = GUI.getScreenBounds();
return new Dimension(bounds.width, bounds.height);
}
public static String[] getLuts() {
ArrayList list = new ArrayList();
Hashtable commands = Menus.getCommands();
Menu lutsMenu = Menus.getImageJMenu("Image>Lookup Tables");
if (commands==null || lutsMenu==null)
return new String[0];
for (int i=0; i<lutsMenu.getItemCount(); i++) {
MenuItem menuItem = lutsMenu.getItem(i);
String label = menuItem.getLabel();
if (label.equals("-") || label.equals("Invert LUT") || label.equals("Apply LUT"))
continue;
String command = (String)commands.get(label);
if (command==null || command.startsWith("ij.plugin.LutLoader"))
list.add(label);
}
return (String[])list.toArray(new String[list.size()]);
}
static void abort() {
if ((ij!=null || Interpreter.isBatchMode()) && macroInterpreter==null)
throw new RuntimeException(Macro.MACRO_CANCELED);
}
static void setClassLoader(ClassLoader loader) {
classLoader = loader;
}
public static void resetClassLoader() {
setClassLoader(null);
}
public static void handleException(Throwable e) {
if (exceptionHandler!=null) {
exceptionHandler.handle(e);
return;
}
if (Macro.MACRO_CANCELED.equals(e.getMessage()))
return;
CharArrayWriter caw = new CharArrayWriter();
PrintWriter pw = new PrintWriter(caw);
e.printStackTrace(pw);
String s = caw.toString();
String lineNumber = "";
if (s!=null && s.contains("ThreadDeath"))
return;
Interpreter interpreter = Thread.currentThread().getName().endsWith("Macro$") ? Interpreter.getInstance() : null;
if (interpreter!=null)
lineNumber = "\nMacro line number: " + interpreter.getLineNumber();
if (getInstance()!=null) {
s = IJ.getInstance().getInfo()+lineNumber+"\n \n"+s;
new TextWindow("Exception", s, 500, 340);
} else
log(s);
}
public static void setExceptionHandler(ExceptionHandler handler) {
exceptionHandler = handler;
}
public interface ExceptionHandler {
public void handle(Throwable e);
}
static ExceptionHandler exceptionHandler;
public static void addEventListener(IJEventListener listener) {
eventListeners.addElement(listener);
}
public static void removeEventListener(IJEventListener listener) {
eventListeners.removeElement(listener);
}
public static void notifyEventListeners(int eventID) {
synchronized (eventListeners) {
for (int i=0; i<eventListeners.size(); i++) {
IJEventListener listener = (IJEventListener)eventListeners.elementAt(i);
listener.eventOccurred(eventID);
}
}
}
public static void setProperty(String key, Object value) {
if (properties==null)
properties = new Properties();
if (value==null)
properties.remove(key);
else
properties.put(key, value);
}
public static Object getProperty(String key) {
if (properties==null)
return null;
else
return properties.get(key);
}
public static boolean statusBarProtected() {
return protectStatusBar;
}
public static void protectStatusBar(boolean protect) {
protectStatusBar = protect;
if (!protectStatusBar)
statusBarThread = null;
}
}