|
Scaler |
|
package ij.plugin; import ij.*; import ij.gui.*; import ij.process.*; import ij.measure.*; import ij.util.Tools; import java.awt.*; import java.awt.event.*; import java.util.*; /** This plugin implements the Edit/Scale command. */ public class Scaler implements PlugIn, TextListener, FocusListener { private ImagePlus imp; private static String xstr = "0.5"; private static String ystr = "0.5"; private static int newWidth, newHeight; private static boolean newWindow = true; private static boolean interpolate = true; private static boolean fillWithBackground; private static boolean processStack = true; private double xscale; private double yscale; private String title = "Untitled"; private Vector fields; private double bgValue; private boolean constainAspectRatio = true; private TextField xField, yField, widthField, heightField; private Rectangle r; private Object fieldWithFocus; public void run(String arg) { imp = IJ.getImage(); Roi roi = imp.getRoi(); if (roi!=null && !roi.isArea()) imp.killRoi(); // ignore any line selection ImageProcessor ip = imp.getProcessor(); if (!showDialog(ip)) return; if (ip.getWidth()>1 && ip.getHeight()>1) ip.setInterpolate(interpolate); else ip.setInterpolate(false); ip.setBackgroundValue(bgValue); imp.startTiming(); try { if (newWindow && imp.getStackSize()>1 && processStack) createNewStack(imp, ip); else scale(ip); } catch(OutOfMemoryError o) { IJ.outOfMemory("Scale"); } IJ.showProgress(1.0); } void createNewStack(ImagePlus imp, ImageProcessor ip) { Rectangle r = ip.getRoi(); boolean crop = r.width!=imp.getWidth() || r.height!=imp.getHeight(); int nSlices = imp.getStackSize(); ImageStack stack1 = imp.getStack(); ImageStack stack2 = new ImageStack(newWidth, newHeight); ImageProcessor ip1, ip2; boolean interp = interpolate; if (imp.getWidth()==1 || imp.getHeight()==1) interp = false; for (int i=1; i<=nSlices; i++) { IJ.showStatus("Scale: " + i + "/" + nSlices); ip1 = stack1.getProcessor(i); String label = stack1.getSliceLabel(i); if (crop) { ip1.setRoi(r); ip1 = ip1.crop(); } ip1.setInterpolate(interp); ip2 = ip1.resize(newWidth, newHeight); if (ip2!=null) stack2.addSlice(label, ip2); IJ.showProgress(i, nSlices); } ImagePlus imp2 = imp.createImagePlus(); imp2.setStack(title, stack2); Calibration cal = imp2.getCalibration(); if (cal.scaled()) { cal.pixelWidth *= 1.0/xscale; cal.pixelHeight *= 1.0/yscale; } int[] dim = imp.getDimensions(); imp2.setDimensions(dim[2], dim[3], dim[4]); IJ.showProgress(1.0); imp2.show(); imp2.changes = true; } void scale(ImageProcessor ip) { if (newWindow) { Rectangle r = ip.getRoi(); ImagePlus imp2 = imp.createImagePlus(); imp2.setProcessor(title, ip.resize(newWidth, newHeight)); Calibration cal = imp2.getCalibration(); if (cal.scaled()) { cal.pixelWidth *= 1.0/xscale; cal.pixelHeight *= 1.0/yscale; } imp2.show(); imp.trimProcessor(); imp2.trimProcessor(); imp2.changes = true; } else { if (processStack && imp.getStackSize()>1) { Undo.reset(); StackProcessor sp = new StackProcessor(imp.getStack(), ip); sp.scale(xscale, yscale, bgValue); } else { ip.snapshot(); Undo.setup(Undo.FILTER, imp); ip.setSnapshotCopyMode(true); ip.scale(xscale, yscale); ip.setSnapshotCopyMode(false); } imp.killRoi(); imp.updateAndDraw(); imp.changes = true; } } boolean showDialog(ImageProcessor ip) { int bitDepth = imp.getBitDepth(); boolean isStack = imp.getStackSize()>1; r = ip.getRoi(); int width = newWidth; if (width==0) width = r.width; int height = (int)((double)width*r.height/r.width); xscale = Tools.parseDouble(xstr, 0.0); yscale = Tools.parseDouble(ystr, 0.0); if (xscale!=0.0 && yscale!=0.0) { width = (int)(r.width*xscale); height = (int)(r.height*yscale); } else { xstr = "-"; ystr = "-"; } GenericDialog gd = new GenericDialog("Scale"); gd.addStringField("X Scale (0.05-25):", xstr); gd.addStringField("Y Scale (0.05-25):", ystr); gd.setInsets(5, 0, 5); gd.addStringField("Width (pixels):", ""+width); gd.addStringField("Height (pixels):", ""+height); fields = gd.getStringFields(); for (int i=0; i<3; i++) { ((TextField)fields.elementAt(i)).addTextListener(this); ((TextField)fields.elementAt(i)).addFocusListener(this); } xField = (TextField)fields.elementAt(0); yField = (TextField)fields.elementAt(1); widthField = (TextField)fields.elementAt(2); heightField = (TextField)fields.elementAt(3); fieldWithFocus = xField; gd.addCheckbox("Interpolate", interpolate); if (bitDepth==8 || bitDepth==24) gd.addCheckbox("Fill with Background Color", fillWithBackground); if (isStack) gd.addCheckbox("Process Entire Stack", processStack); gd.addCheckbox("Create New Window", newWindow); title = WindowManager.getUniqueName(imp.getTitle()); gd.setInsets(10, 0, 0); gd.addStringField("Title:", title, 12); gd.showDialog(); if (gd.wasCanceled()) return false; xstr = gd.getNextString(); ystr = gd.getNextString(); xscale = Tools.parseDouble(xstr, 0.0); yscale = Tools.parseDouble(ystr, 0.0); String wstr = gd.getNextString(); newWidth = (int)Tools.parseDouble(wstr, 0); newHeight = (int)Tools.parseDouble(gd.getNextString(), 0); if (newHeight!=0 && (wstr.equals("-") || wstr.equals("0"))) newWidth= (int)(newHeight*(double)r.width/r.height); if (newWidth==0 || newHeight==0) { IJ.error("Invalid width or height entered"); return false; } if (xscale>25.0) xscale = 25.0; if (yscale>25.0) yscale = 25.0; if (xscale>0.0 && yscale>0.0) { newWidth = (int)(r.width*xscale); newHeight = (int)(r.height*yscale); } interpolate = gd.getNextBoolean(); if (bitDepth==8 || bitDepth==24) fillWithBackground = gd.getNextBoolean(); if (isStack) processStack = gd.getNextBoolean(); newWindow = gd.getNextBoolean(); if (!newWindow && xscale==0.0) { xscale = (double)newWidth/r.width; yscale = (double)newHeight/r.height; } title = gd.getNextString(); if (fillWithBackground) { Color bgc = Toolbar.getBackgroundColor(); if (bitDepth==8) bgValue = ip.getBestIndex(bgc); else if (bitDepth==24) bgValue = bgc.getRGB(); } else { if (bitDepth==8) bgValue = ip.isInvertedLut()?0.0:255.0; // white else if (bitDepth==24) bgValue = 0xffffffff; // white } return true; } public void textValueChanged(TextEvent e) { Object source = e.getSource(); double newXScale = xscale; double newYScale = yscale; if (source==xField && fieldWithFocus==xField) { String newXText = xField.getText(); newXScale = Tools.parseDouble(newXText,0); if (newXScale==0) return; if (newXScale!=xscale) { int newWidth = (int)(newXScale*r.width); widthField.setText(""+newWidth); if (constainAspectRatio) { yField.setText(newXText); int newHeight = (int)(newXScale*r.height); heightField.setText(""+newHeight); } } } else if (source==yField && fieldWithFocus==yField) { String newYText = yField.getText(); newYScale = Tools.parseDouble(newYText,0); if (newYScale==0) return; if (newYScale!=yscale) { int newHeight = (int)(newYScale*r.height); heightField.setText(""+newHeight); } } else if (source==widthField && fieldWithFocus==widthField) { int newWidth = (int)Tools.parseDouble(widthField.getText(), 0.0); if (newWidth!=0) { int newHeight = (int)(newWidth*(double)r.height/r.width); heightField.setText(""+newHeight); xField.setText("-"); yField.setText("-"); newXScale = 0.0; newYScale = 0.0; } } xscale = newXScale; yscale = newYScale; } public void focusGained(FocusEvent e) { fieldWithFocus = e.getSource(); if (fieldWithFocus==widthField) constainAspectRatio = true; else if (fieldWithFocus==yField) constainAspectRatio = false; } public void focusLost(FocusEvent e) {} }
|
Scaler |
|