import ij.*; import ij.process.*; import ij.measure.*; import ij.plugin.*; import ij.plugin.frame.*; import ij.gui.Roi; /* Albert Cardona 2008 * * Applies an 'auto' Brightness and Contrast to each slice in the stack, * based on each slice parameters. */ public class Slice_AutoBC implements PlugIn, Measurements { public void run(String arg) { process(IJ.getImage(), 1); } /** Not accepted: 16 or 32 bit images. */ static public void process(ImagePlus imp, int iterations) { if (null == imp) return; switch (imp.getType()) { case ImagePlus.GRAY16: case ImagePlus.GRAY32: IJ.log("16- and 32-bit not supported."); return; } Calibration cal = imp.getCalibration(); imp.setCalibration(null); for (int i=imp.getStackSize(); i>0; i--) { imp.setSlice(i); autoAdjust(imp, iterations); } imp.setCalibration(cal); imp.unlock(); imp.changes = true; } /** Stripped from ij.plugin.frame.ContrastAdjuster class by Wayne Rasband. * Adjust only the current slice of the ImagePlus imp. */ static public void autoAdjust(ImagePlus imp, int iterations) { ImageProcessor ip = imp.getProcessor(); boolean RGBImage = imp.getType() == ImagePlus.COLOR_RGB; if (RGBImage) ip.reset(); ImageStatistics stats = ImageStatistics.getStatistics(ip, AREA+MEAN+MODE+MIN_MAX, null); // get uncalibrated stats int limit = stats.pixelCount/10; int[] histogram = stats.histogram; int autoThreshold = 0; double min = ip.getMin(); double max = ip.getMax(); int i = -1; boolean found = false; int count; int hmin = 0; for (int it=0; itlimit) count = 0; found = count > threshold; } while (!found && i<255); hmin = i; i = 256; do { i--; count = histogram[i]; if (count>limit) count = 0; found = count > threshold; } while (!found && i>0); } int hmax = i; Roi roi = imp.getRoi(); if (hmax>=hmin) { if (RGBImage) imp.killRoi(); min = stats.histMin+hmin*stats.binSize; max = stats.histMin+hmax*stats.binSize; if (min==max) {min=stats.min; max=stats.max;} ip.setMinAndMax(min, max); if (RGBImage && roi!=null) imp.setRoi(roi); } else { //reset(imp, ip); if (RGBImage) ip.reset(); if ((ip instanceof ShortProcessor) || (ip instanceof FloatProcessor)) { imp.resetDisplayRange(); } ip.setMinAndMax(min, max); return; } if (roi!=null) { ImageProcessor mask = roi.getMask(); if (mask!=null) ip.reset(mask); } apply(imp, ip); } static private void apply(ImagePlus imp, ImageProcessor ip) { String option = null; boolean RGBImage = imp.getType() == ImagePlus.COLOR_RGB; if (RGBImage) { ip.snapshot(); ip.reset(); return; } if (imp.getType()!=ImagePlus.GRAY8) { return; } int[] table = new int[256]; int min = (int)ip.getMin(); int max = (int)ip.getMax(); for (int i=0; i<256; i++) { if (i<=min) table[i] = 0; else if (i>=max) table[i] = 255; else table[i] = (int)(((double)(i-min)/(max-min))*255); } ip.setRoi(imp.getRoi()); if (ip.getMask()!=null) ip.snapshot(); ip.applyTable(table); ip.reset(ip.getMask()); if (RGBImage) ip.reset(); else ip.setMinAndMax(0, 255); } }