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;
}
}
|