package ij.plugin;
import ij.*;
import ij.process.*;
import ij.gui.*;
import ij.measure.Calibration;
import java.awt.*;
import java.awt.image.*;
/** This plugin implements the Image/Transform/Bin command.
* It reduces the size of an image or stack by binning groups of
* pixels of user-specified sizes. The resulting pixel can be
* calculated as average, median, maximum or minimum.
*
* @author Nico Stuurman
* @author Wayne Rasband
*/
public class Binner implements PlugIn {
public static int AVERAGE=0, MEDIAN=1, MIN=2, MAX=3, SUM=4;
private static String[] methods = {"Average", "Median", "Min", "Max", "Sum"};
private int xshrink=2, yshrink=2, zshrink=1;
private int method = AVERAGE;
private float maxValue;
public void run(String arg) {
ImagePlus imp = IJ.getImage();
if (!showDialog(imp))
return;
if (imp.getStackSize()==1)
Undo.setup(Undo.TYPE_CONVERSION, imp);
imp.startTiming();
ImagePlus imp2 = shrink(imp, xshrink, yshrink, zshrink, method);
IJ.showTime(imp, imp.getStartTime(), "", imp.getStackSize());
imp.setStack(imp2.getStack());
imp.setCalibration(imp2.getCalibration());
if (zshrink>1)
imp.setSlice(1);
}
public ImagePlus shrink(ImagePlus imp, int xshrink, int yshrink, int zshrink, int method) {
this.xshrink = xshrink;
this.yshrink = yshrink;
int w = imp.getWidth()/xshrink;
int h = imp.getHeight()/yshrink;
ColorModel cm=imp.createLut().getColorModel();
ImageStack stack=imp.getStack();
ImageStack stack2 = new ImageStack (w, h, cm);
int d = stack.getSize();
if (method==SUM) {
int bitDepth = imp.getBitDepth();
if (bitDepth==8)
maxValue = 255;
else if (bitDepth==16)
maxValue = 65535;
else
maxValue = 0;
}
for (int z=1; z<=d; z++) {
IJ.showProgress(z, d);
ImageProcessor ip = stack.getProcessor(z);
if (ip.isInvertedLut())
ip.invert();
ImageProcessor ip2 = shrink(ip, method);
if (ip.isInvertedLut()) ip2.invert();
stack2.addSlice(stack.getSliceLabel(z), ip2);
}
if (zshrink>1 && !imp.isHyperStack())
stack2 = shrinkZ(stack2, zshrink);
ImagePlus imp2 = imp.createImagePlus();
imp2.setStack("Reduced "+imp.getShortTitle(), stack2);
Calibration cal2 = imp2.getCalibration();
if (cal2.scaled()) {
cal2.pixelWidth *= xshrink;
cal2.pixelHeight *= yshrink;
cal2.pixelDepth *= zshrink;
}
//if (zshrink>1 && imp.isHyperStack())
// imp2 = shrinkHyperstackZ(imp2, zshrink);
imp2.setOpenAsHyperStack(imp.isHyperStack());
if (method==SUM && imp2.getBitDepth()>8) {
ImageProcessor ip = imp2.getProcessor();
ip.setMinAndMax(ip.getMin(), ip.getMax()*xshrink*yshrink*zshrink);
}
return imp2;
}
private ImageStack shrinkZ(ImageStack stack, int zshrink) {
int w = stack.getWidth();
int h = stack.getHeight();
int d = stack.getSize();
int d2 = d/zshrink;
ImageStack stack2 = new ImageStack (w, h, stack.getColorModel());
for (int z=1; z<=d2; z++)
stack2.addSlice(stack.getProcessor(z).duplicate());
boolean rgb = stack.getBitDepth()==24;
ImageProcessor ip = rgb?new ColorProcessor(d, h):new FloatProcessor(d, h);
for (int x=0; xmethods.length)
method = AVERAGE;
int w = ip.getWidth()/xshrink;
int h = ip.getHeight()/yshrink;
ImageProcessor ip2 = ip.createProcessor(w, h);
if (ip instanceof ColorProcessor)
return shrinkRGB((ColorProcessor)ip, (ColorProcessor)ip2, method);
for (int y=0; ymax) {
max = pixels[j];
mj = j;
}
}
pixels[mj] = 0;
}
float max = -Float.MAX_VALUE;
for (int j=0; jmax)
max = pixels[j];
}
return max;
}
private float getMin(ImageProcessor ip, int x, int y) {
float min = Float.MAX_VALUE;
float pixel;
for (int y2=0; y2max)
max = pixel;
}
}
return max;
}
private float getSum(ImageProcessor ip, int x, int y) {
float sum = 0;
for (int y2=0; y20f && sum>maxValue)
sum = maxValue;
return sum;
}
private boolean showDialog(ImagePlus imp) {
boolean stack = imp.getStackSize()>1;
if (imp.isComposite() && imp.getNChannels()==imp.getStackSize())
stack = false;
GenericDialog gd = new GenericDialog("Image Shrink");
gd.addNumericField("X shrink factor:", xshrink, 0);
gd.addNumericField("Y shrink factor:", yshrink, 0);
if (stack)
gd.addNumericField("Z shrink factor:", zshrink, 0);
if (method>methods.length)
method = 0;
gd.addChoice ("Bin Method: ", methods, methods[method]);
if (imp.getStackSize()==1) {
gd.setInsets(5, 0, 0);
gd.addMessage("This command supports Undo", null, Color.darkGray);
}
gd.showDialog();
if (gd.wasCanceled())
return false;
xshrink = (int) gd.getNextNumber();
yshrink = (int) gd.getNextNumber();
if (stack)
zshrink = (int) gd.getNextNumber();
method = gd.getNextChoiceIndex();
return true;
}
}
Ads help maintain this website.