| ScaleDialog |

    package ij.plugin.filter;
    import ij.*;
    import ij.gui.*;
    import ij.process.*;
    import ij.measure.*;
    import ij.util.Tools;
    import java.awt.*;
    import java.awt.event.*;

    /** Implements the Analyze/Set Scale command. */
    public class ScaleDialog implements PlugInFilter {

        private ImagePlus imp;

        public int setup(String arg, ImagePlus imp) {
            this.imp = imp;
            IJ.register(ScaleDialog.class);
            return DOES_ALL+NO_CHANGES;
        }

        public void run(ImageProcessor ip) {
            double measured = 0.0;
            double known = 1.0;
            double aspectRatio = 1.0;
            String unit = "cm";
            boolean global1 = imp.getGlobalCalibration()!=null;
            boolean global2;
            Calibration cal = imp.getCalibration();
            Calibration calOrig = cal.copy();
            boolean isCalibrated = cal.scaled();

            String scale = "<no scale>";
            int digits = 2;
            if (isCalibrated) {
                measured = 1.0/cal.pixelWidth;
                digits = Tools.getDecimalPlaces(measured, measured);
                known = 1.0;
                aspectRatio = cal.pixelHeight/cal.pixelWidth;
                unit = cal.getUnit();
                scale = IJ.d2s(measured,digits)+" pixels/"+unit;
            }
            Roi roi = imp.getRoi();
            if (roi!=null && (roi instanceof Line)) {
                measured = ((Line)roi).getRawLength();
                known = 0.0;
            }

            SetScaleDialog gd = new SetScaleDialog("Set Scale", scale);
            gd.addNumericField("Distance in Pixels:", measured, digits, 8, null);
            gd.addNumericField("Known Distance:", known, 2, 8, null);
            gd.addNumericField("Pixel Aspect Ratio:", aspectRatio, 1, 8, null);
            gd.addStringField("Unit of Length:", unit);
            gd.addMessage("Scale: "+"12345.789 pixels per centimeter");
            gd.addCheckbox("Global", global1);
            gd.addPanel(makeButtonPanel(gd), GridBagConstraints.EAST, new Insets(5, 0, 0, 25));
            gd.showDialog();
            if (gd.wasCanceled())
                return;
            measured = gd.getNextNumber();
            known = gd.getNextNumber();
            aspectRatio = gd.getNextNumber();
            unit = gd.getNextString();
            if (unit.equals("um"))
                unit = IJ.micronSymbol+"m";
            else if (unit.equals("A"))
                unit = ""+IJ.angstromSymbol;
            global2 = gd.getNextBoolean();
            if (measured!=0.0 && known==0.0) {
                imp.setGlobalCalibration(global2?cal:null);
                return;
            }
            if (measured<=0.0 || unit.startsWith("pixel") || unit.startsWith("Pixel") || unit.equals("")) {
                cal.pixelWidth = 1.0;
                cal.pixelHeight = 1.0;
                cal.pixelDepth = 1.0;
                cal.setUnit("pixel");
            } else {
                cal.pixelWidth = known/measured;
                if (aspectRatio!=0.0)
                    cal.pixelHeight = cal.pixelWidth*aspectRatio;
                else
                    cal.pixelHeight = cal.pixelWidth;
                cal.pixelDepth = cal.pixelWidth;
                cal.setUnit(unit);
            }
            if (!cal.equals(calOrig))
                imp.setCalibration(cal);
            imp.setGlobalCalibration(global2?cal:null);
            if (global2 || global2!=global1)
                WindowManager.repaintImageWindows();
            else
                imp.repaintWindow();
        }

        /** Creates a panel containing an "Unscale" button. */
        Panel makeButtonPanel(SetScaleDialog gd) {
            Panel panel = new Panel();
            panel.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
            gd.unscaleButton = new Button("Reset");
            gd.unscaleButton.addActionListener(gd);
            panel.add(gd.unscaleButton);
            return panel;
        }

    }

    class SetScaleDialog extends GenericDialog {
        static final String NO_SCALE = "<no scale>";
        String initialScale;
        Button unscaleButton;

        public SetScaleDialog(String title, String scale) {
            super(title);
            initialScale = scale;
        }

        protected void setup() {
            if (IJ.isJava2())
                initialScale += "          ";
            setScale(initialScale);
        }

        public void textValueChanged(TextEvent e) {
            Double d = getValue(((TextField)numberField.elementAt(0)).getText());
            if (d==null)
                {setScale(NO_SCALE); return;}
            double measured = d.doubleValue();
            d = getValue(((TextField)numberField.elementAt(1)).getText());
            if (d==null)
                {setScale(NO_SCALE); return;}
            double known = d.doubleValue();
            String theScale;
            String unit = ((TextField)stringField.elementAt(0)).getText();
            boolean noScale = measured<=0||known<=0||unit.startsWith("pixel")||unit.startsWith("Pixel")||unit.equals("");
            if (noScale)
                theScale = NO_SCALE;
            else {
                double scale = measured/known;
                int digits = Tools.getDecimalPlaces(scale, scale);
                theScale = IJ.d2s(scale,digits)+" pixels/"+unit;
            }
            setScale(theScale);
        }

        public void actionPerformed(ActionEvent e) {
            super.actionPerformed(e);
            if (e.getSource()==unscaleButton) {
                ((TextField)numberField.elementAt(0)).setText("0.00");
                ((TextField)numberField.elementAt(1)).setText("1.00");
                ((TextField)numberField.elementAt(2)).setText("1.0");
                ((TextField)stringField.elementAt(0)).setText("pixel");
                setScale(NO_SCALE);
            }
        }

        void setScale(String theScale) {
            ((Label)theLabel).setText("Scale: "+theScale);
        }

    }

| ScaleDialog |