package ij.plugin;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import ij.*;
import ij.gui.*;
import ij.process.*;
import ij.util.Tools;
import ij.measure.Calibration;
public class SpecifyROI implements PlugIn, DialogListener {
private static double width, height, xRoi, yRoi;
private static boolean oval;
private static boolean square;
private static boolean centered;
private static boolean scaledUnits;
private final static int WIDTH = 0, HEIGHT = 1, X_ROI = 2, Y_ROI = 3; private final static int OVAL = 0, SQUARE = 1, CENTERED = 2, SCALED_UNITS = 3; private static Rectangle prevRoi;
private static double prevPixelWidth = 1.0;
private int iSlice;
private boolean bAbort;
private ImagePlus imp;
private Vector fields, checkboxes;
private int stackSize;
public void run(String arg) {
imp = IJ.getImage();
if (imp == null) return;
stackSize = imp.getStackSize();
Roi roi = imp.getRoi();
Calibration cal = imp.getCalibration();
if (roi!=null && roi.getBounds().equals(prevRoi) && cal.pixelWidth==prevPixelWidth)
roi = null;
if (roi!=null) {
boolean rectOrOval = roi!=null && (roi.getType()==Roi.RECTANGLE||roi.getType()==Roi.OVAL);
oval = rectOrOval && (roi.getType()==Roi.OVAL); Rectangle r = roi.getBounds();
width = r.width;
height = r.height;
xRoi = r.x;
yRoi = r.y;
if (scaledUnits && cal.scaled()) {
xRoi = xRoi*cal.pixelWidth;
yRoi = yRoi*cal.pixelHeight;
width = width*cal.pixelWidth;
height = height*cal.pixelHeight;
}
if (centered) { xRoi += width/2.0;
yRoi += height/2.0;
}
} else if (!validDialogValues()) {
width = imp.getWidth()/2;
height = imp.getHeight()/2;
xRoi = width/2;
yRoi = height/2;
}
iSlice = imp.getCurrentSlice();
showDialog();
}
boolean validDialogValues() {
Calibration cal = imp.getCalibration();
double pw=cal.pixelWidth, ph=cal.pixelHeight;
if (width/pw<1 || height/ph<1)
return false;
if (xRoi/pw>imp.getWidth() || yRoi/ph>imp.getHeight())
return false;
return true;
}
void showDialog() {
Calibration cal = imp.getCalibration();
int digits = 0;
if (scaledUnits && cal.scaled())
digits = 2;
Roi roi = imp.getRoi();
if (roi==null)
drawRoi();
GenericDialog gd = new GenericDialog("Specify");
gd.addNumericField("Width:", width, digits);
gd.addNumericField("Height:", height, digits);
gd.addNumericField("X coordinate:", xRoi, digits);
gd.addNumericField("Y coordinate:", yRoi, digits);
if (stackSize>1)
gd.addNumericField("Slice:", iSlice, 0);
gd.addCheckbox("Oval", oval);
gd.addCheckbox("Constrain square/circle", square);
gd.addCheckbox("Centered",centered);
if (cal.scaled()) {
boolean unitsMatch = cal.getXUnit().equals(cal.getYUnit());
String units = unitsMatch ? cal.getUnits() : cal.getXUnit()+" x "+cal.getYUnit();
gd.addCheckbox("Scaled units ("+units+")", scaledUnits);
}
fields = gd.getNumericFields();
gd.addDialogListener(this);
gd.showDialog();
if (gd.wasCanceled()) {
if (roi==null)
imp.deleteRoi();
else imp.setRoi(roi);
}
}
void drawRoi() {
double xPxl = xRoi;
double yPxl = yRoi;
if (centered) {
xPxl -= width/2;
yPxl -= height/2;
}
double widthPxl = width;
double heightPxl = height;
Calibration cal = imp.getCalibration();
if (scaledUnits && cal.scaled()) {
xPxl /= cal.pixelWidth;
yPxl /= cal.pixelHeight;
widthPxl /= cal.pixelWidth;
heightPxl /= cal.pixelHeight;
prevPixelWidth = cal.pixelWidth;
}
Roi roi;
if (oval)
roi = new OvalRoi(xPxl, yPxl, widthPxl, heightPxl);
else
roi = new Roi(xPxl, yPxl, widthPxl, heightPxl);
imp.setRoi(roi);
prevRoi = roi.getBounds();
}
public boolean dialogItemChanged(GenericDialog gd, AWTEvent e) {
if (IJ.isMacOSX()) IJ.wait(50);
Calibration cal = imp.getCalibration();
width = gd.getNextNumber();
height = gd.getNextNumber();
xRoi = gd.getNextNumber();
yRoi = gd.getNextNumber();
if (stackSize>1)
iSlice = (int) gd.getNextNumber();
oval = gd.getNextBoolean();
square = gd.getNextBoolean();
centered = gd.getNextBoolean();
if (cal.scaled())
scaledUnits = gd.getNextBoolean();
if (gd.invalidNumber() || width<=0 || height<=0)
return false;
Vector numFields = gd.getNumericFields();
Vector checkboxes = gd.getCheckboxes();
boolean newWidth = false, newHeight = false, newXY = false;
if (e!=null && e.getSource()==checkboxes.get(SQUARE) && square) {
width = 0.5*(width+height); height = width;
newWidth = true;
newHeight = true;
}
if (e!=null && e.getSource()==checkboxes.get(CENTERED)) {
double shiftBy = centered ? 0.5 : -0.5; xRoi += shiftBy * width; yRoi += shiftBy * height;
newXY = true;
}
if (square && width!=height && e!=null) { if (e.getSource()==numFields.get(WIDTH)) {
height = width;
newHeight = true;
} else if (e.getSource()==numFields.get(HEIGHT)) {
width = height;
newWidth = true;
}
}
if (e!=null && cal.scaled() && e.getSource()==checkboxes.get(SCALED_UNITS)) {
double xFactor = scaledUnits ? cal.pixelWidth : 1./cal.pixelWidth;
double yFactor = scaledUnits ? cal.pixelHeight : 1./cal.pixelHeight;
width *= xFactor; height *= yFactor;
xRoi *= xFactor;
yRoi *= yFactor;
newWidth = true; newHeight = true; newXY = true;
}
int digits = (scaledUnits || (int)width!=width) ? 2 : 0;
if (newWidth)
((TextField)(numFields.get(WIDTH))).setText(IJ.d2s(width, digits));
if (newHeight)
((TextField)(numFields.get(HEIGHT))).setText(IJ.d2s(height, digits));
digits = (scaledUnits || (int)xRoi!=xRoi || (int)yRoi!=yRoi) ? 2 : 0;
if (newXY) {
((TextField)(numFields.get(X_ROI))).setText(IJ.d2s(xRoi, digits));
((TextField)(numFields.get(Y_ROI))).setText(IJ.d2s(yRoi, digits));
}
if (stackSize>1 && iSlice>0 && iSlice<=stackSize)
imp.setSlice(iSlice);
if (!newWidth && !newHeight && !newXY) drawRoi();
return true;
}
}