package ij.plugin;
import ij.*;
import ij.gui.*;
import ij.measure.Calibration;
import java.awt.AWTEvent;
import java.awt.geom.Rectangle2D;
/**
* The plugin implements the Image/Adjust/Coordinates command. It allows
* the user to set the corner coordinates of the selection bounds or the full image.
* This modifies the image scale (pixelWidth, pixelHeight) and the xOrigin, yOrigin.
* If a single point is selected, the coordinates of the point can be specified, which only
* sets the xOrigin and yOrigin.
* The units for x and y can be also selected.
* 2016-08-30 Michael Schmid
*/
public class Coordinates implements PlugIn, DialogListener {
private static final String help = ""
+"
Image>Adjust>Coordinates
"
+""
+"This command allows the user to set the corner coordinates of
the selection bounds "
+"or the full image. This modifies the image
scale (pixelWidth, pixelHeight) and xOrigin and yOrigin. "
+"If a
single point is selected, the coordinates of the point can be
specified, which only "
+"sets xOrigin and yOrigin. The units for X
and Y can be also selected.
"
+"";
private final static String SAME_AS_X = "";
private final static int IMAGE = 0, ROI_BOUNDS = 1, POINT = 2; //mode: coordinates of what to specify
private int mode = IMAGE;
public void run(String arg) {
ImagePlus imp = IJ.getImage();
int imageHeight = imp.getHeight();
Calibration cal = imp.getCalibration();
Roi roi = imp.getRoi();
Rectangle2D.Double bounds = null;
if (roi != null) {
bounds = roi.getFloatBounds();
if (bounds.width==0 && bounds.height==0)
mode = POINT;
else
mode = ROI_BOUNDS;
} else { //no Roi, use image bounds
bounds = new Rectangle2D.Double(0, 0, imp.getWidth(), imp.getHeight());
}
String title = (mode==IMAGE ? "Image" : "Selection") +" Coordinates";
if (mode == POINT)
title = "Point Coordinates";
GenericDialog gd = new GenericDialog(title);
if (mode == POINT) {
gd.addNumericField("X:", cal.getX(bounds.x), 2, 8, "");
gd.addNumericField("Y:", cal.getY(bounds.y, imageHeight), 2, 8, "");
} else {
gd.addNumericField("Left:", cal.getX(bounds.x), 2, 8, "");
gd.addNumericField("Right:", cal.getX(bounds.x+bounds.width), 2, 8, "");
gd.addNumericField("Top:", cal.getY(bounds.y, imageHeight), 2, 8, "");
gd.addNumericField("Bottom:", cal.getY(bounds.y+bounds.height, imageHeight), 2, 8, "");
}
String xUnit = cal.getUnit();
String yUnit = cal.getYUnit();
gd.addStringField("X_unit:", xUnit, 18);
gd.addStringField("Y_unit:", yUnit.equals(xUnit) ? SAME_AS_X : yUnit, 18);
gd.addHelp(help);
gd.addDialogListener(this);
gd.showDialog();
if (gd.wasCanceled())
return;
if (mode == POINT) {
double x = gd.getNextNumber();
double y = gd.getNextNumber();
if (gd.invalidNumber()) {
IJ.error("Invalid number");
return;
}
cal.xOrigin = coordinate2offset(x, bounds.x, cal.pixelWidth);
cal.yOrigin = coordinate2offset(y, bounds.y, cal.getInvertY() ? -cal.pixelHeight : cal.pixelHeight);
} else {
double xl = gd.getNextNumber();
double xr = gd.getNextNumber();
double yt = gd.getNextNumber();
double yb = gd.getNextNumber();
if (gd.invalidNumber()) {
IJ.error("Invalid number");
return;
}
cal.pixelWidth = (xr-xl)/bounds.width;
cal.pixelHeight = (yb-yt)/bounds.height;
cal.xOrigin = coordinate2offset(xl, bounds.x, cal.pixelWidth);
cal.yOrigin = coordinate2offset(yt, bounds.y, cal.pixelHeight);
cal.setInvertY(cal.pixelHeight < 0);
if (cal.pixelHeight < 0)
cal.pixelHeight = -cal.pixelHeight;
}
cal.setXUnit(gd.getNextString());
yUnit = gd.getNextString();
cal.setYUnit((yUnit.equals("") || yUnit.equals(SAME_AS_X)) ? null : yUnit);
ImageWindow win = imp.getWindow();
imp.repaintWindow();
}
// In interactive mode, disable 'ok' in case of input errors (bad numbers, zero range or inverted x)
public boolean dialogItemChanged(GenericDialog gd, AWTEvent e) {
if (mode == POINT) {
gd.getNextNumber();
gd.getNextNumber();
return (!gd.invalidNumber());
} else {
double xl = gd.getNextNumber();
double xr = gd.getNextNumber();
double yt = gd.getNextNumber();
double yb = gd.getNextNumber();
return (!gd.invalidNumber() && xr>xl && yt!=yb);
}
}
// Calculates pixel offset from scaled coordinates of a point with given pixel position
private double coordinate2offset(double coordinate, double pixelPos, double pixelSize) {
return pixelPos - coordinate/pixelSize;
}
}