diff --git a/ij/ImageJ.java b/ij/ImageJ.java index 3b1080146..40852e8a9 100644 --- a/ij/ImageJ.java +++ b/ij/ImageJ.java @@ -79,7 +79,7 @@ public class ImageJ extends Frame implements ActionListener, /** Plugins should call IJ.getVersion() or IJ.getFullVersion() to get the version string. */ public static final String VERSION = "1.54e"; - public static final String BUILD = "22"; + public static final String BUILD = "25"; public static Color backgroundColor = new Color(237,237,237); /** SansSerif, 12-point, plain font. */ public static final Font SansSerif12 = new Font("SansSerif", Font.PLAIN, 12); diff --git a/ij/ImagePlus.java b/ij/ImagePlus.java index f13a6e578..bf668fc0f 100644 --- a/ij/ImagePlus.java +++ b/ij/ImagePlus.java @@ -2778,8 +2778,10 @@ public void setIgnoreGlobalCalibration(boolean ignoreGlobalCalibration) { */ public void mouseMoved(int x, int y) { Roi roi2 = getRoi(); - if (ij!=null && !IJ.statusBarProtected() && (roi2==null || roi2.getState()==Roi.NORMAL)) - ij.showStatus(getLocationAsString(x,y) + getValueAsString(x,y)); + if (ij!=null && !IJ.statusBarProtected() && (roi2==null || roi2.getState()==Roi.NORMAL)) { + String title = IJ.altKeyDown()?" ("+getTitle()+")":""; + ij.showStatus(getLocationAsString(x,y) + getValueAsString(x,y)+title); + } } /** Redisplays the (x,y) coordinates and pixel value (which may diff --git a/ij/plugin/ImageInfo.java b/ij/plugin/ImageInfo.java index a2c9a804f..f5a3f50de 100644 --- a/ij/plugin/ImageInfo.java +++ b/ij/plugin/ImageInfo.java @@ -195,6 +195,7 @@ private String getInfo(ImagePlus imp, ImageProcessor ip) { s += displayRanges(imp); else { s += "Display range: "+(int)ip.getMin()+"-"+(int)ip.getMax()+"\n"; + ip.resetRoi(); ImageStatistics stats = ip.getStats(); s += "Pixel value range: "+(int)stats.min+"-"+(int)stats.max+"\n"; } @@ -212,21 +213,23 @@ private String getInfo(ImagePlus imp, ImageProcessor ip) { s += "Display range: "; double min = ip.getMin(); double max = ip.getMax(); + String dash = "-"; + if (type==ImagePlus.GRAY32||cal.calibrated()) + dash = " - "; if (type==ImagePlus.GRAY32) - s += d2s(min) + " - " + d2s(max) + "\n"; + s += d2s(min) + dash + d2s(max) + "\n"; else if (cal.calibrated()) { pvrLabel = "Raw pixel value range: "; min = cal.getCValue((int)min); max = cal.getCValue((int)max); - s += d2s(min) + " - " + d2s(max) + "\n"; + s += d2s(min) + dash + d2s(max) + "\n"; } else - s += (int)min+"-"+(int)max+"\n"; + s += (int)min+dash+(int)max+"\n"; + ip.resetRoi(); ImageStatistics stats = ip.getStats(); - String dash = "-"; if (ip.isSigned16Bit()) { stats.min -= 32768; stats.max -= 32768; - dash = " - "; } if (type==ImagePlus.GRAY32) s += pvrLabel+d2s(stats.min)+dash+d2s(stats.max)+"\n"; @@ -408,7 +411,7 @@ else if (curveFit==Calibration.CUSTOM) s += "Macro is running"+(Interpreter.isBatchMode()?" in batch mode":"")+"\n"; Roi roi = imp.getRoi(); - if (roi == null) { + if (roi==null) { if (cal.calibrated()) s += " \n"; s += "No selection\n"; diff --git a/ij/plugin/Startup.java b/ij/plugin/Startup.java index 50518c7bc..789a1cfc8 100644 --- a/ij/plugin/Startup.java +++ b/ij/plugin/Startup.java @@ -21,7 +21,8 @@ public class Startup implements PlugIn, ItemListener { "Splash Screen", "Bolder selections", "Add to overlay", - "Flip FITS images" + "Flip FITS images", + "Calibrate conversions" }; private String macro = ""; private int originalLength; @@ -100,6 +101,8 @@ else if (item.equals(code[8])) statement = "setOption(\"Add to overlay\", true);\n"; else if (item.equals(code[9])) statement = "setOption(\"FlipFitsImages\", false);\n"; + else if (item.equals(code[10])) + statement = "setOption(\"CalibrateConversions\", true);\n"; if (statement!=null) { TextArea ta = gd.getTextArea1(); ta.insert(statement, ta.getCaretPosition()); diff --git a/ij/process/ImageConverter.java b/ij/process/ImageConverter.java index 3888dc77d..2b3b7cb17 100644 --- a/ij/process/ImageConverter.java +++ b/ij/process/ImageConverter.java @@ -29,7 +29,8 @@ public synchronized void convertToGray8() { ImageProcessor ip = imp.getProcessor(); if (type==ImagePlus.GRAY16 || type==ImagePlus.GRAY32) { if (Prefs.calibrateConversions) { - doScaling = true; + if (type==ImagePlus.GRAY16 && imp.getCalibration().calibrated()) + convertToGray32(); convertAndCalibrate(imp,"8-bit"); } else { imp.setProcessor(null, ip.convertToByte(doScaling)); @@ -67,30 +68,39 @@ public void convertToGray16() { if (type==ImagePlus.GRAY32) record(); imp.trimProcessor(); - if (Prefs.calibrateConversions && imp.getBitDepth()==32) { - doScaling = true; + if (Prefs.calibrateConversions && type==ImagePlus.GRAY32) convertAndCalibrate(imp,"16-bit"); - } else { + else { imp.setProcessor(null, ip.convertToShort(doScaling)); imp.setCalibration(imp.getCalibration()); //update calibration } } public static void convertAndCalibrate(ImagePlus imp, String type) { + setDoScaling(true); + Calibration cal = imp.getCalibration(); ImageProcessor ip = imp.getProcessor(); + int stackSize = imp.getStackSize(); double min = ip.getMin(); double max = ip.getMax(); ip.resetMinAndMax(); double min2 = ip.getMin(); double max2 = ip.getMax(); boolean eightBitConversion = type.equals("8-bit"); - ImageProcessor ip2 = null; - if (eightBitConversion) - ip2 = ip.convertToByte(true); - else - ip2 = ip.convertToShort(true); - imp.setProcessor(null,ip2); - Calibration cal = imp.getCalibration(); + if (stackSize>1) { + cal.disableDensityCalibration(); + ImageStatistics stats = new StackStatistics(imp); + min2 = stats.min; + max2 = stats.max; + convertStack(imp, eightBitConversion, min2, max2); + } else { + ImageProcessor ip2 = null; + if (eightBitConversion) + ip2 = ip.convertToByte(true); + else + ip2 = ip.convertToShort(true); + imp.setProcessor(null,ip2); + } int maxRange = eightBitConversion?255:65535; double[] x = {0,maxRange}; double[] y = {min2,max2}; @@ -109,6 +119,36 @@ public static void convertAndCalibrate(ImagePlus imp, String type) { imp.updateAndDraw(); } + private static void convertStack(ImagePlus imp, boolean eightBitConversion, double min, double max) { + int nSlices = imp.getStackSize(); + int width = imp.getWidth(); + int height = imp.getHeight(); + ImageStack stack1 = imp.getStack(); + ImageStack stack2 = new ImageStack(width, height); + String label; + int inc = nSlices/20; + if (inc<1) inc = 1; + ImageProcessor ip1, ip2; + for(int i=1; i<=nSlices; i++) { + label = stack1.getSliceLabel(1); + ip1 = stack1.getProcessor(1); + ip1.setMinAndMax(min, max); + if (eightBitConversion) + ip2 = ip1.convertToByte(true); + else + ip2 = ip1.convertToShort(true); + stack1.deleteSlice(1); + stack2.addSlice(label, ip2); + if ((i%inc)==0) { + IJ.showProgress((double)i/nSlices); + IJ.showStatus("Converting to 16-bits: "+i+"/"+nSlices); + } + } + IJ.showProgress(1.0); + imp.setStack(null, stack2); + ImageConverter.record(); + } + public static void record() { if (Recorder.record) { if (Prefs.calibrateConversions) { diff --git a/ij/process/ShortProcessor.java b/ij/process/ShortProcessor.java index 029690476..d20436fc7 100644 --- a/ij/process/ShortProcessor.java +++ b/ij/process/ShortProcessor.java @@ -476,7 +476,7 @@ public void applyTable(int[] lut) { findMinAndMax(); } - private void process(int op, double value) { + protected void process(int op, double value) { //wsr int v1, v2; double range = getMax()-getMin(); //boolean resetMinMax = roiWidth==width && roiHeight==height && !(op==FILL); diff --git a/ij/process/StackConverter.java b/ij/process/StackConverter.java index 0a1bd7e76..3462318c2 100644 --- a/ij/process/StackConverter.java +++ b/ij/process/StackConverter.java @@ -42,6 +42,12 @@ public void convertToGray8() { imp.setSlice(currentSlice); return; } + if (Prefs.calibrateConversions && !composite && (type==ImagePlus.GRAY16||type==ImagePlus.GRAY32)) { + if (type==ImagePlus.GRAY16 && imp.getCalibration().calibrated()) + convertToGray32(); + ImageConverter.convertAndCalibrate(imp,"8-bit"); + return; + } ImageStack stack2 = new ImageStack(width, height); Image img; @@ -116,6 +122,10 @@ public void convertToGray16() { return; if (!(type==ImagePlus.GRAY8 || type==ImagePlus.GRAY32)) throw new IllegalArgumentException("Unsupported conversion"); + if (Prefs.calibrateConversions && imp.getNChannels()==1 && type==ImagePlus.GRAY32) { + ImageConverter.convertAndCalibrate(imp,"16-bit"); + return; + } ImageStack stack1 = imp.getStack(); ImageStack stack2 = new ImageStack(width, height); int channels = imp.getNChannels(); diff --git a/ij/text/TextCanvas.java b/ij/text/TextCanvas.java index acf84ada0..795cec740 100644 --- a/ij/text/TextCanvas.java +++ b/ij/text/TextCanvas.java @@ -129,7 +129,7 @@ synchronized char[] getChars(int column, int row) { return null; if (row>=tp.vData.size()) return null; - char[] chars = row=0&&row -
  • 1.54e21 19 April 2023 +
  • 1.54e25 29 April 2023
    • Thanks to Jerome Mutterer, selections can now be both filled and outlined. For an example, use the new @@ -13,9 +13,12 @@ command.
    • Thanks to Eric Kischell, added a "Calibrate" checkbox to the Edit>Options>Conversions dialog and a -setOption("CalibrateConversions",boolean) macro DOCUMENT +setOption("CalibrateConversions",boolean) macro function (example). +
    • Thanks to Chris Ambrose, the title is displayed in the +status bar when the cursor is moved over an image with the +alt key down.
    • Thanks to 'Nottsuni', the Image>Show Info command displays both the pixel value range and the display range.
    • Thanks to Michael Ellis, the Edit>Selection>Interpolate @@ -37,7 +40,7 @@ use the Help>Examples>Macro>Turtle Graphics command.
    • Thanks to Stein Rorvik and Dennis Chang, added the -"Full range 16-bit inversons" option to the +"Full range 16-bit inversions" option to the Edit>Options>Conversions dialog and the setOption("fullRangeInversions") macro function. @@ -102,11 +105,11 @@ TextWindow.setAntialiased(boolean) method.
    • Fixed a bug that caused the selectImage(n) macro function, where n>0, to sometimes fail in batch mode macros. -
    • Thanks go 'Sethur', fixed a bug that caused the current +
    • Thanks to 'Sethur', fixed a bug that caused the current working directory to not be transferred to plugins executed from command line macros.
    • Thanks to 'Sethur', fixed a bug the caused the -ImagePlus.setPositionWithoutupdate(c,z,t) method to not +ImagePlus.setPositionWithoutUpdate(c,z,t) method to not work as expected.
    • Thanks to Eugene Katrukha, fixed a bug that caused the Edit>Selection>Fit Spline command to