From 0c9e51886e294d2546784e1b6df381a82597c416 Mon Sep 17 00:00:00 2001 From: Wayne Rasband Date: Thu, 6 Aug 2009 22:49:14 +0200 Subject: [PATCH] =?UTF-8?q?=20=20=E2=80=A2=201.43e,=206=20August=202009=20?= =?UTF-8?q?=20=20=20=20=20=20=E2=96=A1=20Added=20the=20Process>Batch>=20su?= =?UTF-8?q?bmenu,=20containing=20Measure,=20Convert=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20and=20Process=20commands.=20=20=20=20=20=20=20=E2=96=A1?= =?UTF-8?q?=20Thanks=20to=20Norbert=20Vischer,=20it=20is=20now=20much=20ea?= =?UTF-8?q?sier=20to=20outline=20=20=20=20=20=20=20=20=20circular=20object?= =?UTF-8?q?s=20using=20the=20constrained=20(shift=20key=20down)=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20elliptical=20selection=20tool.=20=20=20=20=20?= =?UTF-8?q?=20=20=E2=96=A1=20Added=20an=20"Export"=20button=20to=20Plugins?= =?UTF-8?q?>Utilities>Command=20Finder.=20=20=20=20=20=20=20=E2=96=A1=20Ad?= =?UTF-8?q?ded=20the=20selectWindow("ImageJ")=20macro=20function.=20=20=20?= =?UTF-8?q?=20=20=20=20=E2=96=A1=20Fixed=20a=20bug=20that=20caused=20image?= =?UTF-8?q?=20zooming=20to=20fail=20on=20secondary=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20monitors.=20=20=20=20=20=20=20=E2=96=A1=20Fixed=20bugs=20tha?= =?UTF-8?q?t=20caused=20the=20particle=20analyzer=20to=20sometimes=20not?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20work=20as=20expected=20when=20"Black?= =?UTF-8?q?=20Background"=20was=20enabled=20in=20=20=20=20=20=20=20=20=20P?= =?UTF-8?q?rocess>Binary>Options.=20=20=20=20=20=20=20=E2=96=A1=20Fixed=20?= =?UTF-8?q?a=20bug=20that=20caused=20the=20Plugins>Utilities>Memory=20Moni?= =?UTF-8?q?tor=20=20=20=20=20=20=20=20=20tool=20to=20not=20work=20correctl?= =?UTF-8?q?y=20when=20the=20line=20width=20was=20greater=20than=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20one.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IJ_Props.txt | 7 +- ij/CommandListener.java | 11 +- ij/Executer.java | 2 +- ij/IJ.java | 64 ++++- ij/ImageJ.java | 3 +- ij/Menus.java | 1 + ij/gui/GenericDialog.java | 2 +- ij/gui/ImageCanvas.java | 27 +-- ij/gui/ImageWindow.java | 36 ++- ij/gui/ProgressBar.java | 7 +- ij/gui/Roi.java | 34 ++- ij/io/DirectoryChooser.java | 9 +- ij/io/Opener.java | 8 +- ij/macro/Functions.java | 10 +- ij/measure/Calibration.java | 3 +- ij/plugin/BatchConverter.java | 137 +++++++++++ ij/plugin/BatchMeasure.java | 29 +++ ij/plugin/BatchProcesser.java | 292 +++++++++++++++++++++++ ij/plugin/CommandFinder.java | 29 ++- ij/plugin/DragAndDrop.java | 12 +- ij/plugin/Macro_Runner.java | 8 +- ij/plugin/MemoryMonitor.java | 1 + ij/plugin/TextWriter.java | 3 +- ij/plugin/URLOpener.java | 4 +- ij/plugin/filter/Binary.java | 3 +- ij/plugin/filter/Calibrator.java | 2 +- ij/plugin/filter/EDM.java | 8 +- ij/plugin/filter/PlugInFilter.java | 2 + ij/plugin/filter/PlugInFilterRunner.java | 8 +- ij/plugin/filter/Resizer.java | 1 + ij/process/FloatProcessor.java | 6 +- ij/process/ImageProcessor.java | 25 +- release-notes.html | 37 +-- 33 files changed, 712 insertions(+), 119 deletions(-) create mode 100644 ij/plugin/BatchConverter.java create mode 100644 ij/plugin/BatchMeasure.java create mode 100644 ij/plugin/BatchProcesser.java diff --git a/IJ_Props.txt b/IJ_Props.txt index 18371df3c..58a4cf4f0 100644 --- a/IJ_Props.txt +++ b/IJ_Props.txt @@ -6,7 +6,7 @@ # Note that commands must be unique. -# Version 1.42 +# Version 1.43 # Popup Menu popup01=Undo @@ -265,6 +265,11 @@ filters08="Variance...",ij.plugin.filter.RankFilters("variance") filters09=- filters10="Show Circular Masks...",ij.plugin.filter.RankFilters("masks") +# Plugins installed in the File/Batch submenu +batch01="Measure...",ij.plugin.BatchMeasure +batch02="Convert...",ij.plugin.BatchConverter +batch03="Process...",ij.plugin.BatchProcesser + # Plugins installed in the Analyze/Gels submenu gels01="Select First Lane[1]",ij.plugin.GelAnalyzer("first") gels02="Select Next Lane[2]",ij.plugin.GelAnalyzer("next") diff --git a/ij/CommandListener.java b/ij/CommandListener.java index 98bbf540e..6b610a4ec 100644 --- a/ij/CommandListener.java +++ b/ij/CommandListener.java @@ -1,9 +1,16 @@ package ij; - /** Plugins that implement this interface are notified - when ImageJ is about to run a menu command. */ + /** Plugins that implement this interface are notified when ImageJ + is about to run a menu command. There is an example plugin at + http://rsb.info.nih.gov/ij/plugins/download/misc/Command_Listener.java + */ public interface CommandListener { + /* The method is called when ImageJ is about to run a menu command, + where 'command' is the name of the command. Return this string + and ImageJ will run the command, return a different command name + and ImageJ will run that command, or return null to not run a command. + */ public String commandExecuting(String command); } diff --git a/ij/Executer.java b/ij/Executer.java index 5444ac4d6..b5255f945 100644 --- a/ij/Executer.java +++ b/ij/Executer.java @@ -62,7 +62,7 @@ public void run() { IJ.setKeyUp(IJ.ALL_KEYS); // set keys up except for "<", ">", "+" and "-" shortcuts } catch(Throwable e) { IJ.showStatus(""); - IJ.showProgress(1.0); + IJ.showProgress(1, 1); ImagePlus imp = WindowManager.getCurrentImage(); if (imp!=null) imp.unlock(); String msg = e.getMessage(); diff --git a/ij/IJ.java b/ij/IJ.java index d00deb8e0..607a16caf 100644 --- a/ij/IJ.java +++ b/ij/IJ.java @@ -80,8 +80,9 @@ public static ImageJ getInstance() { } /** Runs the macro contained in the string macro. - Returns any string value returned by the macro, or null. - The equivalent macro function is eval(). */ + Returns any string value returned by the macro, null if the macro + does not return a value, or "[aborted]" if the macro was aborted + due to an error. The equivalent macro function is eval(). */ public static String runMacro(String macro) { return runMacro(macro, ""); } @@ -89,7 +90,9 @@ public static String runMacro(String macro) { /** Runs the macro contained in the string macro. The optional string argument can be retrieved in the called macro using the getArgument() macro function. - Returns any string value returned by the macro, or null. */ + Returns any string value returned by the macro, null if the macro + does not return a value, or "[aborted]" if the macro was aborted + due to an error. */ public static String runMacro(String macro, String arg) { Macro_Runner mr = new Macro_Runner(); return mr.runMacro(macro, arg); @@ -455,7 +458,11 @@ public static void showProgress(double progress) { The bar is updated only if more than 90 ms have passed since the last call. Does nothing if the ImageJ window is not present. */ public static void showProgress(int currentIndex, int finalIndex) { - if (progressBar!=null) progressBar.show(currentIndex, finalIndex); + if (progressBar!=null) { + progressBar.show(currentIndex, finalIndex); + if (currentIndex==finalIndex) + progressBar.setBatchMode(false); + } } /** Displays a message in a dialog box titled "Message". @@ -1006,6 +1013,8 @@ public static void selectWindow(int id) { /** Activates the window with the specified title. */ public static void selectWindow(String title) { + if (title.equals("ImageJ")&&ij!=null) + {ij.toFront(); return;} long start = System.currentTimeMillis(); while (System.currentTimeMillis()-start<3000) { // 3 sec timeout Frame frame = WindowManager.getFrame(title); @@ -1399,8 +1408,9 @@ static String updateExtension(String path, String extension) { return path; } - /** Saves a string as a file. Returns an error message - if there is an exception, otherwise returns null. */ + /** Saves a string as a file. Displays a file save dialog if + 'path' is null or blank. Returns an error message + if there is an exception, otherwise returns null. */ public static String saveString(String string, String path) { return write(string, path, false); } @@ -1413,6 +1423,13 @@ public static String append(String string, String path) { } 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); @@ -1423,6 +1440,41 @@ private static String write(String string, String path, boolean append) { return null; } + /** Opens a text file as a string. Displays a file open dialog + if path is null or blank. Returns null if the user cancels + the file open dialog. If there is an error, returns a + message in the form "Error: message". */ + public static String openAsString(String path) { + if (path==null || path.equals("")) { + OpenDialog od = new OpenDialog("Open As String", ""); + 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; + } + /** Creates a new imagePlus. Type should contain "8-bit", "16-bit", "32-bit" or "RGB". In addition, it can contain "white", "black" or "ramp" (the default is "white"). Width and height specify the width and height of the image in pixels. diff --git a/ij/ImageJ.java b/ij/ImageJ.java index 221ea26dc..5ea7b6b70 100644 --- a/ij/ImageJ.java +++ b/ij/ImageJ.java @@ -69,7 +69,7 @@ public class ImageJ extends Frame implements ActionListener, MouseListener, KeyListener, WindowListener, ItemListener, Runnable { /** Plugins should call IJ.getVersion() to get the version string. */ - public static final String VERSION = "1.43d"; + public static final String VERSION = "1.43e"; public static Color backgroundColor = new Color(220,220,220); //224,226,235 /** SansSerif, 12-point, plain font. */ public static final Font SansSerif12 = new Font("SansSerif", Font.PLAIN, 12); @@ -318,6 +318,7 @@ public void mouseClicked(MouseEvent e) {} public void mouseEntered(MouseEvent e) {} public void keyPressed(KeyEvent e) { + //if (e.isConsumed()) return; int keyCode = e.getKeyCode(); IJ.setKeyDown(keyCode); hotkey = false; diff --git a/ij/Menus.java b/ij/Menus.java index bf428802f..9f8e2da9b 100644 --- a/ij/Menus.java +++ b/ij/Menus.java @@ -171,6 +171,7 @@ String addMenuBar() { getMenu("Process>FFT", true); Menu filtersMenu = getMenu("Process>Filters", true); process.addSeparator(); + getMenu("Process>Batch", true); addPlugInItem(process, "Image Calculator...", "ij.plugin.ImageCalculator", 0, false); addPlugInItem(process, "Subtract Background...", "ij.plugin.filter.BackgroundSubtracter", 0, false); addItem(process, "Repeat Command", KeyEvent.VK_R, true); diff --git a/ij/gui/GenericDialog.java b/ij/gui/GenericDialog.java index 381793326..c0a7e9fbf 100644 --- a/ij/gui/GenericDialog.java +++ b/ij/gui/GenericDialog.java @@ -452,7 +452,7 @@ public void addTextAreas(String text1, String text2, int rows, int columns) { c.gridx = 0; c.gridy = y; c.gridwidth = 2; c.anchor = GridBagConstraints.WEST; - c.insets = new Insets(15, 20, 0, 0); + c.insets = getInsets(15, 20, 0, 0); grid.setConstraints(panel, c); add(panel); y++; diff --git a/ij/gui/ImageCanvas.java b/ij/gui/ImageCanvas.java index 6202577f1..4896c508a 100644 --- a/ij/gui/ImageCanvas.java +++ b/ij/gui/ImageCanvas.java @@ -465,30 +465,6 @@ void setMagnification2(double magnification) { imp.setTitle(imp.getTitle()); } - /* - public void setMagnification(double mag, int x, int y) { - if (mag>32.0) magnification = 32.0; - if (mag<0.03125) mag = 0.03125; - int newWidth = (int)(imageWidth*mag); - int newHeight = (int)(imageHeight*mag); - Dimension newSize = canEnlarge(newWidth, newHeight); - if (newSize!=null) { - setDrawingSize(newSize.width, newSize.height); - if (newSize.width!=newWidth || newSize.height!=newHeight) - adjustSourceRect(mag, x, y); - else - setMagnification(mag); - imp.getWindow().pack(); - } else - adjustSourceRect(mag, x, y); - repaint(); - if (srcRect.widthinsets.left+5 || loc.y>insets.top+5) { @@ -645,7 +620,7 @@ protected Dimension canEnlarge(int newWidth, int newHeight) { r1.width = r1.width - dstWidth + newWidth+10; r1.height = r1.height - dstHeight + newHeight+10; } - Rectangle max = win.getMaxWindow(); + Rectangle max = win.getMaxWindow(r1.x, r1.y); boolean fitsHorizontally = r1.x+r1.widthbounds.x+bounds.width || yloc>bounds.y+bounds.height) { + Rectangle bounds2 = getSecondaryMonitorBounds(ge, xloc, yloc); + if (bounds2!=null) return bounds2; + } Dimension ijSize = ij!=null?ij.getSize():new Dimension(0,0); - if (maxWindow.height>600) { - maxWindow.y += ijSize.height; - maxWindow.height -= ijSize.height; + if (bounds.height>600) { + bounds.y += ijSize.height; + bounds.height -= ijSize.height; } - return maxWindow; + return bounds; } - + + private Rectangle getSecondaryMonitorBounds(GraphicsEnvironment ge, int xloc, int yloc) { + //IJ.log("getSecondaryMonitorBounds "+wb); + GraphicsDevice[] gs = ge.getScreenDevices(); + for (int j=0; j=1.0) { //clear the progress bar percent = 0.0; showBar = false; @@ -109,4 +110,8 @@ public Dimension getPreferredSize() { return new Dimension(canvasWidth, canvasHeight); } + public void setBatchMode(boolean batchMode) { + this.batchMode = batchMode; + } + } \ No newline at end of file diff --git a/ij/gui/Roi.java b/ij/gui/Roi.java index 603298b9c..dd6914ce3 100644 --- a/ij/gui/Roi.java +++ b/ij/gui/Roi.java @@ -320,6 +320,8 @@ protected void grow(int sx, int sy) { } if (constrain) { // constrain selection to be square + if (!center) + {growConstrained(xNew, yNew); return;} int dx, dy, d; dx = xNew - x; dy = yNew - y; @@ -330,7 +332,6 @@ protected void grow(int sx, int sy) { xNew = x + d; yNew = y + d; } - if (center) { width = Math.abs(xNew - startX)*2; height = Math.abs(yNew - startY)*2; @@ -354,6 +355,29 @@ protected void grow(int sx, int sy) { oldHeight = height; } + private void growConstrained(int xNew, int yNew) { + int dx = xNew - startX; + int dy = yNew - startY; + width = height = (int)Math.round(Math.sqrt(dx*dx + dy*dy)); + if (type==RECTANGLE) { + x = (xNew>=startX)?startX:startX - width; + y = (yNew>=startY)?startY:startY - height; + if (x<0) x = 0; + if (y<0) y = 0; + if ((x+width) > xMax) width = xMax-x; + if ((y+height) > yMax) height = yMax-y; + } else { + x = startX + dx/2 - width/2; + y = startY + dy/2 - height/2; + } + updateClipRect(); + imp.draw(clipX, clipY, clipWidth, clipHeight); + oldX = x; + oldY = y; + oldWidth = width; + oldHeight = height; + } + protected void moveHandle(int sx, int sy) { double asp; if (clipboard!=null) return; @@ -454,10 +478,10 @@ protected void moveHandle(int sx, int sy) { } if(constrain) { - - if(activeHandle==1 || activeHandle==5) width=height; - else height=width; - + if (activeHandle==1 || activeHandle==5) + width=height; + else + height=width; if(center){ x=xc-width/2; y=yc-height/2; diff --git a/ij/io/DirectoryChooser.java b/ij/io/DirectoryChooser.java index 8f79c04a8..3dcd39383 100644 --- a/ij/io/DirectoryChooser.java +++ b/ij/io/DirectoryChooser.java @@ -50,7 +50,8 @@ public void run() { directory = dir.getPath(); if (!directory.endsWith(File.separator)) directory += File.separator; - defaultDir = directory; + if (directory!=null) + defaultDir = (new File(directory)).getParent(); String fileName = file.getName(); if (fileName.indexOf(":\\")!=-1) directory = defaultDir = fileName; @@ -79,7 +80,8 @@ void getDirectoryUsingJFileChooserOnThisThread(final String title) { directory = dir.getPath(); if (!directory.endsWith(File.separator)) directory += File.separator; - defaultDir = directory; + if (directory!=null) + defaultDir = (new File(directory)).getParent(); String fileName = file.getName(); if (fileName.indexOf(":\\")!=-1) directory = defaultDir = fileName; @@ -99,7 +101,8 @@ void getDirectoryUsingFileDialog(String title) { directory = null; else directory = od.getDirectory() + od.getFileName() + "/"; - defaultDir = directory; + if (directory!=null) + defaultDir = (new File(directory)).getParent(); System.setProperty("apple.awt.fileDialogForDirectories", "false"); Prefs.useJFileChooser = saveUseJFC; } diff --git a/ij/io/Opener.java b/ij/io/Opener.java index e1f04a1b7..460519266 100644 --- a/ij/io/Opener.java +++ b/ij/io/Opener.java @@ -195,10 +195,11 @@ private boolean isText(String path) { return true; int lastSlash = path.lastIndexOf("/"); if (lastSlash==-1) lastSlash = 0; - int dotIndex = path.indexOf(".", lastSlash+1); - if (dotIndex==-1 || (path.length()-dotIndex)>6) + int lastDot = path.lastIndexOf("."); + if (lastDot==-1 || lastDot6) return true; // no extension - return false; + else + return false; } /** Opens the specified file and adds it to the File/Open Recent menu. @@ -356,6 +357,7 @@ void openTextURL(String url) { name = name.substring(0, len-1); else if (index!=-1 && index=0&&index30000) + error("File is too large"); + else + gd.getTextArea1().setText(text); + } + } + + void save() { + macro = gd.getTextArea1().getText(); + if (!macro.equals("")) + IJ.saveString(macro, ""); + } + + void error(String msg) { + IJ.error("Batch Processer", msg); + } + + public void run() { + TextArea ta = gd.getTextArea1(); + //ta.selectAll(); + String macro = ta.getText(); + String inputPath = inputDir.getText(); + inputPath = addSeparator(inputPath); + File f1 = new File(inputPath); + if (!f1.exists() || !f1.isDirectory()) { + error("Input does not exist or is not a folder\n \n"+inputPath); + return; + } + if (macro.equals("")) { + error("There is no macro code in the text area"); + return; + } + String[] list = (new File(inputPath)).list(); + String name = list[0]; + if (name.startsWith(".")&&list.length>1) name = list[1]; + String path = inputPath + name; + ImagePlus imp = IJ.openImage(path); + if (imp==null) return; + WindowManager.setTempCurrentImage(imp); + String str = IJ.runMacro(macro, ""); + if (testImage!=0) { + ImagePlus imp2 = WindowManager.getImage(testImage); + if (imp2!=null) + {imp2.changes=false; imp2.close();} + } + imp.show(); + ImageWindow iw = imp.getWindow(); + if (iw!=null) iw.setLocation(10, 30); + testImage = imp.getID(); + } + +} diff --git a/ij/plugin/CommandFinder.java b/ij/plugin/CommandFinder.java index 45abac659..8c4e7d28e 100644 --- a/ij/plugin/CommandFinder.java +++ b/ij/plugin/CommandFinder.java @@ -17,14 +17,15 @@ below will only show commands that match that substring (case package ij.plugin; import ij.*; +import ij.text.*; import java.awt.*; import java.awt.event.*; -import java.util.Hashtable; import java.util.Arrays; import java.util.Iterator; import java.util.ArrayList; import java.util.Set; +import java.util.Hashtable; public class CommandFinder implements PlugIn, TextListener, ActionListener, WindowListener, KeyListener, ItemListener, MouseListener { @@ -59,12 +60,12 @@ public String toString() { Dialog d; TextField prompt; List completions; - Button runButton; - Button closeButton; + Button runButton, closeButton, exportButton; Checkbox fullInfoCheckbox, closeCheckbox; Hashtable commandsHash; String [] commands; Hashtable listLabelToCommand; + static boolean closeWhenRunning = true; protected String makeListLabel(String command, CommandAction ca, boolean fullInfo) { if (fullInfo) { @@ -105,6 +106,8 @@ public void actionPerformed(ActionEvent ae) { return; } runFromLabel(selected); + } else if (source == exportButton) { + export(); } else if (source == closeButton) { d.dispose(); } @@ -134,6 +137,18 @@ public void mousePressed(MouseEvent e) {} public void mouseReleased(MouseEvent e) {} public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} + + void export() { + String[] list = completions.getItems(); + StringBuffer sb = new StringBuffer(2000); + for (int i=0; i=0) { - int index2 = s.indexOf("\"", index1+6); + int index2 = s.indexOf("\"", index1+5); if (index2>0) - return s.substring(index1+6, index2); + return s.substring(index1+5, index2); } - index1 = s.indexOf("src=\""); + index1 = s.indexOf("href=\""); if (index1>=0) { - int index2 = s.indexOf("\"", index1+5); + int index2 = s.indexOf("\"", index1+6); if (index2>0) - return s.substring(index1+5, index2); + return s.substring(index1+6, index2); } return s; } diff --git a/ij/plugin/Macro_Runner.java b/ij/plugin/Macro_Runner.java index 6d3aac76a..7cfb0b1e7 100644 --- a/ij/plugin/Macro_Runner.java +++ b/ij/plugin/Macro_Runner.java @@ -124,8 +124,8 @@ public String runMacroFile(String name, String arg) { /** Opens and runs the specified macro on the current thread. Macros can retrieve the optional string argument by calling the getArgument() macro function. - Returns the String value returned by the macro or null if the macro does not - return a value. */ + Returns the String value returned by the macro, null if the macro does not + return a value, or "[aborted]" if the macro was aborted due to an error. */ public String runMacro(String macro, String arg) { Interpreter interp = new Interpreter(); try { @@ -138,7 +138,7 @@ public String runMacro(String macro, String arg) { if (imp!=null) imp.unlock(); String msg = e.getMessage(); if (e instanceof RuntimeException && msg!=null && e.getMessage().equals(Macro.MACRO_CANCELED)) - return null; + return "[aborted]"; CharArrayWriter caw = new CharArrayWriter(); PrintWriter pw = new PrintWriter(caw); e.printStackTrace(pw); @@ -153,7 +153,7 @@ public String runMacro(String macro, String arg) { IJ.log(s); } } - return null; + return "[aborted]"; } public String runMacroFromIJJar(String name, String arg) { diff --git a/ij/plugin/MemoryMonitor.java b/ij/plugin/MemoryMonitor.java index 2204a9651..e5adf0bf1 100644 --- a/ij/plugin/MemoryMonitor.java +++ b/ij/plugin/MemoryMonitor.java @@ -90,6 +90,7 @@ void updatePixels() { if (used>0.9*max) max *= 2.0; mem[index++] = used; if (index==mem.length) index = 0; + ip.setLineWidth(1); ip.reset(); int index2 = index+1; if (index2==mem.length) index2 = 0; diff --git a/ij/plugin/TextWriter.java b/ij/plugin/TextWriter.java index 86e626f43..931713881 100644 --- a/ij/plugin/TextWriter.java +++ b/ij/plugin/TextWriter.java @@ -25,7 +25,8 @@ void saveText() { } else { IJ.error("Save As Text", "This command requires a TextWindow, such\n" - + "as the \"Log\" window, or an Editor window."); + + "as the \"Log\" window, or an Editor window. Use\n" + + "File>Save>Text Image to save an image as text."); } } diff --git a/ij/plugin/URLOpener.java b/ij/plugin/URLOpener.java index 5128fee60..a317d432c 100644 --- a/ij/plugin/URLOpener.java +++ b/ij/plugin/URLOpener.java @@ -80,8 +80,8 @@ else if (url.endsWith(".jar")||url.endsWith(".class")) boolean noExtension(String url) { int lastSlash = url.lastIndexOf("/"); if (lastSlash==-1) lastSlash = 0; - int dotIndex = url.indexOf(".", lastSlash+1); - if (dotIndex==-1 || (url.length()-dotIndex)>6) + int lastDot = url.lastIndexOf("."); + if (lastDot==-1 || lastDot6) return true; // no extension else return false; diff --git a/ij/plugin/filter/Binary.java b/ij/plugin/filter/Binary.java index bb0ee9502..3ca0b4cf5 100644 --- a/ij/plugin/filter/Binary.java +++ b/ij/plugin/filter/Binary.java @@ -28,7 +28,7 @@ public class Binary implements ExtendedPlugInFilter, DialogListener { boolean previewing; boolean escapePressed; int foreground, background; - int flags = DOES_8G | DOES_8C | SUPPORTS_MASKING | PARALLELIZE_STACKS | KEEP_PREVIEW; + int flags = DOES_8G | DOES_8C | SUPPORTS_MASKING | PARALLELIZE_STACKS | KEEP_PREVIEW | KEEP_THRESHOLD; int nPasses; public int setup(String arg, ImagePlus imp) { @@ -122,6 +122,7 @@ else if (arg.equals("open")) { doIterations(ip, "erode"); } ip.setSnapshotCopyMode(false); + ip.setBinaryThreshold(); } void doIterations (ImageProcessor ip, String mode) { diff --git a/ij/plugin/filter/Calibrator.java b/ij/plugin/filter/Calibrator.java index bf2e026d4..ba08181e7 100644 --- a/ij/plugin/filter/Calibrator.java +++ b/ij/plugin/filter/Calibrator.java @@ -107,7 +107,7 @@ else if (function==Calibration.CUSTOM) } } - /** Creates a panel containing "Save..." and "Save..." buttons. */ + /** Creates a panel containing "Open..." and "Save..." buttons. */ Panel makeButtonPanel(GenericDialog gd) { Panel buttons = new Panel(); buttons.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 0)); diff --git a/ij/plugin/filter/EDM.java b/ij/plugin/filter/EDM.java index 497c4549c..6e8ef1b83 100644 --- a/ij/plugin/filter/EDM.java +++ b/ij/plugin/filter/EDM.java @@ -111,16 +111,17 @@ public int setup (String arg, ImagePlus imp) { //##arg="points"; //processing type; default is 'EDM' (0) - if (arg.equals("watershed")) + if (arg.equals("watershed")) { processType = WATERSHED; - else if (arg.equals("points")) + flags += KEEP_THRESHOLD; + } else if (arg.equals("points")) processType = UEP; else if (arg.equals("voronoi")) processType = VORONOI; //output type if (processType != WATERSHED) //Watershed always has output BYTE_OVERWRITE=0 - outImageType = outputType; + outImageType = outputType; if (outImageType != BYTE_OVERWRITE) flags |= NO_CHANGES; return flags; @@ -193,6 +194,7 @@ public void run (ImageProcessor ip) { if (processType==WATERSHED) { if (background255) maxIp.invert(); ip.copyBits(maxIp, 0, 0, Blitter.COPY); + ip.setBinaryThreshold(); } else switch (outImageType) { //for all these, output contains the values of the EDM case FLOAT: outIp = floatEdm; diff --git a/ij/plugin/filter/PlugInFilter.java b/ij/plugin/filter/PlugInFilter.java index ebfb69526..5cdc74dca 100644 --- a/ij/plugin/filter/PlugInFilter.java +++ b/ij/plugin/filter/PlugInFilter.java @@ -80,6 +80,8 @@ converted to a FloatProcessor. With RGB images, the run() method is * the calls to the run(ip) have finished. The argument arg of setup * will be "final" in that case. */ public final int FINAL_PROCESSING = 65536; + /** Set this flag to keep the invisible binary threshold from being reset. */ + public final int KEEP_THRESHOLD = 131072; // flags 0x01000000 and above are reserved for ExtendedPlugInFilter } \ No newline at end of file diff --git a/ij/plugin/filter/PlugInFilterRunner.java b/ij/plugin/filter/PlugInFilterRunner.java index 29d91b36b..407669e18 100644 --- a/ij/plugin/filter/PlugInFilterRunner.java +++ b/ij/plugin/filter/PlugInFilterRunner.java @@ -106,7 +106,8 @@ public PlugInFilterRunner(Object theFilter, String command, String arg) { else Undo.reset(); } - if ((flags&PlugInFilter.NO_CHANGES)==0) ip.resetBinaryThreshold(); + if ((flags&PlugInFilter.NO_CHANGES)==0&&(flags&PlugInFilter.KEEP_THRESHOLD)==0) + ip.resetBinaryThreshold(); } else { // S T A C K Undo.reset(); // no undo for processing a complete stack IJ.resetEscape(); @@ -145,9 +146,10 @@ public PlugInFilterRunner(Object theFilter, String command, String arg) { } // end processing: if ((flags&PlugInFilter.FINAL_PROCESSING)!=0 && !IJ.escapePressed()) ((PlugInFilter)theFilter).setup("final", imp); - if (IJ.escapePressed()) + if (IJ.escapePressed()) { IJ.showStatus(command + " INTERRUPTED"); - else + IJ.showProgress(1,1); + } else IJ.showTime(imp, imp.getStartTime()-previewTime, command + ": ", doStack?slices:1); IJ.showProgress(1.0); if (ipChanged) { diff --git a/ij/plugin/filter/Resizer.java b/ij/plugin/filter/Resizer.java index 264802228..2e7c3ccbe 100644 --- a/ij/plugin/filter/Resizer.java +++ b/ij/plugin/filter/Resizer.java @@ -130,6 +130,7 @@ public void run(ImageProcessor ip) { } catch(OutOfMemoryError o) { IJ.outOfMemory("Resize"); } + imp.changes = true; } public void textValueChanged(TextEvent e) { diff --git a/ij/process/FloatProcessor.java b/ij/process/FloatProcessor.java index 2196a34ba..c0b3fac10 100644 --- a/ij/process/FloatProcessor.java +++ b/ij/process/FloatProcessor.java @@ -10,11 +10,9 @@ public class FloatProcessor extends ImageProcessor { private float min, max, snapshotMin, snapshotMax; private float[] pixels; - private byte[] pixels8; + protected byte[] pixels8; private float[] snapshotPixels = null; - private byte[] LUT = null; private float fillColor = Float.MAX_VALUE; - //private float bgColor = Float.MIN_VALUE; private boolean fixedScale = false; /** Creates a new FloatProcessor using the specified pixel array and ColorModel. @@ -156,7 +154,7 @@ public Image createImage() { return img; } - byte[] create8BitImage() { + protected byte[] create8BitImage() { // scale from float to 8-bits int size = width*height; if (pixels8==null) diff --git a/ij/process/ImageProcessor.java b/ij/process/ImageProcessor.java index b6f636acb..8fa7880ab 100644 --- a/ij/process/ImageProcessor.java +++ b/ij/process/ImageProcessor.java @@ -366,7 +366,7 @@ public void resetMinAndMax() {} can be RED_LUT, BLACK_AND_WHITE_LUT, OVER_UNDER_LUT or NO_LUT_UPDATE. Thresholding of RGB images is not supported. */ public void setThreshold(double minThreshold, double maxThreshold, int lutUpdate) { - //ij.IJ.write("setThreshold: "+" "+minThreshold+" "+maxThreshold+" "+lutUpdate); + //ij.IJ.log("setThreshold: "+" "+minThreshold+" "+maxThreshold+" "+lutUpdate); if (this instanceof ColorProcessor) return; this.minThreshold = minThreshold; @@ -607,8 +607,27 @@ public int getLutUpdateMode() { return lutUpdateMode; } + /* Sets the threshold levels (non-visible) of an 8-bit mask based on + the state of Prefs.blackBackground and isInvertedLut(). + @see ImageProcessor#resetBinaryThreshold + */ + public void setBinaryThreshold() { + //ij.IJ.log("setMaskThreshold1"); + if (!(this instanceof ByteProcessor)) return; + double t1=255.0, t2=255.0; + boolean invertedLut = isInvertedLut(); + if ((invertedLut&&ij.Prefs.blackBackground) || (!invertedLut&&!ij.Prefs.blackBackground)) { + t1 = 0.0; + t2 = 0.0; + } + //ij.IJ.log("setMaskThreshold2 "+t1+" "+t2); + setThreshold(t1, t2, ImageProcessor.NO_LUT_UPDATE); + } + /** Resets the threshold if minThreshold=maxThreshold and lutUpdateMode=NO_LUT_UPDATE. - This removes the invisible threshold set by the MakeBinary and Convert to Mask commands.*/ + This removes the invisible threshold set by the MakeBinary and Convert to Mask commands. + @see ImageProcessor#setBinaryThreshold + */ public void resetBinaryThreshold() { if (minThreshold==maxThreshold && lutUpdateMode==NO_LUT_UPDATE) resetThreshold(); @@ -2090,5 +2109,5 @@ public boolean isBinary() { public static void setUseBicubic(boolean b) { useBicubic = b; } - + } diff --git a/release-notes.html b/release-notes.html index 5f1ff4422..7aa207a8a 100644 --- a/release-notes.html +++ b/release-notes.html @@ -5,32 +5,19 @@ -
  • 1.43d, 20 July 2009 +
  • 1.43e, 6 August 2009
      -
    • Thanks to Dimiter Prodanov, plugins (.jar and .class files) -dragged from a browser window and dropped on the "ImageJ" window -are installed and the ImageJ menus are updated. -
    • Text files can be dragged from a browser window -and dropped on the "ImageJ" window. -
    • Thanks to Julian Cooper, the alt key constrains resizing to -the current aspect ratio for rectangle and oval selections, and -keeps the same length for line selections. -
    • Added a "32-bit ABGR" option to the File>Import>Raw -dialog box. -
    • The ImageJ and Java version numbers are displayed when -you click in the status bar. -
    • Added the IJ.openUrlAsString() method. -
    • Fixed a bug that sometimes caused the micron symbol (µ) to not -be displayed correctly on Linux. -
    • Fixed a bug that caused big-endian ARGB TIFFs to open incorrectly. -
    • Fixed a bug that caused LUTs in the ImageJ/luts folder to not be -added to the Image>Lookup Tables menu when running Fiji on OS X. -
    • Fixed a bug that could cause Metamorph .stk files to open with -an all zero LUT. -
    • Fixed a bug that could cause ImageJ to generate an exception or fail -to start if there was a corrupted jar file in the plugins folder. -
    • Fixed a bug in the TIFF reader that could cause -a "Strip offsets are not in order" error. +
    • Added a Process>Batch> submenu containing Measure, +Convert and Process commands. +
    • Thanks to Norbert Vischer, it is now easier to outline circular objects +using the elliptical selection tool with the shift key down. +
    • Added an "Export" button to Plugins>Utilities>Command Finder. +
    • Added the selectWindow("ImageJ") macro function. +
    • Fixed a bug that caused image zooming to fail on secondary monitors. +
    • Fixed a bug that cuased the particle analyzer to sometimes not work as expected +when "Black Background" was enabled in the Process>Binary>Options dialog box. +
    • Fixed a bug that caused the Plugins>Utilities>Memory Monitor +tool to not work correctly when the line width was greater than one.
    Home