File: RoiEnlarger.java

package info (click to toggle)
imagej 1.52j-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 5,604 kB
  • sloc: java: 120,017; sh: 279; xml: 161; makefile: 6
file content (138 lines) | stat: -rw-r--r-- 3,974 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package ij.plugin;
import ij.*;
import ij.process.*;
import ij.gui.*;
import ij.measure.Calibration;
import ij.plugin.filter.EDM;
import ij.plugin.filter.ThresholdToSelection;
import java.awt.*;

/** This plugin, which enlarges or shrinks selections, implements the Edit/Selection/Enlarge command. */
public class RoiEnlarger implements PlugIn {
	private static double defaultDistance = 15; // pixels

	public void run(String arg) {
		ImagePlus imp = IJ.getImage();
		Roi roi = imp.getRoi();
		if (roi==null || roi.isLine()) {
			IJ.error("Enlarge", "This command requires an area selection");
			return;
		}
		double n = showDialog(imp, defaultDistance);
		if (n==Double.NaN)
			return;
		if (n>255) {
			IJ.error("Enlarge", "Cannot enlarge by more than 255 pixels"); 
			return;
		}
		Roi roi2 = enlarge(roi, n);
		if (roi2!=null) {
			imp.setRoi(roi2);
			Roi.previousRoi = roi;
			defaultDistance = n;
		}
	}
	
	public double showDialog(ImagePlus imp, double pixels) {
		Calibration cal = imp.getCalibration();
		boolean scaled = cal.scaled();
		boolean usePixels = false;
		double n = pixels*cal.pixelWidth;
		int decimalPlaces = 0;
		if (Math.floor(n)!=n)
			decimalPlaces = 2;
		GenericDialog gd = new GenericDialog("Enlarge Selection");
		gd.addNumericField("Enlarge by", n, decimalPlaces, 4, cal.getUnits());
		if (scaled) {
			gd.setInsets(0, 20, 0);
			gd.addCheckbox("Pixel units", usePixels);
		}
		gd.setInsets(10, 0, 0);
		gd.addMessage("Enter negative number to shrink", null, Color.darkGray);
		gd.showDialog();
		if (gd.wasCanceled())
			return Double.NaN;
		n = gd.getNextNumber();
		if (scaled)
			usePixels = gd.getNextBoolean();
		pixels = usePixels?n:n/cal.pixelWidth;
		return pixels;
	}
	
	public static Roi enlarge(Roi roi, double pixels) {
		if (pixels==0)
			return roi;
		int type = roi.getType();
		int n = (int)Math.round(pixels);
		if (type==Roi.RECTANGLE || type==Roi.OVAL)
			return enlargeRectOrOval(roi, n);
		if (n>255)
			n = 255;
		if (n<0)
			return shrink(roi, -n);
		Rectangle bounds = roi.getBounds();
		int width = bounds.width;
		int height = bounds.height;
		width += 2*n +2;
		height += 2*n +2;
		ImageProcessor ip = new ByteProcessor(width, height);
		ip.invert();
		roi.setLocation(n+1, n+1);
		ip.setColor(0);
		ip.fill(roi);
		roi.setLocation(bounds.x, bounds.y);
		boolean bb = Prefs.blackBackground;
		Prefs.blackBackground = true;
		new EDM().toEDM(ip);
		//new ImagePlus("ip", ip).show();
		Prefs.blackBackground = bb;
		ip.setThreshold(0, n, ImageProcessor.NO_LUT_UPDATE);
		Roi roi2 = (new ThresholdToSelection()).convert(ip);
		if (roi2==null)
			return roi;
		roi2.setLocation(bounds.x-n, bounds.y-n);
		roi2.setStrokeColor(roi.getStrokeColor());
		if (roi.getStroke()!=null)
			roi2.setStroke(roi.getStroke());
		return roi2;
	}
	
	private static Roi enlargeRectOrOval(Roi roi, int n) {
		Rectangle bounds = roi.getBounds();
		bounds.x -= n;
		bounds.y -= n;
		bounds.width += 2*n;
		bounds.height += 2*n;
		if (bounds.width<=0 || bounds.height<=0)
			return roi;
		if (roi.getType()==Roi.RECTANGLE)
			return new Roi(bounds.x, bounds.y, bounds.width, bounds.height);
		else
			return new OvalRoi(bounds.x, bounds.y, bounds.width, bounds.height);
	}
   
	private static Roi shrink(Roi roi, int n) {
		Rectangle bounds = roi.getBounds();
		int width = bounds.width + 2;
		int height = bounds.height + 2;
		ImageProcessor ip = new ByteProcessor(width, height);
		roi.setLocation(1, 1);
		ip.setColor(255);
		ip.fill(roi);
		roi.setLocation(bounds.x, bounds.y);
		boolean bb = Prefs.blackBackground;
		Prefs.blackBackground = true;
		new EDM().toEDM(ip);
		Prefs.blackBackground = bb;
		ip.setThreshold(n+1, 255, ImageProcessor.NO_LUT_UPDATE);
		Roi roi2 = (new ThresholdToSelection()).convert(ip);
		if (roi2==null)
			return roi;
		Rectangle bounds2 = roi2.getBounds();
		if (bounds2.width<=0 && bounds2.height<=0)
			return roi;
		roi2.setLocation(bounds.x+bounds2.x-1, bounds.y+bounds2.y-1);
		return roi2;
	}

}