|
GaussianBlur |
|
package ij.plugin.filter; import ij.*; import ij.process.*; import ij.gui.*; import ij.text.*; import java.awt.*; import java.util.*; /** This plugin implements ImageJ's Gaussian Blur command. */ public class GaussianBlur implements PlugInFilter { private static final int BYTE=0, SHORT=1, FLOAT=2, RGB=3; private ImagePlus imp; private boolean canceled; private int slice; private boolean isLineRoi; private boolean isAreaRoi; private boolean displayKernel; private static int radius = 2; public int setup(String arg, ImagePlus imp) { IJ.register(GaussianBlur.class); this.imp = imp; if (imp!=null) { IJ.resetEscape(); Roi roi = imp.getRoi(); isLineRoi= roi!=null && roi.isLine(); isAreaRoi = roi!=null && !isLineRoi; } if (imp!=null && !showDialog()) return DONE; else return IJ.setupDialog(imp, DOES_ALL); } public void run(ImageProcessor ip) { if (canceled) return; slice++; if (slice==1) { if (imp.getType()==ImagePlus.GRAY32 && !isAreaRoi && imp.getStackSize()==1) { Undo.setup(Undo.COMPOUND_FILTER, imp); blur(ip, radius); Undo.setup(Undo.COMPOUND_FILTER_DONE, imp); return; } } else IJ.showStatus("Gaussian Blur: "+slice+"/"+imp.getStackSize()); if (isLineRoi) ip.resetRoi(); blur(ip, radius); if (canceled) Undo.undo(); } public boolean blur(ImageProcessor ip, double radius) { Rectangle rect = ip.getRoi(); ImageProcessor ip2 = ip; boolean isRoi = rect.width!=ip.getWidth()||rect.height!=ip.getHeight(); boolean nonRectRoi = ip.getMask()!=null; if (isRoi) { ip2.setRoi(rect); ip2 = ip2.crop(); } int type; if (ip2 instanceof ByteProcessor) type = BYTE; else if (ip2 instanceof ShortProcessor) type = SHORT; else if (ip2 instanceof FloatProcessor) type = FLOAT; else type = RGB; float[] kernel = makeKernel(radius); if (slice==1 && displayKernel) { TextWindow tw = new TextWindow("Kernel", "", 150, 300); for (int i=0; i<kernel.length; i++) tw.append(i+" "+IJ.d2s(kernel[i],3)); } if (type==RGB) { if (nonRectRoi) { ip2.snapshot(); blurRGB(ip2, kernel); ip2.reset(ip.getMask()); } else blurRGB(ip2, kernel); if (nonRectRoi) ip2.reset(ip.getMask()); if (isRoi) ip.insert(ip2, rect.x, rect.y); return !canceled; } ip2.setCalibrationTable(null); ip2 = ip2.convertToFloat(); blurFloat(ip2, kernel); if (nonRectRoi) ip.snapshot(); switch (type) { case BYTE: ip2 = ip2.convertToByte(false); ip.insert(ip2, rect.x, rect.y); break; case SHORT: ip2 = ip2.convertToShort(false); ip.insert(ip2, rect.x, rect.y); break; case FLOAT: if (isRoi) ip.insert(ip2, rect.x, rect.y); break; } if (nonRectRoi) ip.reset(ip.getMask()); return !canceled; } void blurFloat(ImageProcessor ip, float[] kernel) { if (canceled) return; Convolver c = new Convolver(); if (!c.convolve(ip, kernel, kernel.length, 1)) {canceled=true; return;} ip.snapshot(); if (!c.convolve(ip, kernel,1, kernel.length)) {canceled=true; return;} } public void blurRGB(ImageProcessor ip, float[] kernel) { int width = ip.getWidth(); int height = ip.getHeight(); int size = width*height; byte[] r = new byte[size]; byte[] g = new byte[size]; byte[] b = new byte[size]; ((ColorProcessor)ip).getRGB(r,g,b); ImageProcessor rip = new ByteProcessor(width, height, r, null); ImageProcessor gip = new ByteProcessor(width, height, g, null); ImageProcessor bip = new ByteProcessor(width, height, b, null); ImageProcessor ip2 = rip.convertToFloat(); blurFloat(ip2, kernel); ImageProcessor r2 = ip2.convertToByte(false); ip2 = gip.convertToFloat(); blurFloat(ip2, kernel); ImageProcessor g2 = ip2.convertToByte(false); ip2 = bip.convertToFloat(); blurFloat(ip2, kernel); ImageProcessor b2 = ip2.convertToByte(false); ((ColorProcessor)ip).setRGB((byte[])r2.getPixels(), (byte[])g2.getPixels(), (byte[])b2.getPixels()); } public float[] makeKernel(double radius) { radius += 1; int size = (int)radius*2+1; float[] kernel = new float[size]; double v; for (int i=0; i<size; i++) kernel[i] = (float)Math.exp(-0.5*(sqr((i-radius)/(radius*2)))/sqr(0.2)); float[] kernel2 = new float[size-2]; for (int i=0; i<size-2; i++) kernel2[i] = kernel[i+1]; if (kernel2.length==1) kernel2[0] = 1f; return kernel2; } double sqr(double x) {return x*x;} public boolean showDialog() { GenericDialog gd = new GenericDialog("Gaussian Blur..."); gd.addNumericField("Radius (pixels)", radius,0); gd.addCheckbox("Show Kernel", displayKernel); gd.showDialog(); if (gd.wasCanceled()) { canceled = true; return false; } radius = (int)gd.getNextNumber(); displayKernel = gd.getNextBoolean(); return true; } }
|
GaussianBlur |
|