package ij; import ij.util.Java2; import java.io.*; import java.util.*; import java.applet.*; import java.net.URL; import java.awt.*; import java.applet.Applet; import ij.io.*; import ij.util.Tools; import ij.gui.*; import ij.plugin.filter.*; import ij.process.ImageConverter; import ij.plugin.Animator; import ij.process.FloatBlitter; import ij.plugin.GelAnalyzer; import ij.process.ColorProcessor; import ij.text.TextWindow; /** This class contains the ImageJ preferences, which are loaded from the "IJ_Props.txt" and "IJ_Prefs.txt" files. @see ij.ImageJ */ public class Prefs { public static final String PROPS_NAME = "IJ_Props.txt"; public static final String PREFS_NAME = "IJ_Prefs.txt"; public static final String DIR_IMAGE = "dir.image"; public static final String FCOLOR = "fcolor"; public static final String BCOLOR = "bcolor"; public static final String ROICOLOR = "roicolor"; public static final String SHOW_ALL_COLOR = "showcolor"; public static final String JPEG = "jpeg"; public static final String FPS = "fps"; public static final String DIV_BY_ZERO_VALUE = "div-by-zero"; public static final String NOISE_SD = "noise.sd"; public static final String MENU_SIZE = "menu.size"; public static final String THREADS = "threads"; public static final String KEY_PREFIX = "."; private static final int USE_POINTER=1<<0, ANTIALIASING=1<<1, INTERPOLATE=1<<2, ONE_HUNDRED_PERCENT=1<<3, BLACK_BACKGROUND=1<<4, JFILE_CHOOSER=1<<5, UNUSED=1<<6, BLACK_CANVAS=1<<7, WEIGHTED=1<<8, AUTO_MEASURE=1<<9, REQUIRE_CONTROL=1<<10, USE_INVERTING_LUT=1<<11, ANTIALIASED_TOOLS=1<<12, INTEL_BYTE_ORDER=1<<13, DOUBLE_BUFFER=1<<14, NO_POINT_LABELS=1<<15, NO_BORDER=1<<16, SHOW_ALL_SLICE_ONLY=1<<17, COPY_HEADERS=1<<18, NO_ROW_NUMBERS=1<<19, MOVE_TO_MISC=1<<20, ADD_TO_MANAGER=1<<21, RUN_SOCKET_LISTENER=1<<22, MULTI_POINT_MODE=1<<23, ROTATE_YZ=1<<24, FLIP_XZ=1<<25, DONT_SAVE_HEADERS=1<<26, DONT_SAVE_ROW_NUMBERS=1<<27, NO_CLICK_TO_GC=1<<28, AVOID_RESLICE_INTERPOLATION=1<<29, KEEP_UNDO_BUFFERS=1<<30; public static final String OPTIONS = "prefs.options"; private static final int USE_SYSTEM_PROXIES=1<<0; private static final int USE_FILE_CHOOSER=1<<1; public static final String OPTIONS2 = "prefs.options2"; public static final String vistaHint = "\n \nOn Windows Vista, ImageJ must be installed in a directory that\nthe user can write to, such as \"Desktop\" or \"Documents\""; /** file.separator system property */ public static String separator = System.getProperty("file.separator"); /** Use pointer cursor instead of cross */ public static boolean usePointerCursor; /** No longer used */ public static boolean antialiasedText; /** Display images scaled <100% using bilinear interpolation */ public static boolean interpolateScaledImages; /** Open images at 100% magnification*/ public static boolean open100Percent; /** Backgound is black in binary images*/ public static boolean blackBackground; /** Use JFileChooser instead of FileDialog to open and save files. */ public static boolean useJFileChooser; /** Color to grayscale conversion is weighted (0.299, 0.587, 0.114) if the variable is true. */ public static boolean weightedColor; /** Use black image border. */ public static boolean blackCanvas; /** Point tool auto-measure mode. */ public static boolean pointAutoMeasure; /** Point tool auto-next slice mode (not saved in IJ_Prefs). */ public static boolean pointAutoNextSlice; /** Require control or command key for keybaord shortcuts. */ public static boolean requireControlKey; /** Open 8-bit images with inverting LUT so 0 is white and 255 is black. */ public static boolean useInvertingLut; /** Draw tool icons using antialiasing. */ public static boolean antialiasedTools = true; /** Export TIFF and Raw using little-endian byte order. */ public static boolean intelByteOrder; /** Double buffer display of selections and overlays. */ public static boolean doubleBuffer = true; /** Do not label multiple points created using point tool. */ public static boolean noPointLabels; /** Disable Edit/Undo command. */ public static boolean disableUndo; /** Do not draw black border around image. */ public static boolean noBorder; /** Only show ROIs associated with current slice in Roi Manager "Show All" mode. */ public static boolean showAllSliceOnly; /** Include column headers when copying tables to clipboard. */ public static boolean copyColumnHeaders; /** Do not include row numbers when copying tables to clipboard. */ public static boolean noRowNumbers; /** Move isolated plugins to Miscellaneous submenu. */ public static boolean moveToMisc; /** Add points to ROI Manager. */ public static boolean pointAddToManager; /** Extend the borders to foreground for binary erosions and closings. */ public static boolean padEdges; /** Run the SocketListener. */ public static boolean runSocketListener; /** Use MultiPoint tool. */ public static boolean multiPointMode; /** Open DICOMs as 32-bit float images */ public static boolean openDicomsAsFloat; /** Plot rectangular selectons vertically */ public static boolean verticalProfile; /** Rotate YZ orthogonal views 90 degrees */ public static boolean rotateYZ; /** Rotate XZ orthogonal views 180 degrees */ public static boolean flipXZ; /** Don't save Results table column headers */ public static boolean dontSaveHeaders; /** Don't save Results table row numbers */ public static boolean dontSaveRowNumbers; /** Don't run garbage collector when user clicks in status bar */ public static boolean noClickToGC; /** Angle tool measures reflex angle */ public static boolean reflexAngle; /** Avoid interpolation when re-slicing */ public static boolean avoidResliceInterpolation; /** Preserve undo (snapshot) buffers when switching images */ public static boolean keepUndoBuffers; /** Use ROI names as "show all" labels in the ROI Manager */ public static boolean useNamesAsLabels; /** Set the "java.net.useSystemProxies" property */ public static boolean useSystemProxies; /** Use the file chooser to import and export image sequences on Windows and Linux*/ public static boolean useFileChooser; static Properties ijPrefs = new Properties(); static Properties props = new Properties(ijPrefs); static String prefsDir; static String imagesURL; static String homeDir; // ImageJ folder static int threads; static int transparentIndex = -1; static boolean commandLineMacro; /** Finds and loads the ImageJ configuration file, "IJ_Props.txt". @return an error message if "IJ_Props.txt" not found. */ public static String load(Object ij, Applet applet) { InputStream f = ij.getClass().getResourceAsStream("/"+PROPS_NAME); if (applet!=null) return loadAppletProps(f, applet); if (homeDir==null) homeDir = System.getProperty("user.dir"); String userHome = System.getProperty("user.home"); if (IJ.isWindows()) { prefsDir = homeDir; //ImageJ folder on Windows if (prefsDir.endsWith("Desktop")) prefsDir = userHome; } else { prefsDir = userHome; // Mac Preferences folder or Unix home dir if (IJ.isMacOSX()) prefsDir += "/Library/Preferences"; else prefsDir += "/.imagej"; } if (f==null) { try {f = new FileInputStream(homeDir+"/"+PROPS_NAME);} catch (FileNotFoundException e) {f=null;} } if (f==null) return PROPS_NAME+" not found in ij.jar or in "+homeDir; f = new BufferedInputStream(f); try {props.load(f); f.close();} catch (IOException e) {return("Error loading "+PROPS_NAME);} imagesURL = props.getProperty("images.location"); loadPreferences(); loadOptions(); return null; } /* static void dumpPrefs(String title) { IJ.log(""); IJ.log(title); Enumeration e = ijPrefs.keys(); while (e.hasMoreElements()) { String key = (String) e.nextElement(); IJ.log(key+": "+ijPrefs.getProperty(key)); } } */ static String loadAppletProps(InputStream f, Applet applet) { if (f==null) return PROPS_NAME+" not found in ij.jar"; try { props.load(f); f.close(); } catch (IOException e) {return("Error loading "+PROPS_NAME);} try { URL url = new URL(applet.getDocumentBase(), "images/"); imagesURL = url.toString(); } catch (Exception e) {} return null; } /** Returns the URL of the directory that contains the ImageJ sample images. */ public static String getImagesURL() { return imagesURL; } /** Sets the URL of the directory that contains the ImageJ sample images. */ public static void setImagesURL(String url) { imagesURL = url; } /** Returns the path to the ImageJ directory. */ public static String getHomeDir() { return homeDir; } /** Gets the path to the directory where the preferences file (IJPrefs.txt) is saved. */ public static String getPrefsDir() { return prefsDir; } /** Sets the path to the ImageJ directory. */ static void setHomeDir(String path) { if (path.endsWith(File.separator)) path = path.substring(0, path.length()-1); homeDir = path; } /** Returns the default directory, if any, or null. */ public static String getDefaultDirectory() { if (commandLineMacro) return null; else return getString(DIR_IMAGE); } /** Finds an string in IJ_Props or IJ_Prefs.txt. */ public static String getString(String key) { return props.getProperty(key); } /** Finds an string in IJ_Props or IJ_Prefs.txt. */ public static String getString(String key, String defaultString) { if (props==null) return defaultString; String s = props.getProperty(key); if (s==null) return defaultString; else return s; } /** Finds a boolean in IJ_Props or IJ_Prefs.txt. */ public static boolean getBoolean(String key, boolean defaultValue) { if (props==null) return defaultValue; String s = props.getProperty(key); if (s==null) return defaultValue; else return s.equals("true"); } /** Finds an int in IJ_Props or IJ_Prefs.txt. */ public static int getInt(String key, int defaultValue) { if (props==null) //workaround for Netscape JIT bug return defaultValue; String s = props.getProperty(key); if (s!=null) { try { return Integer.decode(s).intValue(); } catch (NumberFormatException e) {IJ.write(""+e);} } return defaultValue; } /** Looks up a real number in IJ_Props or IJ_Prefs.txt. */ public static double getDouble(String key, double defaultValue) { if (props==null) return defaultValue; String s = props.getProperty(key); Double d = null; if (s!=null) { try {d = new Double(s);} catch (NumberFormatException e){d = null;} if (d!=null) return(d.doubleValue()); } return defaultValue; } /** Finds a color in IJ_Props or IJ_Prefs.txt. */ public static Color getColor(String key, Color defaultColor) { int i = getInt(key, 0xaaa); if (i == 0xaaa) return defaultColor; return new Color((i >> 16) & 0xFF, (i >> 8) & 0xFF, i & 0xFF); } /** Returns the file.separator system property. */ public static String getFileSeparator() { return separator; } /** Opens the IJ_Prefs.txt file. */ static void loadPreferences() { String path = prefsDir+separator+PREFS_NAME; boolean ok = loadPrefs(path); if (!ok && !IJ.isWindows()) { path = System.getProperty("user.home")+separator+PREFS_NAME; ok = loadPrefs(path); // look in home dir if (ok) new File(path).delete(); } } static boolean loadPrefs(String path) { try { InputStream is = new BufferedInputStream(new FileInputStream(path)); ijPrefs.load(is); is.close(); return true; } catch (Exception e) { return false; } } /** Saves user preferences in the IJ_Prefs.txt properties file. */ public static void savePreferences() { try { Properties prefs = new Properties(); String dir = OpenDialog.getDefaultDirectory(); if (dir!=null) prefs.put(DIR_IMAGE, dir); prefs.put(ROICOLOR, Tools.c2hex(Roi.getColor())); prefs.put(SHOW_ALL_COLOR, Tools.c2hex(ImageCanvas.getShowAllColor())); prefs.put(FCOLOR, Tools.c2hex(Toolbar.getForegroundColor())); prefs.put(BCOLOR, Tools.c2hex(Toolbar.getBackgroundColor())); prefs.put(JPEG, Integer.toString(FileSaver.getJpegQuality())); prefs.put(FPS, Double.toString(Animator.getFrameRate())); prefs.put(DIV_BY_ZERO_VALUE, Double.toString(FloatBlitter.divideByZeroValue)); prefs.put(NOISE_SD, Double.toString(Filters.getSD())); if (threads>1) prefs.put(THREADS, Integer.toString(threads)); if (IJ.isMacOSX()) useJFileChooser = false; saveOptions(prefs); savePluginPrefs(prefs); IJ.getInstance().savePreferences(prefs); Menus.savePreferences(prefs); ParticleAnalyzer.savePreferences(prefs); Analyzer.savePreferences(prefs); ImportDialog.savePreferences(prefs); PlotWindow.savePreferences(prefs); NewImage.savePreferences(prefs); String path = prefsDir+separator+PREFS_NAME; if (prefsDir.endsWith(".imagej")) { File f = new File(prefsDir); if (!f.exists()) f.mkdir(); // create .imagej directory } savePrefs(prefs, path); } catch (Throwable t) { String msg = t.getMessage(); if (msg==null) msg = ""+t; int delay = 4000; if (IJ.isVista()) { msg += vistaHint; delay = 8000; } try { new TextWindow("Error Saving Preferences", msg, 500, 200); IJ.wait(delay); } catch (Throwable t2) {} } } static void loadOptions() { int defaultOptions = ANTIALIASING+AVOID_RESLICE_INTERPOLATION +(!IJ.isMacOSX()?RUN_SOCKET_LISTENER:0); int options = getInt(OPTIONS, defaultOptions); usePointerCursor = (options&USE_POINTER)!=0; //antialiasedText = (options&ANTIALIASING)!=0; antialiasedText = false; interpolateScaledImages = (options&INTERPOLATE)!=0; open100Percent = (options&ONE_HUNDRED_PERCENT)!=0; open100Percent = (options&ONE_HUNDRED_PERCENT)!=0; blackBackground = (options&BLACK_BACKGROUND)!=0; useJFileChooser = (options&JFILE_CHOOSER)!=0; weightedColor = (options&WEIGHTED)!=0; if (weightedColor) ColorProcessor.setWeightingFactors(0.299, 0.587, 0.114); blackCanvas = (options&BLACK_CANVAS)!=0; pointAutoMeasure = (options&AUTO_MEASURE)!=0; requireControlKey = (options&REQUIRE_CONTROL)!=0; useInvertingLut = (options&USE_INVERTING_LUT)!=0; antialiasedTools = (options&ANTIALIASED_TOOLS)!=0; intelByteOrder = (options&INTEL_BYTE_ORDER)!=0; // doubleBuffer = (options&DOUBLE_BUFFER)!=0; // always double buffer //noPointLabels = (options&NO_POINT_LABELS)!=0; noBorder = (options&NO_BORDER)!=0; showAllSliceOnly = (options&SHOW_ALL_SLICE_ONLY)!=0; copyColumnHeaders = (options©_HEADERS)!=0; noRowNumbers = (options&NO_ROW_NUMBERS)!=0; moveToMisc = (options&MOVE_TO_MISC)!=0; pointAddToManager = (options&ADD_TO_MANAGER)!=0; runSocketListener = (options&RUN_SOCKET_LISTENER)!=0; multiPointMode = (options&MULTI_POINT_MODE)!=0; rotateYZ = (options&ROTATE_YZ)!=0; flipXZ = (options&FLIP_XZ)!=0; dontSaveHeaders = (options&DONT_SAVE_HEADERS)!=0; dontSaveRowNumbers = (options&DONT_SAVE_ROW_NUMBERS)!=0; noClickToGC = (options&NO_CLICK_TO_GC)!=0; avoidResliceInterpolation = (options&AVOID_RESLICE_INTERPOLATION)!=0; keepUndoBuffers = (options&KEEP_UNDO_BUFFERS)!=0; defaultOptions = (!IJ.isMacOSX()?USE_FILE_CHOOSER:0); int options2 = getInt(OPTIONS2, defaultOptions); useSystemProxies = (options2&USE_SYSTEM_PROXIES)!=0; useFileChooser = (options2&USE_FILE_CHOOSER)!=0; } static void saveOptions(Properties prefs) { int options = (usePointerCursor?USE_POINTER:0) + (antialiasedText?ANTIALIASING:0) + (interpolateScaledImages?INTERPOLATE:0) + (open100Percent?ONE_HUNDRED_PERCENT:0) + (blackBackground?BLACK_BACKGROUND:0) + (useJFileChooser?JFILE_CHOOSER:0) + (blackCanvas?BLACK_CANVAS:0) + (weightedColor?WEIGHTED:0) + (pointAutoMeasure?AUTO_MEASURE:0) + (requireControlKey?REQUIRE_CONTROL:0) + (useInvertingLut?USE_INVERTING_LUT:0) + (antialiasedTools?ANTIALIASED_TOOLS:0) + (intelByteOrder?INTEL_BYTE_ORDER:0) + (doubleBuffer?DOUBLE_BUFFER:0) + (noPointLabels?NO_POINT_LABELS:0) + (noBorder?NO_BORDER:0) + (showAllSliceOnly?SHOW_ALL_SLICE_ONLY:0) + (copyColumnHeaders?COPY_HEADERS:0) + (noRowNumbers?NO_ROW_NUMBERS:0) + (moveToMisc?MOVE_TO_MISC:0) + (pointAddToManager?ADD_TO_MANAGER:0) + (runSocketListener?RUN_SOCKET_LISTENER:0) + (multiPointMode?MULTI_POINT_MODE:0) + (rotateYZ?ROTATE_YZ:0) + (flipXZ?FLIP_XZ:0) + (dontSaveHeaders?DONT_SAVE_HEADERS:0) + (dontSaveRowNumbers?DONT_SAVE_ROW_NUMBERS:0) + (noClickToGC?NO_CLICK_TO_GC:0) + (avoidResliceInterpolation?AVOID_RESLICE_INTERPOLATION:0) + (keepUndoBuffers?KEEP_UNDO_BUFFERS:0); prefs.put(OPTIONS, Integer.toString(options)); int options2 = (useSystemProxies?USE_SYSTEM_PROXIES:0) + (useFileChooser?USE_FILE_CHOOSER:0); prefs.put(OPTIONS2, Integer.toString(options2)); } /** Saves the value of the string <code>text</code> in the preferences file using the keyword <code>key</code>. This string can be retrieved using the appropriate <code>get()</code> method. */ public static void set(String key, String text) { if (key.indexOf('.')<1) throw new IllegalArgumentException("Key must have a prefix"); ijPrefs.put(KEY_PREFIX+key, text); } /** Saves <code>value</code> in the preferences file using the keyword <code>key</code>. This value can be retrieved using the appropriate <code>getPref()</code> method. */ public static void set(String key, int value) { set(key, Integer.toString(value)); } /** Saves <code>value</code> in the preferences file using the keyword <code>key</code>. This value can be retrieved using the appropriate <code>getPref()</code> method. */ public static void set(String key, double value) { set(key, ""+value); } /** Saves the boolean variable <code>value</code> in the preferences file using the keyword <code>key</code>. This value can be retrieved using the appropriate <code>getPref()</code> method. */ public static void set(String key, boolean value) { set(key, ""+value); } /** Uses the keyword <code>key</code> to retrieve a string from the preferences file. Returns <code>defaultValue</code> if the key is not found. */ public static String get(String key, String defaultValue) { String value = ijPrefs.getProperty(KEY_PREFIX+key); if (value == null) return defaultValue; else return value; } /** Uses the keyword <code>key</code> to retrieve a number from the preferences file. Returns <code>defaultValue</code> if the key is not found. */ public static double get(String key, double defaultValue) { String s = ijPrefs.getProperty(KEY_PREFIX+key); Double d = null; if (s!=null) { try {d = new Double(s);} catch (NumberFormatException e) {d = null;} if (d!=null) return(d.doubleValue()); } return defaultValue; } /** Uses the keyword <code>key</code> to retrieve a boolean from the preferences file. Returns <code>defaultValue</code> if the key is not found. */ public static boolean get(String key, boolean defaultValue) { String value = ijPrefs.getProperty(KEY_PREFIX+key); if (value==null) return defaultValue; else return value.equals("true"); } /** Saves the Point <code>loc</code> in the preferences file as a string using the keyword <code>key</code>. */ public static void saveLocation(String key, Point loc) { set(key, loc.x+","+loc.y); } /** Uses the keyword <code>key</code> to retrieve a location from the preferences file. Returns null if the key is not found or the location is not valid (e.g., offscreen). */ public static Point getLocation(String key) { String value = ijPrefs.getProperty(KEY_PREFIX+key); if (value==null) return null; int index = value.indexOf(","); if (index==-1) return null; double xloc = Tools.parseDouble(value.substring(0, index)); if (Double.isNaN(xloc) || index==value.length()-1) return null; double yloc = Tools.parseDouble(value.substring(index+1)); if (Double.isNaN(yloc)) return null; Point p = new Point((int)xloc, (int)yloc); Dimension screen = IJ.getScreenSize(); if (p.x>screen.width-100 || p.y>screen.height-40) return null; else return p; } /** Save plugin preferences. */ static void savePluginPrefs(Properties prefs) { Enumeration e = ijPrefs.keys(); while (e.hasMoreElements()) { String key = (String) e.nextElement(); if (key.indexOf(KEY_PREFIX) == 0) prefs.put(key, ijPrefs.getProperty(key)); } } public static void savePrefs(Properties prefs, String path) throws IOException{ FileOutputStream fos = new FileOutputStream(path); BufferedOutputStream bos = new BufferedOutputStream(fos); prefs.store(bos, "ImageJ "+ImageJ.VERSION+" Preferences"); bos.close(); } /** Returns the number of threads used by PlugInFilters to process stacks. */ public static int getThreads() { if (threads==0) { threads = getInt(THREADS, 0); int processors = Runtime.getRuntime().availableProcessors(); if (threads<1 || threads>processors) threads = processors; } return threads; } /** Sets the number of threads (1-32) used by PlugInFilters to process stacks. */ public static void setThreads(int n) { if (n<1) n = 1; if (n>32) n = 32; threads = n; } /** Sets the transparent index (0-255), or set to -1 to disable transparency. */ public static void setTransparentIndex(int index) { if (index<-1 || index>255) index = -1; transparentIndex = index; } /** Returns the transparent index (0-255), or -1 if transparency is disabled. */ public static int getTransparentIndex() { return transparentIndex; } public static Properties getControlPanelProperties() { return ijPrefs; } }