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