Skip to content

Commit

Permalink
2023.04.19 (1.54e21; Scaled type conversions)
Browse files Browse the repository at this point in the history
  • Loading branch information
rasband committed Apr 19, 2023
1 parent 559646b commit b1c61b3
Show file tree
Hide file tree
Showing 14 changed files with 135 additions and 42 deletions.
2 changes: 1 addition & 1 deletion ij/ImageJ.java
Original file line number Diff line number Diff line change
Expand Up @@ -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 = "11";
public static final String BUILD = "22";
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);
Expand Down
11 changes: 8 additions & 3 deletions ij/Prefs.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ public class Prefs {
REVERSE_NEXT_PREVIOUS_ORDER=1<<5, AUTO_RUN_EXAMPLES=1<<6, SHOW_ALL_POINTS=1<<7,
DO_NOT_SAVE_WINDOW_LOCS=1<<8, JFILE_CHOOSER_CHANGED=1<<9,
CANCEL_BUTTON_ON_RIGHT=1<<10, IGNORE_RESCALE_SLOPE=1<<11,
NON_BLOCKING_DIALOGS=1<<12, FIXED_DICOM_SCALINGg=1<<13;
NON_BLOCKING_DIALOGS=1<<12, FIXED_DICOM_SCALING=1<<13,
CALIBRATE_CONVERSIONS=1<<14;
public static final String OPTIONS2 = "prefs.options2";

/** file.separator system property */
Expand Down Expand Up @@ -192,6 +193,8 @@ public class Prefs {
public static boolean autoLivePlots;
/** Use full range for 16-bit inversions */
public static boolean fullRange16bitInversions;
/** Calibrate image type conversions */
public static boolean calibrateConversions;

//Save location of moved image windows */
//public static boolean saveImageLocation = true;
Expand Down Expand Up @@ -589,7 +592,8 @@ static void loadOptions() {
dialogCancelButtonOnRight = (options2&CANCEL_BUTTON_ON_RIGHT)!=0;
ignoreRescaleSlope = (options2&IGNORE_RESCALE_SLOPE)!=0;
nonBlockingFilterDialogs = (options2&NON_BLOCKING_DIALOGS)!=0;
fixedDicomScaling = (options2&FIXED_DICOM_SCALINGg)!=0;
fixedDicomScaling = (options2&FIXED_DICOM_SCALING)!=0;
//calibrateConversions = (options2&CALIBRATE_CONVERSIONS)!=0;
}

static void saveOptions(Properties prefs) {
Expand Down Expand Up @@ -621,7 +625,8 @@ static void saveOptions(Properties prefs) {
+ (dialogCancelButtonOnRight?CANCEL_BUTTON_ON_RIGHT:0)
+ (ignoreRescaleSlope?IGNORE_RESCALE_SLOPE:0)
+ (nonBlockingFilterDialogs?NON_BLOCKING_DIALOGS:0)
+ (fixedDicomScaling?FIXED_DICOM_SCALINGg:0);
+ (fixedDicomScaling?FIXED_DICOM_SCALING:0);
//+ (calibrateConversions?CALIBRATE_CONVERSIONS:0);
prefs.put(OPTIONS2, Integer.toString(options2));
}

Expand Down
2 changes: 1 addition & 1 deletion ij/gui/ImageCanvas.java
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ void drawRoi(Graphics g, Roi roi, int index) {
ImagePlus imp2 = roi.getImage();
roi.setImage(imp);
Color saveColor = roi.getStrokeColor();
if (saveColor==null)
if (saveColor==null && roi.getFillColor()==null)
roi.setStrokeColor(defaultColor);
if (roi.getStroke()==null)
((Graphics2D)g).setStroke(Roi.onePixelWide);
Expand Down
6 changes: 3 additions & 3 deletions ij/gui/PolygonRoi.java
Original file line number Diff line number Diff line change
Expand Up @@ -271,11 +271,11 @@ private void drawSpline(Graphics g, float[] xpoints, float[] ypoints, int npoint
if (xpoints==null || xpoints.length==0)
return;
boolean doScaling = ic!=null; //quicker drawing if we don't need to convert to screen coordinates
if (ic!=null) {
if (ic!=null) try {
Rectangle srcRect = ic.getSrcRect();
if (srcRect!=null && srcRect.x == 0 && srcRect.y == 0 && ic!=null && ic.getMagnification()==1.0)
if (srcRect!=null && srcRect.x==0 && srcRect.y==0 && ic.getMagnification()==1.0)
doScaling = false;
}
} catch(Exception e) {}
double xd = getXBase();
double yd = getYBase();
Graphics2D g2d = (Graphics2D)g;
Expand Down
14 changes: 10 additions & 4 deletions ij/gui/Roi.java
Original file line number Diff line number Diff line change
Expand Up @@ -1936,14 +1936,19 @@ public static Color getColor() {
return ROIColor;
}

/** Sets the color used by this ROI to draw its outline. This color, if not null,
* overrides the global color set by the static setColor() method.
/** Sets the color used by this ROI to draw its outline.
* This color, if not null, overrides the global color set
* by the static setColor() method. Set the stroke color
* after setting the fill color to both fill and outline
* the ROI.
* @see #getStrokeColor
* @see #setStrokeWidth
* @see ij.ImagePlus#setOverlay(ij.gui.Overlay)
*/
public void setStrokeColor(Color c) {
strokeColor = c;
strokeColor = c;
//if (getType()==TRACED_ROI && c!=null && fillColor!=null)
// throw new IllegalArgumentException();
}

/** Returns the the color used to draw the ROI outline or null if the default color is being used.
Expand All @@ -1964,7 +1969,8 @@ public static void setDefaultColor(Color color) {
*/
public void setFillColor(Color color) {
fillColor = color;
if (isArea()) strokeColor=null;
if (fillColor!=null && isArea())
strokeColor=null;
}

/** Returns the fill color used to display this ROI, or null if it is displayed transparently.
Expand Down
13 changes: 7 additions & 6 deletions ij/macro/Functions.java
Original file line number Diff line number Diff line change
Expand Up @@ -4734,9 +4734,10 @@ else if (arg1.startsWith("supportmacroundo"))
Prefs.supportMacroUndo = state;
else if (arg1.equals("inverty"))
getImage().getCalibration().setInvertY(state);
else if (arg1.equals("scaleconversions"))
else if (arg1.equals("scaleconversions")) {
ImageConverter.setDoScaling(state);
else if (arg1.startsWith("copyhead"))
Prefs.calibrateConversions = false;
} else if (arg1.startsWith("copyhead"))
Prefs.copyColumnHeaders = state;
else if (arg1.equals("waitforcompletion"))
waitForCompletion = state;
Expand All @@ -4748,10 +4749,10 @@ else if (arg1.startsWith("monospaced"))
TextWindow.setMonospaced(state);
else if (arg1.startsWith("fullrange"))
Prefs.fullRange16bitInversions = state;
//else if (arg1.startsWith("saveimageloc")) {
// Prefs.saveImageLocation = state;
// if (!state) Prefs.set(ImageWindow.LOC_KEY,null);
else
else if (arg1.startsWith("calibrate")) {
Prefs.calibrateConversions = state;
ImageConverter.setDoScaling(true);
} else
interp.error("Invalid option");
}

Expand Down
27 changes: 23 additions & 4 deletions ij/plugin/ImageInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,11 @@ private String getInfo(ImagePlus imp, ImageProcessor ip) {
s += "(" + lut + ")\n";
if (imp.getNChannels()>1)
s += displayRanges(imp);
else
else {
s += "Display range: "+(int)ip.getMin()+"-"+(int)ip.getMax()+"\n";
ImageStatistics stats = ip.getStats();
s += "Pixel value range: "+(int)stats.min+"-"+(int)stats.max+"\n";
}
break;
case ImagePlus.GRAY16: case ImagePlus.GRAY32:
if (type==ImagePlus.GRAY16) {
Expand All @@ -205,15 +208,31 @@ private String getInfo(ImagePlus imp, ImageProcessor ip) {
if (imp.getNChannels()>1)
s += displayRanges(imp);
else {
String pvrLabel = "Pixel value range: ";
s += "Display range: ";
double min = ip.getMin();
double max = ip.getMax();
if (cal.calibrated()) {
if (type==ImagePlus.GRAY32)
s += d2s(min) + " - " + 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";
} else
s += (int)min+"-"+(int)max+"\n";
ImageStatistics stats = ip.getStats();
String dash = "-";
if (ip.isSigned16Bit()) {
stats.min -= 32768;
stats.max -= 32768;
dash = " - ";
}
s += d2s(min) + " - " + d2s(max) + "\n";
}
if (type==ImagePlus.GRAY32)
s += pvrLabel+d2s(stats.min)+dash+d2s(stats.max)+"\n";
else
s += pvrLabel+(int)stats.min+dash+(int)stats.max+"\n";
}
break;
case ImagePlus.COLOR_256:
s += "Bits per pixel: 8 (color LUT)\n";
Expand Down
5 changes: 5 additions & 0 deletions ij/plugin/Options.java
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ void conversions() {
//boolean weighted = !(Math.abs(weights[0]-1d/3d)<0.0001 && Math.abs(weights[1]-1d/3d)<0.0001 && Math.abs(weights[2]-1d/3d)<0.0001);
GenericDialog gd = new GenericDialog("Conversion Options");
gd.addCheckbox("Scale when converting", ImageConverter.getDoScaling());
gd.setInsets(0,40,0);
gd.addCheckbox("Calibrate", Prefs.calibrateConversions);
String prompt = "Weighted RGB conversions";
if (weighted)
prompt += " (" + IJ.d2s(weights[0]) + "," + IJ.d2s(weights[1]) + ","+ IJ.d2s(weights[2]) + ")";
Expand All @@ -177,8 +179,11 @@ void conversions() {
if (gd.wasCanceled())
return;
ImageConverter.setDoScaling(gd.getNextBoolean());
Prefs.calibrateConversions = gd.getNextBoolean();
Prefs.weightedColor = gd.getNextBoolean();
Prefs.fullRange16bitInversions = gd.getNextBoolean();
if (Prefs.calibrateConversions)
ImageConverter.setDoScaling(true);
if (!Prefs.weightedColor)
ColorProcessor.setWeightingFactors(1d/3d, 1d/3d, 1d/3d);
else if (Prefs.weightedColor && !weighted)
Expand Down
2 changes: 1 addition & 1 deletion ij/plugin/OverlayCommands.java
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ void addSelection() {
String name = roi.getName();
boolean newOverlay = name!=null && name.equals("new-overlay");
Roi roiClone = (Roi)roi.clone();
if (roi.getStrokeColor()==null)
if (roi.getStrokeColor()==null && roi.getFillColor()==null)
roi.setStrokeColor(Roi.getColor());
if (overlay==null || newOverlay)
overlay = OverlayLabels.createOverlay();
Expand Down
2 changes: 1 addition & 1 deletion ij/plugin/frame/RoiManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -1528,7 +1528,7 @@ void setProperties(Color color, int lineWidth, Color fillColor) {
fillColor = rpRoi.getFillColor();
rpName = rpRoi.getName();
}
if (rpRoi.getStrokeColor()==null)
if (rpRoi.getStrokeColor()==null && rpRoi.getFillColor()==null)
rpRoi.setStrokeColor(Roi.getColor());
rpRoi = (Roi) rpRoi.clone();
if (n>1)
Expand Down
69 changes: 60 additions & 9 deletions ij/process/ImageConverter.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,13 @@ public synchronized void convertToGray8() {
}
ImageProcessor ip = imp.getProcessor();
if (type==ImagePlus.GRAY16 || type==ImagePlus.GRAY32) {
imp.setProcessor(null, ip.convertToByte(doScaling));
imp.setCalibration(imp.getCalibration()); //update calibration
if (Prefs.calibrateConversions) {
doScaling = true;
convertAndCalibrate(imp,"8-bit");
} else {
imp.setProcessor(null, ip.convertToByte(doScaling));
imp.setCalibration(imp.getCalibration()); //update calibration
}
record();
} else if (type==ImagePlus.COLOR_RGB)
imp.setProcessor(null, ip.convertToByte(doScaling));
Expand Down Expand Up @@ -62,17 +67,63 @@ public void convertToGray16() {
if (type==ImagePlus.GRAY32)
record();
imp.trimProcessor();
imp.setProcessor(null, ip.convertToShort(doScaling));
imp.setCalibration(imp.getCalibration()); //update calibration
if (Prefs.calibrateConversions && imp.getBitDepth()==32) {
doScaling = true;
convertAndCalibrate(imp,"16-bit");
} else {
imp.setProcessor(null, ip.convertToShort(doScaling));
imp.setCalibration(imp.getCalibration()); //update calibration
}
}

public static void convertAndCalibrate(ImagePlus imp, String type) {
ImageProcessor ip = imp.getProcessor();
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();
int maxRange = eightBitConversion?255:65535;
double[] x = {0,maxRange};
double[] y = {min2,max2};
CurveFitter cf = new CurveFitter(x,y);
cf.doFit(CurveFitter.STRAIGHT_LINE, false);
int np = cf.getNumParams();
double[] p = cf.getParams();
double[] parameters = new double[np];
for (int i=0; i<np; i++)
parameters[i] = p[i];
cal.setFunction(Calibration.STRAIGHT_LINE, parameters, type+" converted");
min = cal.getRawValue(min);
max = cal.getRawValue(max);
if (IJ.debugMode) IJ.log("convertAndCalibrate: "+min+" "+max);
imp.setDisplayRange(min,max);
imp.updateAndDraw();
}

public static void record() {
if (Recorder.record) {
Boolean state = ImageConverter.getDoScaling();
if (Recorder.scriptMode())
Recorder.recordCall("ImageConverter.setDoScaling("+state+");", true);
else
Recorder.recordString("setOption(\"ScaleConversions\", "+state+");\n");
if (Prefs.calibrateConversions) {
boolean state = true;
if (Recorder.scriptMode())
Recorder.recordCall("Prefs.calibrateConversions = true;", true);
else
Recorder.recordString("setOption(\"CalibrateConversions\", "+state+");\n");
} else {
Boolean state = ImageConverter.getDoScaling();
if (Recorder.scriptMode())
Recorder.recordCall("ImageConverter.setDoScaling("+state+");", true);
else
Recorder.recordString("setOption(\"ScaleConversions\", "+state+");\n");
}
}
}

Expand Down
5 changes: 2 additions & 3 deletions ij/process/IntProcessor.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
package ij.process;

import java.util.*;
import java.awt.*;
import java.awt.image.*;
Expand All @@ -9,12 +8,12 @@
public class IntProcessor extends ColorProcessor {
private byte[] pixels8;

/**Creates a blank IntProcessor with the specified dimensions. */
/** Creates a blank IntProcessor with the specified dimensions. */
public IntProcessor(int width, int height) {
this(width, height, new int[width*height]);
}

/**Creates an IntProcessor from a pixel array. */
/** Creates an IntProcessor from a pixel array. */
public IntProcessor(int width, int height, int[] pixels) {
super(width, height, pixels);
makeDefaultColorModel();
Expand Down
10 changes: 5 additions & 5 deletions ij/process/ShortProcessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@
and methods that operate on that image. */
public class ShortProcessor extends ImageProcessor {

private int min, max, snapshotMin, snapshotMax;
private short[] pixels;
private byte[] pixels8;
protected int min, max, snapshotMin, snapshotMax; //wsr
protected short[] pixels;
protected byte[] pixels8;
private short[] snapshotPixels;
private byte[] LUT;
private boolean fixedScale;
protected boolean fixedScale;
private int bgValue;


Expand Down Expand Up @@ -292,7 +292,7 @@ public int getPixel(int x, int y) {
return 0;
}

public final int get(int x, int y) {
public int get(int x, int y) { //wsr final
return pixels[y*width+x]&0xffff;
}

Expand Down
9 changes: 8 additions & 1 deletion release-notes.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,19 @@
</head>
<body>

<li> <u>1.54e11 11 April 2023</u>
<li> <u>1.54e21 19 April 2023</u>
<ul>
<li> Thanks to Jerome Mutterer, selections can now be both
filled and outlined. For an example, use the new
<i>Help&gt;Examples&gt;Macro&gt;Easter Eggs</i>
command.
<li> Thanks to Eric Kischell, added a "Calibrate" checkbox to the
<i>Edit&gt;Options&gt;Conversions</i> dialog and a
setOption("CalibrateConversions",boolean) macro DOCUMENT
function
(<a href="http://wsr.imagej.net/macros/CalibrateConversions.ijm">example</a>).
<li> Thanks to 'Nottsuni', the <i>Image&gt;Show Info</i> command
displays both the pixel value range and the display range.
<li> Thanks to Michael Ellis, the <i>Edit&gt;Selection&gt;Interpolate</i>
command works with composite selections with holes.
<li> Thanks to Philippe Carl and Michael Schmid, added the
Expand Down

0 comments on commit b1c61b3

Please sign in to comment.