package ij.plugin.filter;
import java.awt.*;
import java.util.*;
import ij.*;
import ij.gui.*;
import ij.process.*;
import ij.text.*;
import ij.measure.*;
import ij.io.*;
import ij.util.Tools;
/** This plugin implements the Image/Show Info command. */
public class Info implements PlugInFilter {
private ImagePlus imp;
public int setup(String arg, ImagePlus imp) {
this.imp = imp;
return DOES_ALL+NO_CHANGES;
}
public void run(ImageProcessor ip) {
String info = getImageInfo(imp, ip);
if (info.indexOf("----")>0)
showInfo(info, 450, 500);
else
showInfo(info, 300, 300);
}
public String getImageInfo(ImagePlus imp, ImageProcessor ip) {
String infoProperty = null;
if (imp.getStackSize()>1) {
ImageStack stack = imp.getStack();
String label = stack.getSliceLabel(imp.getCurrentSlice());
if (label!=null && label.indexOf('\n')>0)
infoProperty = label;
}
if (infoProperty==null)
infoProperty = (String)imp.getProperty("Info");
String info = getInfo(imp, ip);
if (infoProperty!=null)
return infoProperty + "\n------------------------\n" + info;
else
return info;
}
String getInfo(ImagePlus imp, ImageProcessor ip) {
String s = new String("\n");
s += "Title: " + imp.getTitle() + "\n";
Calibration cal = imp.getCalibration();
int stackSize = imp.getStackSize();
int channels = imp.getNChannels();
int slices = imp.getNSlices();
int frames = imp.getNFrames();
int digits = imp.getBitDepth()==32?4:0;
if (cal.scaled()) {
String unit = cal.getUnit();
String units = cal.getUnits();
s += "Width: "+IJ.d2s(imp.getWidth()*cal.pixelWidth,2)+" " + units+" ("+imp.getWidth()+")\n";
s += "Height: "+IJ.d2s(imp.getHeight()*cal.pixelHeight,2)+" " + units+" ("+imp.getHeight()+")\n";
if (slices>1)
s += "Depth: "+IJ.d2s(slices*cal.pixelDepth,2)+" " + units+" ("+slices+")\n";
double xResolution = 1.0/cal.pixelWidth;
double yResolution = 1.0/cal.pixelHeight;
int places = Tools.getDecimalPlaces(xResolution, yResolution);
if (xResolution==yResolution)
s += "Resolution: "+IJ.d2s(xResolution,places) + " pixels per "+unit+"\n";
else {
s += "X Resolution: "+IJ.d2s(xResolution,places) + " pixels per "+unit+"\n";
s += "Y Resolution: "+IJ.d2s(yResolution,places) + " pixels per "+unit+"\n";
}
} else {
s += "Width: " + imp.getWidth() + " pixels\n";
s += "Height: " + imp.getHeight() + " pixels\n";
if (stackSize>1)
s += "Depth: " + slices + " pixels\n";
}
if (stackSize>1)
s += "Voxel size: "+d2s(cal.pixelWidth)+"x"+d2s(cal.pixelHeight)+"x"+d2s(cal.pixelDepth)+" "+cal.getUnit()+"\n";
else
s += "Pixel size: "+d2s(cal.pixelWidth)+"x"+d2s(cal.pixelHeight)+" "+cal.getUnit()+"\n";
s += "ID: "+imp.getID()+"\n";
String zOrigin = stackSize>1||cal.zOrigin!=0.0?","+d2s(cal.zOrigin):"";
s += "Coordinate origin: " + d2s(cal.xOrigin)+","+d2s(cal.yOrigin)+zOrigin+"\n";
int type = imp.getType();
switch (type) {
case ImagePlus.GRAY8:
s += "Bits per pixel: 8 ";
String lut = "LUT";
if (imp.getProcessor().isColorLut())
lut = "color " + lut;
else
lut = "grayscale " + lut;
if (imp.isInvertedLut())
lut = "inverting " + lut;
s += "(" + lut + ")\n";
s += "Display range: "+(int)ip.getMin()+"-"+(int)ip.getMax()+"\n";
break;
case ImagePlus.GRAY16: case ImagePlus.GRAY32:
if (type==ImagePlus.GRAY16) {
String sign = cal.isSigned16Bit()?"signed":"unsigned";
s += "Bits per pixel: 16 ("+sign+")\n";
} else
s += "Bits per pixel: 32 (float)\n";
s += "Display range: ";
double min = ip.getMin();
double max = ip.getMax();
if (cal.calibrated()) {
min = cal.getCValue((int)min);
max = cal.getCValue((int)max);
}
s += IJ.d2s(min,digits) + " - " + IJ.d2s(max,digits) + "\n";
break;
case ImagePlus.COLOR_256:
s += "Bits per pixel: 8 (color LUT)\n";
break;
case ImagePlus.COLOR_RGB:
s += "Bits per pixel: 32 (RGB)\n";
break;
}
double interval = cal.frameInterval;
double fps = cal.fps;
if (stackSize>1) {
ImageStack stack = imp.getStack();
int slice = imp.getCurrentSlice();
String number = slice + "/" + stackSize;
String label = stack.getShortSliceLabel(slice);
if (label!=null && label.length()>0)
label = " (" + label + ")";
else
label = "";
if (interval>0.0 || fps!=0.0) {
s += "Frame: " + number + label + "\n";
if (fps!=0.0) {
String sRate = Math.abs(fps-Math.round(fps))<0.00001?IJ.d2s(fps,0):IJ.d2s(fps,5);
s += "Frame rate: " + sRate + " fps\n";
}
if (interval!=0.0)
s += "Frame interval: " + ((int)interval==interval?IJ.d2s(interval,0):IJ.d2s(interval,5)) + " " + cal.getTimeUnit() + "\n";
} else
s += "Image: " + number + label + "\n";
if (imp.isHyperStack()) {
if (channels>1)
s += " Channel: " + imp.getChannel() + "/" + channels + "\n";
if (slices>1)
s += " Slice: " + imp.getSlice() + "/" + slices + "\n";
if (frames>1)
s += " Frame: " + imp.getFrame() + "/" + frames + "\n";
}
if (imp.isComposite()) {
if (!imp.isHyperStack() && channels>1)
s += " Channels: " + channels + "\n";
String mode = ((CompositeImage)imp).getModeAsString();
s += " Composite mode: \"" + mode + "\"\n";
}
}
if (ip.getMinThreshold()==ImageProcessor.NO_THRESHOLD)
s += "No Threshold\n";
else {
double lower = ip.getMinThreshold();
double upper = ip.getMaxThreshold();
int dp = digits;
if (cal.calibrated()) {
lower = cal.getCValue((int)lower);
upper = cal.getCValue((int)upper);
dp = cal.isSigned16Bit()?0:4;
}
s += "Threshold: "+IJ.d2s(lower,dp)+"-"+IJ.d2s(upper,dp)+"\n";
}
ImageCanvas ic = imp.getCanvas();
double mag = ic!=null?ic.getMagnification():1.0;
if (mag!=1.0)
s += "Magnification: " + mag + "\n";
if (cal.calibrated()) {
s += " \n";
int curveFit = cal.getFunction();
s += "Calibration Function: ";
if (curveFit==Calibration.UNCALIBRATED_OD)
s += "Uncalibrated OD\n";
else if (curveFit==Calibration.CUSTOM)
s += "Custom lookup table\n";
else
s += CurveFitter.fList[curveFit]+"\n";
double[] c = cal.getCoefficients();
if (c!=null) {
s += " a: "+IJ.d2s(c[0],6)+"\n";
s += " b: "+IJ.d2s(c[1],6)+"\n";
if (c.length>=3)
s += " c: "+IJ.d2s(c[2],6)+"\n";
if (c.length>=4)
s += " c: "+IJ.d2s(c[3],6)+"\n";
if (c.length>=5)
s += " c: "+IJ.d2s(c[4],6)+"\n";
}
s += " Unit: \""+cal.getValueUnit()+"\"\n";
} else
s += "Uncalibrated\n";
FileInfo fi = imp.getOriginalFileInfo();
if (fi!=null) {
if (fi.url!=null && !fi.url.equals(""))
s += "URL: " + fi.url + "\n";
else if (fi.directory!=null && fi.fileName!=null)
s += "Path: " + fi.directory + fi.fileName + "\n";
}
Roi roi = imp.getRoi();
if (roi == null) {
if (cal.calibrated())
s += " \n";
s += "No Selection\n";
} else if (roi instanceof EllipseRoi) {
s += "\nElliptical Selection\n";
double[] p = ((EllipseRoi)roi).getParams();
double dx = p[2] - p[0];
double dy = p[3] - p[1];
double major = Math.sqrt(dx*dx+dy*dy);
s += " Major: " + IJ.d2s(major,2) + "\n";
s += " Minor: " + IJ.d2s(major*p[4],2) + "\n";
s += " X1: " + IJ.d2s(p[0],2) + "\n";
s += " Y1: " + IJ.d2s(p[1],2) + "\n";
s += " X2: " + IJ.d2s(p[2],2) + "\n";
s += " Y2: " + IJ.d2s(p[3],2) + "\n";
s += " Aspect ratio: " + IJ.d2s(p[4],2) + "\n";
} else {
s += " \n";
s += roi.getTypeAsString()+" Selection";
String points = null;
if (roi instanceof PointRoi) {
int npoints = ((PolygonRoi)roi).getNCoordinates();
String suffix = npoints>1?"s)":")";
points = " (" + npoints + " point" + suffix;
}
String name = roi.getName();
if (name!=null) {
s += " (\"" + name + "\")";
if (points!=null) s += "\n " + points;
} else if (points!=null)
s += points;
s += "\n";
Rectangle r = roi.getBounds();
if (roi instanceof Line) {
Line line = (Line)roi;
s += " X1: " + IJ.d2s(line.x1d*cal.pixelWidth) + "\n";
s += " Y1: " + IJ.d2s(yy(line.y1d,imp)*cal.pixelHeight) + "\n";
s += " X2: " + IJ.d2s(line.x2d*cal.pixelWidth) + "\n";
s += " Y2: " + IJ.d2s(yy(line.y2d,imp)*cal.pixelHeight) + "\n";
} else if (cal.scaled()) {
s += " X: " + IJ.d2s(r.x*cal.pixelWidth) + " (" + r.x + ")\n";
s += " Y: " + IJ.d2s(yy(r.y,imp)*cal.pixelHeight) + " (" + r.y + ")\n";
s += " Width: " + IJ.d2s(r.width*cal.pixelWidth) + " (" + r.width + ")\n";
s += " Height: " + IJ.d2s(r.height*cal.pixelHeight) + " (" + r.height + ")\n";
} else {
s += " X: " + r.x + "\n";
s += " Y: " + yy(r.y,imp) + "\n";
s += " Width: " + r.width + "\n";
s += " Height: " + r.height + "\n";
}
}
return s;
}
String d2s(double n) {
return n==(int)n?Integer.toString((int)n):IJ.d2s(n);
}
// returns a Y coordinate based on the "Invert Y Coodinates" flag
int yy(int y, ImagePlus imp) {
return Analyzer.updateY(y, imp.getHeight());
}
// returns a Y coordinate based on the "Invert Y Coodinates" flag
double yy(double y, ImagePlus imp) {
return Analyzer.updateY(y, imp.getHeight());
}
void showInfo(String info, int width, int height) {
new TextWindow("Info for "+imp.getTitle(), info, width, height);
}
}