Skip to content

Commit

Permalink
2023.05.15 (1.54e46; Spectrum Plot)
Browse files Browse the repository at this point in the history
  • Loading branch information
rasband committed May 15, 2023
1 parent d962255 commit 8d46a00
Show file tree
Hide file tree
Showing 8 changed files with 103 additions and 44 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 = "37";
public static final String BUILD = "46";
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
1 change: 1 addition & 0 deletions ij/Menus.java
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@ public static Menu getExamplesMenu(ActionListener listener) {
addExample(submenu, "Plot Styles", "Plot_Styles_.ijm");
addExample(submenu, "Random Data", "Random_Data_.ijm");
addExample(submenu, "Plot Results", "Plot_Results_.ijm");
addExample(submenu, "Plot With Spectrum", "Plot_With_Spectrum_.ijm");
submenu.addActionListener(listener);
menu.add(submenu);

Expand Down
4 changes: 2 additions & 2 deletions ij/VirtualStack.java
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,10 @@ public void addSlice(String sliceLabel, ImageProcessor ip, int n) {

/** Deletes the specified slice, where {@literal 1<=n<=nslices}. */
public void deleteSlice(int n) {
if (nSlices==0)
return;
if (n<1 || n>nSlices)
throw new IllegalArgumentException("Argument out of range: "+n);
if (nSlices<1)
return;
for (int i=n; i<nSlices; i++)
names[i-1] = names[i];
names[nSlices-1] = null;
Expand Down
5 changes: 4 additions & 1 deletion ij/macro/Functions.java
Original file line number Diff line number Diff line change
Expand Up @@ -8243,7 +8243,7 @@ static boolean isStringFunction(String name, int type) {
break;
case COLOR:
if (name.equals("foreground") || name.equals("background")
|| name.equals("toString"))
|| name.equals("toString") || name.equals("wavelengthToColor"))
isString = true;
break;
}
Expand Down Expand Up @@ -8340,6 +8340,9 @@ private Variable doColor() {
} else if (name.equals("getLut")) {
getLut();
return null;
} else if (name.equals("wavelengthToColor")) {
Color c = Colors.wavelengthToColor(getArg());
return new Variable(Colors.colorToString(c));
} else
interp.error("Unrecognized Color function");
return null;
Expand Down
51 changes: 51 additions & 0 deletions ij/plugin/Colors.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ public class Colors implements PlugIn, ItemListener {
private static final String[] colors2 = {"Red","Green","Blue","Magenta","Cyan","Yellow","Orange","Black","White","Gray","lightGray","darkGray","Pink"};
private Choice fchoice, bchoice, schoice;
private Color fc2, bc2, sc2;
private static final double gamma = 0.8;
private static final double intensityMax = 255;


public void run(String arg) {
showDialog();
Expand Down Expand Up @@ -273,4 +276,52 @@ public static String[] getColors(String... moreColors) {
names.add(arg);
return (String[])names.toArray(new String[names.size()]);
}

/** Converts a wavelength (380-750 nm) to color.
* Based on the wavelength_to_rgb.R program at
* https://gist.github.com/friendly/67a7df339aa999e2bcfcfec88311abfc,
* which in turn is based on a FORTRAN program at
* http://www.physics.sfasu.edu/astro/color.html.
* Thia method is used the the LutLoader class to
* generate the "Spectrum" LUT.
*/
public static Color wavelengthToColor(double wl) {
double R, G, B;
if (wl >= 380 & wl <= 440) {
double attenuation = 0.3 + 0.7 * (wl - 380) / (440 - 380);
R = Math.pow((-(wl - 440) / (440 - 380) * attenuation), gamma);
G = 0.0;
B = Math.pow((1.0 * attenuation), gamma);
} else if (wl >= 440 & wl <= 490) {
R = 0.0;
G = Math.pow(((wl - 440) / (490 - 440)), gamma);
B = 1.0;
} else if (wl >= 490 & wl <= 510) {
R = 0.0;
G = 1.0;
B = Math.pow((-(wl - 510) / (510 - 490)), gamma);
} else if (wl >= 510 & wl <= 580) {
R = Math.pow(((wl - 510) / (580 - 510)), gamma);
G = 1.0;
B = 0.0;
} else if (wl >= 580 & wl <= 645) {
R = 1.0;
G = Math.pow((-(wl - 645) / (645 - 580)), gamma);
B = 0.0;
} else if (wl >= 645 & wl <= 750) {
double attenuation = 0.3 + 0.7 * (750 - wl) / (750 - 645);
R = Math.pow((1.0 * attenuation), gamma);
G = 0.0;
B = 0.0;
} else {
R = 0.0;
G = 0.0;
B = 0.0;
}
R = Math.floor(R*255);
G = Math.floor(G*255);
B = Math.floor(B*255);
return new Color((int)R, (int)G, (int)B);
}

}
4 changes: 2 additions & 2 deletions ij/plugin/LutLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -227,9 +227,9 @@ int ice(byte[] reds, byte[] greens, byte[] blues) {
}

int spectrum(byte[] reds, byte[] greens, byte[] blues) {
Color c;
for (int i=0; i<256; i++) {
c = Color.getHSBColor(i/255f, 1f, 1f);
double wavelength = 380 + i*(700-380)/255.0;
Color c = Colors.wavelengthToColor(wavelength);
reds[i] = (byte)c.getRed();
greens[i] = (byte)c.getGreen();
blues[i] = (byte)c.getBlue();
Expand Down
72 changes: 35 additions & 37 deletions ij/plugin/SubstackMaker.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ public class SubstackMaker implements PlugIn {
private static boolean staticNoCreate;
private boolean noCreate;
private boolean methodCall;
private boolean isFFMPEG;

public void run(String arg) {
ImagePlus imp = IJ.getImage();
Expand All @@ -40,16 +39,16 @@ public void run(String arg) {
return;
}
ImageStack stack = imp.getStack();
if (stack.isVirtual() && stack.getClass().getName().contains("ffmpeg")) {
// stacks opened with FFMPEG plugin do not support delete
isFFMPEG = true;
}
int size1 = stack.size();
String userInput = showDialog();
if (userInput==null)
return;
ImagePlus imp2 = makeSubstack(imp, userInput);
if (imp2!=null && !noCreate)
imp2.show();
// stacks opened with FFMPEG and BioFormats plugins do not support slice delete
if (delete && stack.isVirtual() && stack.size()==size1)
IJ.log("This virtual stack does not support delete: "+stack.getClass().getName());
}

/**
Expand All @@ -62,11 +61,11 @@ public void run(String arg) {
public static ImagePlus run(ImagePlus imp, String rangeOrList) {
SubstackMaker sm = new SubstackMaker();
sm.delete = rangeOrList.contains("delete ");
sm.noCreate = rangeOrList.contains("do ");
sm.noCreate = rangeOrList.contains("do_not ");
if (sm.delete)
rangeOrList = rangeOrList.replace("delete ","");
if (sm.noCreate) {
rangeOrList = rangeOrList.replace("do ","");
rangeOrList = rangeOrList.replace("do_not ","");
sm.delete = true;
}
sm.methodCall = true;
Expand Down Expand Up @@ -132,6 +131,7 @@ public ImagePlus makeSubstack(ImagePlus imp, String userInput) {
imp2 = stackList(imp, count, numList, stackTitle);
}
} catch (Exception e) {
IJ.showProgress(1,1);
IJ.error("Substack Maker", "Invalid input string: \n \n \""+userInput+"\"");
}
if (hasFrames && imp2!=null)
Expand All @@ -154,32 +154,24 @@ String showDialog() {
gd.setInsets(10,45,0);
gd.addMessage("Enter a range (e.g. 2-14), a range with increment\n(e.g. 1-100-2) or a list (e.g. 7,9,25,27)", null, Color.darkGray);
gd.addStringField("Slices:", "", 40);
if (!isFFMPEG) {
gd.addCheckbox("Delete slices from original stack", delete);
gd.addCheckbox("Do not create substack", noCreate);
} else
gd.addMessage("FFMPEG plugin does not support virtual stack delete");
gd.addCheckbox("Delete slices from original stack", delete);
gd.addCheckbox("Do_not create substack", noCreate);
gd.showDialog();
if (gd.wasCanceled())
return null;
else {
String userInput = gd.getNextString();
if (isFFMPEG) {
staticDelete = delete = false;
staticNoCreate = noCreate = false;
} else {
delete = gd.getNextBoolean();
noCreate = gd.getNextBoolean();
if (noCreate)
staticDelete = delete = true;
}
delete = gd.getNextBoolean();
noCreate = gd.getNextBoolean();
if (noCreate)
staticDelete = delete = true;
if (!isMacro) {
staticDelete = delete;
staticNoCreate = noCreate;
}
options = "";
if (noCreate) options = "do_not "+options;
if (delete) options = "delete "+options;
if (noCreate) options = "do "+options;
Recorder.recordCall("SubstackMaker.run(imp, \""+options+userInput+"\");");
return userInput;
}
Expand All @@ -194,16 +186,17 @@ ImagePlus stackList(ImagePlus imp, int count, int[] numList, String stackTitle)
double max = imp.getDisplayRangeMax();
Roi roi = imp.getRoi();
boolean dup = imp.getWindow()!=null && !delete;
if (noCreate) dup=false;
for (int i=0, j=0; i<count; i++) {
int currSlice = numList[i]-j;
ImageProcessor ip2 = stack.getProcessor(currSlice);
ip2.setRoi(roi);
if (!methodCall || !delete)
ip2 = ip2.crop();
if (stack2==null)
stack2 = new ImageStack(ip2.getWidth(), ip2.getHeight());
stack2.addSlice(stack.getSliceLabel(currSlice), dup?ip2.duplicate():ip2);
if (!noCreate) {
ImageProcessor ip2 = stack.getProcessor(currSlice);
ip2.setRoi(roi);
if (!methodCall || !delete)
ip2 = ip2.crop();
if (stack2==null)
stack2 = new ImageStack(ip2.getWidth(), ip2.getHeight());
stack2.addSlice(stack.getSliceLabel(currSlice), dup?ip2.duplicate():ip2);
}
if (delete) {
stack.deleteSlice(currSlice);
j++;
Expand All @@ -217,6 +210,8 @@ ImagePlus stackList(ImagePlus imp, int count, int[] numList, String stackTitle)
if (swin!=null)
swin.updateSliceSelector();
}
if (stack2==null)
return null;
ImagePlus impSubstack = imp.createImagePlus();
impSubstack.setStack(stackTitle, stack2);
if (virtualStack)
Expand All @@ -234,16 +229,17 @@ ImagePlus stackRange(ImagePlus imp, int first, int last, int inc, String title)
Roi roi = imp.getRoi();
boolean showProgress = stack.size()>400 || stack.isVirtual();
boolean dup = imp.getWindow()!=null && !delete;
if (noCreate) dup=false;
for (int i= first, j=0; i<= last; i+=inc) {
if (showProgress) IJ.showProgress(i,last);
int currSlice = i-j;
ImageProcessor ip2 = stack.getProcessor(currSlice);
ip2.setRoi(roi);
ip2 = ip2.crop();
if (stack2==null)
stack2 = new ImageStack(ip2.getWidth(), ip2.getHeight());
stack2.addSlice(stack.getSliceLabel(currSlice), dup?ip2.duplicate():ip2);
if (!noCreate) {
ImageProcessor ip2 = stack.getProcessor(currSlice);
ip2.setRoi(roi);
ip2 = ip2.crop();
if (stack2==null)
stack2 = new ImageStack(ip2.getWidth(), ip2.getHeight());
stack2.addSlice(stack.getSliceLabel(currSlice), dup?ip2.duplicate():ip2);
}
if (delete) {
stack.deleteSlice(currSlice);
j++;
Expand All @@ -257,6 +253,8 @@ ImagePlus stackRange(ImagePlus imp, int first, int last, int inc, String title)
if (swin!=null)
swin.updateSliceSelector();
}
if (stack2==null)
return null;
ImagePlus substack = imp.createImagePlus();
substack.setStack(title, stack2);
substack.setCalibration(imp.getCalibration());
Expand Down
8 changes: 7 additions & 1 deletion release-notes.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@
</head>
<body>

<li> <u>1.54e37 11 May 2023</u>
<li> <u>1.54e46 15 May 2023</u>
<ul>
<li> Thanks to Jerome Mutterer, added the
<i>Help&gt;Examples&gt;Plots&gt;Plot with Spectrum</i>
example macro.
<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>
Expand All @@ -27,6 +30,9 @@
command works with composite selections with holes.
<li> Thanks to Philippe Carl and Michael Schmid, added the
Plot.eneableLive() macro function.
<li> Thanks to Jerome Mutterer, added the Color.wavelengthToColor()
macro function and the Colors.wavelengthToColor() method,
which is now used to generate the "Spectrum" LUT.
<li> Thanks to Michael Schmid, fixed issue with thresholding of 16-bit
and float images with inverting LUTs.
<li> Thanks to 'Jossie', fixed problem with <i>Image&gt;Color&gt;Make Composite</i>
Expand Down

0 comments on commit 8d46a00

Please sign in to comment.