package ij.plugin.filter;
import ij.*;
import ij.gui.*;
import ij.process.*;
import ij.measure.*;
import ij.util.Tools;
import ij.io.FileOpener;
import ij.plugin.frame.Recorder;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Rectangle2D;
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 = 0.0;
double aspectRatio = 1.0;
String unit = "pixel";
boolean global1 = imp.getGlobalCalibration()!=null;
boolean global2;
Calibration cal = imp.getCalibration();
Calibration calOrig = cal.copy();
boolean isCalibrated = cal.scaled();
String length = "0.00";
String scale = "<no scale>";
int digits = 2;
Roi roi = imp.getRoi();
if (roi!=null) {
if (roi instanceof Line) {
measured = ((Line)roi).getRawLength();
length = IJ.d2s(measured, 2);
} else if (roi.getType()==Roi.RECTANGLE) {
Rectangle2D r = roi.getFloatBounds();
measured = Math.max(r.getWidth(),r.getHeight());
length = IJ.d2s(measured, 2);
}
}
if (isCalibrated) {
if (measured!=0.0)
known = measured*cal.pixelWidth;
else {
measured = 1.0/cal.pixelWidth;
known = 1.0;
}
double dscale = measured/known;
digits = Tools.getDecimalPlaces(dscale);
unit = cal.getUnit();
scale = IJ.d2s(dscale, digits)+" pixels/"+unit;
aspectRatio = cal.pixelHeight/cal.pixelWidth;
}
digits = Tools.getDecimalPlaces(measured);
int asDigits = aspectRatio==1.0?1:3;
SetScaleDialog gd = new SetScaleDialog("Set Scale", scale, length);
gd.addNumericField("Distance in pixels:", measured, digits, 8, null);
gd.addNumericField("Known distance:", known, 2, 8, null);
gd.addNumericField("Pixel aspect ratio:", aspectRatio, asDigits, 8, null);
gd.addStringField("Unit of length:", unit);
gd.addPanel(makeButtonPanel(gd), GridBagConstraints.EAST, new Insets(5, 0, 0, 0));
gd.setInsets(0, 30, 0);
gd.addCheckbox("Global", global1);
gd.setInsets(10, 0, 0);
gd.addMessage("Scale: "+"12345.789 pixels per centimeter");
gd.addHelp(IJ.URL+"/docs/menus/analyze.html#scale");
gd.showDialog();
if (gd.wasCanceled())
return;
measured = gd.getNextNumber();
known = gd.getNextNumber();
if (aspectRatio==1.0)
gd.setSmartRecording(true);
aspectRatio = gd.getNextNumber();
gd.setSmartRecording(false);
unit = gd.getNextString();
if (unit.equals("A"))
unit = ""+IJ.angstromSymbol;
global2 = gd.getNextBoolean();
if (measured==known && unit.equals("unit"))
unit = "pixel";
if (measured<=0.0 || known<=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 {
if (gd.scaleChanged || IJ.macroRunning()) {
cal.pixelWidth = known/measured;
if (cal.pixelDepth==1.0)
cal.pixelDepth = cal.pixelWidth;
}
if (aspectRatio!=0.0)
cal.pixelHeight = cal.pixelWidth*aspectRatio;
else
cal.pixelHeight = cal.pixelWidth;
cal.setUnit(unit);
}
if (!cal.equals(calOrig)) {
imp.setCalibration(cal);
imp.changes = true;
}
imp.setGlobalCalibration(global2?cal:null);
if (global2 || global2!=global1)
WindowManager.repaintImageWindows();
else
imp.repaintWindow();
if (global2 && global2!=global1)
FileOpener.setShowConflictMessage(true);
}
Panel makeButtonPanel(SetScaleDialog gd) {
Panel panel = new Panel();
panel.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
gd.unscaleButton = new Button("Click to Remove Scale");
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;
String length;
boolean scaleChanged;
public SetScaleDialog(String title, String scale, String length) {
super(title);
initialScale = scale;
this.length = length;
}
protected void setup() {
initialScale += " ";
setScale(initialScale);
}
public void textValueChanged(TextEvent e) {
Object source = e.getSource();
if (source==numberField.elementAt(0) || source==numberField.elementAt(1))
scaleChanged = true;
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 noUnit = unit.startsWith("pixel")||unit.startsWith("Pixel")||unit.equals("");
if (known>0.0 && noUnit && e.getSource()==numberField.elementAt(1)) {
unit = "unit";
((TextField)stringField.elementAt(0)).setText(unit);
}
boolean noScale = measured<=0||known<=0||noUnit;
if (noScale)
theScale = NO_SCALE;
else {
double scale = measured/known;
int digits = Tools.getDecimalPlaces(scale);
theScale = IJ.d2s(scale,digits)+(scale==1.0?" pixel/":" pixels/")+unit;
}
setScale(theScale);
}
public void actionPerformed(ActionEvent e) {
super.actionPerformed(e);
if (e.getSource()==unscaleButton) {
((TextField)numberField.elementAt(0)).setText(length);
((TextField)numberField.elementAt(1)).setText("0.00");
((TextField)numberField.elementAt(2)).setText("1.0");
((TextField)stringField.elementAt(0)).setText("pixel");
setScale(NO_SCALE);
scaleChanged = true;
if (IJ.isMacOSX() && false){
setVisible(false);
setVisible(true);
}
if (Recorder.record) {
Recorder.disableCommandRecording();
if (Recorder.scriptMode())
Recorder.recordCall("imp.removeScale();");
else
Recorder.record("Image.removeScale");
}
}
}
void setScale(String theScale) {
((Label)theLabel).setText("Scale: "+theScale);
}
}