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.