|
Binary |
|
package ij.plugin.filter;
import ij.*;
import ij.gui.*;
import ij.process.*;
import java.awt.*;
/** Implements the commands in the Process/Binary submenu. */
public class Binary implements PlugInFilter {
String arg;
ImagePlus imp;
static int iterations = 1;
static int count = 1;
int foreground, background;
public int setup(String arg, ImagePlus imp) {
this.arg = arg;
this.imp = imp;
IJ.register(Binary.class);
if (arg.equals("options")) {
showDialog();
return DONE;
}
if (imp!=null && (imp.getType()==ImagePlus.GRAY8 || imp.getType()==ImagePlus.COLOR_256)) {
ImageStatistics stats = imp.getStatistics();
if (stats.histogram[0]+stats.histogram[255]!=stats.pixelCount) {
IJ.error("8-bit binary (black and white only) image required.");
return DONE;
}
}
return IJ.setupDialog(imp, DOES_8G+DOES_8C+SUPPORTS_MASKING);
}
public void run(ImageProcessor ip) {
foreground = Prefs.blackBackground?255:0;
if (ip.isInvertedLut())
foreground = 255 - foreground;
background = 255 - foreground;
ip.setSnapshotCopyMode(true);
if (arg.equals("erode")) erode(ip);
else if (arg.equals("dilate")) dilate(ip);
else if (arg.equals("open")) open(ip);
else if (arg.equals("close")) close(ip);
else if (arg.equals("outline")) outline(ip);
else if (arg.equals("skel")) skeletonize(ip);
ip.setSnapshotCopyMode(false);
}
void erode(ImageProcessor ip) {
for (int i=0; i<iterations; i++)
((ByteProcessor)ip).erode(count, background);
}
void dilate(ImageProcessor ip) {
for (int i=0; i<iterations; i++)
((ByteProcessor)ip).dilate(count, background);
}
void open(ImageProcessor ip) {
for (int i=0; i<iterations; i++)
((ByteProcessor)ip).erode(count, background);
for (int i=0; i<iterations; i++)
((ByteProcessor)ip).dilate(count, background);
}
void close(ImageProcessor ip) {
for (int i=0; i<iterations; i++)
((ByteProcessor)ip).dilate(count, background);
for (int i=0; i<iterations; i++)
((ByteProcessor)ip).erode(count, background);
}
void outline(ImageProcessor ip) {
if (Prefs.blackBackground) ip.invert();
((ByteProcessor)ip).outline();
if (Prefs.blackBackground) ip.invert();
}
void skeletonize(ImageProcessor ip) {
if (Prefs.blackBackground) ip.invert();
boolean edgePixels = hasEdgePixels(ip);
ImageProcessor ip2 = expand(ip, edgePixels);
((ByteProcessor)ip2).skeletonize();
ip = shrink(ip, ip2, edgePixels);
if (Prefs.blackBackground) ip.invert();
}
void showDialog() {
GenericDialog gd = new GenericDialog("Binary Options");
gd.addNumericField("Iterations (1-25):", iterations, 0, 3, "");
gd.addNumericField("Count (1-8):", count, 0, 3, "");
gd.addCheckbox("Black Background", Prefs.blackBackground);
gd.showDialog();
if (gd.wasCanceled()) return;
int n = (int)gd.getNextNumber();
Prefs.blackBackground = gd.getNextBoolean();
if (n>25) n = 25;
if (n<1) n = 1;
iterations = n;
count = (int)gd.getNextNumber();
if (count<1) count = 1;
if (count>8) count = 8;
}
boolean hasEdgePixels(ImageProcessor ip) {
int width = ip.getWidth();
int height = ip.getHeight();
boolean edgePixels = false;
for (int x=0; x<width; x++) { // top edge
if (ip.getPixel(x, 0)==foreground)
edgePixels = true;
}
for (int x=0; x<width; x++) { // bottom edge
if (ip.getPixel(x, height-1)==foreground)
edgePixels = true;
}
for (int y=0; y<height; y++) { // left edge
if (ip.getPixel(0, y)==foreground)
edgePixels = true;
}
for (int y=0; y<height; y++) { // right edge
if (ip.getPixel(height-1, y)==foreground)
edgePixels = true;
}
return edgePixels;
}
ImageProcessor expand(ImageProcessor ip, boolean hasEdgePixels) {
if (hasEdgePixels) {
ImageProcessor ip2 = ip.createProcessor(ip.getWidth()+2, ip.getHeight()+2);
if (foreground==0) {
ip2.setColor(255);
ip2.fill();
}
ip2.insert(ip, 1, 1);
//new ImagePlus("ip2", ip2).show();
return ip2;
} else
return ip;
}
ImageProcessor shrink(ImageProcessor ip, ImageProcessor ip2, boolean hasEdgePixels) {
if (hasEdgePixels) {
int width = ip.getWidth();
int height = ip.getHeight();
for (int y=0; y<height; y++)
for (int x=0; x<width; x++)
ip.putPixel(x, y, ip2.getPixel(x+1, y+1));
}
return ip;
}
}
|
Binary |
|