Skip to content

Commit 2651c5f

Browse files
committed
2025.04.12 (1.54q13; 3D filters)
1 parent 2bfe4ff commit 2651c5f

File tree

9 files changed

+328
-137
lines changed

9 files changed

+328
-137
lines changed

ij/ImageJ.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ public class ImageJ extends Frame implements ActionListener,
7979

8080
/** Plugins should call IJ.getVersion() or IJ.getFullVersion() to get the version string. */
8181
public static final String VERSION = "1.54q";
82-
public static final String BUILD = "6";
82+
public static final String BUILD = "13";
8383
public static Color backgroundColor = new Color(237,237,237);
8484
/** SansSerif, 12-point, plain font. */
8585
public static final Font SansSerif12 = new Font("SansSerif", Font.PLAIN, 12);

ij/Menus.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -844,7 +844,10 @@ public static Menu getImageJMenu(String menuPath) {
844844
}
845845

846846
private static Menu getMenu(String menuPath) {
847-
return getMenu(menuPath, false);
847+
if (GraphicsEnvironment.isHeadless())
848+
return null;
849+
else
850+
return getMenu(menuPath, false);
848851
}
849852

850853
private static Menu getMenu(String menuName, boolean readFromProps) {

ij/gui/PointRoi.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,7 @@ public int getCounter(int index) {
465465
return counters[index];
466466
}
467467

468+
/** Deletes all counters and stack position associations */
468469
public void resetCounters() {
469470
for (int i=0; i<counts.length; i++)
470471
counts[i] = 0;
@@ -669,7 +670,7 @@ public int[] getCounters() {
669670
/** Sets the counter number and slice number for each point from an
670671
* array, where the lower 8 bits are the counter number and the
671672
* higher 24 bits contain the slice position of each point.
672-
* Used when reading a roi fromfile (RoiDecoder). */
673+
* Used when reading a roi from file (RoiDecoder). */
673674
public void setCounters(int[] counters) {
674675
if (counters!=null) {
675676
int n = counters.length;
@@ -704,6 +705,7 @@ public void updateCounts() {
704705
* (ii) if it is the currently active Roi and Prefs.showAllPoints
705706
* ('Show an all slices' in the Point Tool Options dialog) is off.
706707
* Clears any association of this Roi to a hyperstack position.
708+
* Stack positions of individual points are overwritten.
707709
*
708710
* Note that the behavior differs from that of the other Roi types:
709711
* For the other Roi types, setPosition does not restrict the visibility
@@ -716,8 +718,11 @@ public void setPosition(int n) {
716718
if (n == 0) {
717719
positions = null;
718720
} else {
719-
if (positions == null)
720-
positions = new int[counters == null ? nPoints*2 : counters.length];
721+
if (positions == null) {
722+
if (counters == null)
723+
counters = new short[nPoints*2];
724+
positions = new int[counters.length];
725+
}
721726
if (n != POINTWISE_POSITION)
722727
Arrays.fill(positions, n);
723728
}

ij/macro/Functions.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6126,10 +6126,29 @@ else if (name.equals("deleteIndex"))
61266126
return deleteArrayIndex();
61276127
else if (name.equals("filter"))
61286128
return filterArray();
6129+
else if (name.equals("applyMacro"))
6130+
return applyMacroToArray();
61296131
else
61306132
interp.error("Unrecognized Array function");
61316133
return null;
61326134
}
6135+
6136+
Variable[] applyMacroToArray() {
6137+
interp.getLeftParen();
6138+
Variable[] a = getArray();
6139+
String macro = (String)getNextString();
6140+
interp.getRightParen();
6141+
ResultsTable rt = new ResultsTable();
6142+
rt.setColumn("v", a);
6143+
rt.applyMacro(macro);
6144+
Variable column = null;
6145+
try {
6146+
column = new Variable(rt.getColumnAsVariables("v"));
6147+
} catch (Exception e) {
6148+
interp.error(e.getMessage());
6149+
}
6150+
return column.getArray();
6151+
}
61336152

61346153
Variable[] filterArray() {
61356154
ArrayList list = new ArrayList();

ij/plugin/AboutBox.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ public void run(String arg) {
2727
text[6] = "ImageJ is in the public domain";
2828
ImageProcessor ip = null;
2929
ImageJ ij = IJ.getInstance();
30-
URL url = ij .getClass() .getResource("/about.jpg");
30+
if (ij==null)
31+
return;
32+
URL url = ij.getClass().getResource("/about.jpg");
3133
if (url!=null) {
3234
Image img = null;
3335
try {img = ij.createImage((ImageProducer)url.getContent());}

ij/plugin/Filters3D.java

Lines changed: 72 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
import ij.process.*;
55
import ij.gui.GenericDialog;
66
import ij.util.ThreadUtil;
7-
import ij.plugin.RGBStackMerge;
8-
import ij.gui.*;
97
import java.util.concurrent.atomic.AtomicInteger;
108

119
/*
@@ -15,6 +13,8 @@
1513
public class Filters3D implements PlugIn {
1614
public final static int MEAN=10, MEDIAN=11, MIN=12, MAX=13, VAR=14, MAXLOCAL=15;
1715
private static float xradius = 2, yradius = 2, zradius = 2;
16+
private static boolean doAllFrms=true;
17+
private static boolean doAllChs=true;
1818

1919
public void run(String arg) {
2020
String name = null;
@@ -45,103 +45,124 @@ public void run(String arg) {
4545
return;
4646
imp.startTiming();
4747
run(imp, filter, xradius, yradius, zradius);
48-
IJ.showTime(imp, imp.getStartTime(), "", imp.getStackSize());
48+
int nProcessedSlices=imp.getStackSize();
49+
if(!doAllChs)nProcessedSlices/=imp.getNChannels();
50+
if(!doAllFrms)nProcessedSlices/=imp.getNFrames();
51+
IJ.showTime(imp, imp.getStartTime(), "", nProcessedSlices);
4952
}
5053

5154
private boolean showDialog(String name) {
55+
ImagePlus imp = IJ.getImage();
5256
GenericDialog gd = new GenericDialog(name);
5357
gd.addNumericField("X radius:", xradius, 1);
5458
gd.addNumericField("Y radius:", yradius, 1);
5559
gd.addNumericField("Z radius:", zradius, 1);
60+
if(imp.getNChannels()>1)gd.addCheckbox("SingleChannel (current channel only)", !doAllChs);
61+
if(imp.getNFrames()>1)gd.addCheckbox("SingleFrame (current frame only)", !doAllFrms);
5662
gd.showDialog();
5763
if (gd.wasCanceled()) {
5864
return false;
5965
}
6066
xradius = (float) gd.getNextNumber();
6167
yradius = (float) gd.getNextNumber();
6268
zradius = (float) gd.getNextNumber();
69+
if(imp.getNChannels()>1)doAllChs=!gd.getNextBoolean();
70+
if(imp.getNFrames()>1)doAllFrms=!gd.getNextBoolean();
6371
return true;
6472
}
6573

6674
private void run(ImagePlus imp, int filter, float radX, float radY, float radZ) {
67-
if (imp.isHyperStack()) {
68-
filterHyperstack(imp, filter, radX, radY, radZ);
69-
return;
70-
}
71-
ImageStack res = filter(imp.getStack(), filter, radX, radY, radZ);
75+
int cmax=imp.getC(), cmin=cmax-1, tmax=imp.getT(), tmin=tmax-1, nZSlices=imp.getNSlices();
76+
if(doAllChs) { cmin=0; cmax=imp.getNChannels(); }
77+
if(doAllFrms) { tmin=0; tmax=imp.getNFrames(); }
78+
if(imp.getStackSize()==imp.getNFrames()) nZSlices=imp.getNFrames();
79+
ImageStack res = filter(imp.getStack(), filter, radX, radY, radZ, imp.getNChannels(), nZSlices, cmin, cmax, tmin, tmax);
7280
imp.setStack(res);
7381
}
74-
82+
7583
public static ImageStack filter(ImageStack stackorig, int filter, float vx, float vy, float vz) {
84+
return filter(stackorig, filter, vx, vy, vz, 1, stackorig.size(), 0, 1, 0, 1);
85+
}
7686

77-
if (stackorig.getBitDepth()==24)
78-
return filterRGB(stackorig, filter, vx, vy, vz);
87+
/**
88+
* Original functionality was for a single stack, so if imp is not provided, then
89+
* assume a non-hyperstack.
90+
*
91+
* @param imp Required if a hyperstack, otherwise null is ok
92+
* @param stack ImageStack
93+
* @param filter
94+
* @param vx
95+
* @param vy
96+
* @param vz
97+
* @return
98+
*/
99+
public static ImageStack filter(final ImageStack stack, final int filter, final float vx, final float vy, final float vz,
100+
final int nChs, int numberOfZSlices, int cmin, int cmax, int tmin, int tmax) {
101+
102+
if (stack.getBitDepth()==24)
103+
return filterRGB(stack, filter, vx, vy, vz, numberOfZSlices, tmin, tmax);
79104

80105
// get stack info
81-
final ImageStack stack = stackorig;
82-
final float voisx = vx;
83-
final float voisy = vy;
84-
final float voisz = vz;
85106
final int width= stack.getWidth();
86107
final int height= stack.getHeight();
87108
final int depth= stack.size();
109+
if(numberOfZSlices>depth) numberOfZSlices=depth;
110+
final int nZSlices=numberOfZSlices;
111+
if(cmin<0) cmin=0;
112+
if(tmin<0) tmin=0;
113+
if(cmax<nChs) cmax=nChs;
114+
if(tmax>(depth/nChs/nZSlices)) tmax=depth/nChs/nZSlices;
88115
ImageStack res = null;
89116

90117
if ((filter==MEAN) || (filter==MEDIAN) || (filter==MIN) || (filter==MAX) || (filter==VAR)) {
91118
if (filter==VAR)
92119
res = ImageStack.create(width, height, depth, 32);
93120
else
94-
res = ImageStack.create(width, height, depth, stackorig.getBitDepth());
121+
res = ImageStack.create(width, height, depth, stack.getBitDepth());
95122
IJ.showStatus("3D filtering...");
96123
// PARALLEL
97124
final ImageStack out = res;
98125
final AtomicInteger ai = new AtomicInteger(0);
99126
final int n_cpus = Prefs.getThreads();
100127

101-
final int f = filter;
102128
final int dec = (int) Math.ceil((double) stack.size() / (double) n_cpus);
103-
Thread[] threads = ThreadUtil.createThreadArray(n_cpus);
104-
for (int ithread = 0; ithread < threads.length; ithread++) {
105-
threads[ithread] = new Thread() {
106-
public void run() {
107-
StackProcessor processor = new StackProcessor(stack);
108-
for (int k = ai.getAndIncrement(); k < n_cpus; k = ai.getAndIncrement()) {
109-
processor.filter3D(out, voisx, voisy, voisz, dec * k, dec * (k + 1), f);
129+
for(int fr=0; fr< (depth/nZSlices/nChs); fr++) {
130+
for(int ch=0; ch<nChs; ch++) {
131+
if( fr>=tmin && fr<tmax && ch>=cmin && ch<cmax) {
132+
final int chf=ch;
133+
final int frf=fr;
134+
ai.set(0);
135+
Thread[] threads = ThreadUtil.createThreadArray(n_cpus);
136+
for (int ithread = 0; ithread < threads.length; ithread++) {
137+
threads[ithread] = new Thread() {
138+
public void run() {
139+
StackProcessor processor = new StackProcessor(stack);
140+
for (int k = ai.getAndIncrement(); k < n_cpus; k = ai.getAndIncrement()) {
141+
processor.filter3D(out, nChs, nZSlices, vx, vy, vz, chf, chf+1, dec * k, dec * (k + 1), frf, frf+1, filter);
142+
}
143+
}
144+
};
145+
}
146+
ThreadUtil.startAndJoin(threads);
147+
}else {
148+
for(int sl=0;sl<nZSlices;sl++) {
149+
int index=1+ch+(nChs*sl)+(nChs*nZSlices*fr);
150+
out.setProcessor(stack.getProcessor(index),index);
151+
out.setSliceLabel(stack.getSliceLabel(index), index);
110152
}
111153
}
112-
};
154+
}
113155
}
114-
ThreadUtil.startAndJoin(threads);
156+
115157
}
116158
return res;
117159
}
118-
119-
private static void filterHyperstack(ImagePlus imp, int filter, float vx, float vy, float vz) {
120-
if (imp.getNDimensions()>4) {
121-
IJ.error("5D hyperstacks are currently not supported");
122-
return;
123-
}
124-
if (imp.getNChannels()==1) {
125-
ImageStack stack = filter(imp.getStack(), filter, vx, vy, vz);
126-
imp.setStack(stack);
127-
return;
128-
}
129-
ImagePlus[] channels = ChannelSplitter.split(imp);
130-
int n = channels.length;
131-
for (int i=0; i<n; i++) {
132-
ImageStack stack = filter(channels[i].getStack(), filter, vx, vy, vz);
133-
channels[i].setStack(stack);
134-
}
135-
ImagePlus imp2 = RGBStackMerge.mergeChannels(channels, false);
136-
imp.setImage(imp2);
137-
imp.setC(1);
138-
}
139160

140-
private static ImageStack filterRGB(ImageStack rgb_in, int filter, float vx, float vy, float vz) {
161+
private static ImageStack filterRGB(ImageStack rgb_in, int filter, float vx, float vy, float vz, int nZSlices, int tmin, int tmax) {
141162
ImageStack[] channels = ChannelSplitter.splitRGB(rgb_in, false);
142-
ImageStack red = filter(channels[0], filter, vx, vy, vz);
143-
ImageStack green = filter(channels[1], filter, vx, vy, vz);
144-
ImageStack blue = filter(channels[2], filter, vx, vy, vz);
163+
ImageStack red = filter(channels[0], filter, vx, vy, vz, 1, nZSlices, 0, 1, tmin, tmax);
164+
ImageStack green = filter(channels[1], filter, vx, vy, vz, 1, nZSlices, 0, 1, tmin, tmax);
165+
ImageStack blue = filter(channels[2], filter, vx, vy, vz, 1, nZSlices, 0, 1, tmin, tmax);
145166
return RGBStackMerge.mergeStacks(red, green, blue, false);
146167
}
147168

0 commit comments

Comments
 (0)