Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
Binary.java
1 package ij.plugin.filter;
2 import ij.*;
3 import ij.gui.*;
4 import ij.process.*;
5 import java.awt.*;
6 
8 public class Binary implements PlugInFilter {
9 
10  String arg;
11  ImagePlus imp;
12  static int iterations = 1;
13  static boolean blackBackground = Prefs.blackBackground;
14  int foreground;
15 
16  public int setup(String arg, ImagePlus imp) {
17  this.arg = arg;
18  this.imp = imp;
19  IJ.register(Binary.class);
20 
21  if (arg.equals("options")) {
22  showDialog();
23  return DONE;
24  }
25 
26  if (arg.equals("outline") || arg.equals("skel")) {
27  if (imp!=null && (imp.getType()==ImagePlus.GRAY8 || imp.getType()==ImagePlus.COLOR_256)) {
28  ImageStatistics stats = imp.getStatistics();
29  if (stats.histogram[0]+stats.histogram[255]!=stats.pixelCount) {
30  IJ.error("8-bit binary (black and white only) image required.");
31  return DONE;
32  }
33  }
35  } else
37  }
38 
39  public void run(ImageProcessor ip) {
40  if (arg.equals("erode")) erode(ip);
41  else if (arg.equals("dilate")) dilate(ip);
42  else if (arg.equals("open")) open(ip);
43  else if (arg.equals("close")) close(ip);
44  else if (arg.equals("outline")) outline(ip);
45  else if (arg.equals("skel")) skeletonize(ip);
46  }
47 
48 
49  void erode(ImageProcessor ip) {
50  boolean edgePixels = hasEdgePixels(ip);
51  //IJ.log("erode: "+edgePixels);
52  ImageProcessor ip2 = expand(ip, edgePixels);
53  for (int i=0; i<iterations; i++)
54  if (blackBackground) ip2.dilate(); else ip2.erode();
55  ip = shrink(ip, ip2, edgePixels);
56  }
57 
58  void dilate(ImageProcessor ip) {
59  boolean edgePixels = hasEdgePixels(ip);
60  ImageProcessor ip2 = expand(ip, edgePixels);
61  for (int i=0; i<iterations; i++)
62  if (blackBackground) ip2.erode(); else ip2.dilate();
63  ip = shrink(ip, ip2, edgePixels);
64  }
65 
66 
67  void open(ImageProcessor ip) {
68  boolean edgePixels = hasEdgePixels(ip);
69  ImageProcessor ip2 = expand(ip, edgePixels);
70  for (int i=0; i<iterations; i++)
71  if (blackBackground) ip2.dilate(); else ip2.erode();
72  for (int i=0; i<iterations; i++)
73  if (blackBackground) ip2.erode(); else ip2.dilate();
74  ip = shrink(ip, ip2, edgePixels);
75  }
76 
77  void close(ImageProcessor ip) {
78  boolean edgePixels = hasEdgePixels(ip);
79  ImageProcessor ip2 = expand(ip, edgePixels);
80  for (int i=0; i<iterations; i++)
81  if (blackBackground) ip2.erode(); else ip2.dilate();
82  for (int i=0; i<iterations; i++)
83  if (blackBackground) ip2.dilate(); else ip2.erode();
84  ip = shrink(ip, ip2, edgePixels);
85  }
86 
87  void outline(ImageProcessor ip) {
88  if (blackBackground) ip.invert();
89  ((ByteProcessor)ip).outline();
90  if (blackBackground) ip.invert();
91  }
92 
93  void skeletonize(ImageProcessor ip) {
94  if (blackBackground) ip.invert();
95  boolean edgePixels = hasEdgePixels(ip);
96  ImageProcessor ip2 = expand(ip, edgePixels);
97  ((ByteProcessor)ip2).skeletonize();
98  ip = shrink(ip, ip2, edgePixels);
99  if (blackBackground) ip.invert();
100  }
101 
102  void showDialog() {
103  GenericDialog gd = new GenericDialog("Binary Options");
104  gd.addNumericField("Iterations (1-25):", iterations, 0);
105  gd.addCheckbox("Black Background", blackBackground);
106  gd.showDialog();
107  if (gd.wasCanceled()) return;
108  int n = (int)gd.getNextNumber();
109  Prefs.blackBackground = blackBackground = gd.getNextBoolean();
110  if (n>25) n = 25;
111  if (n<1) n = 1;
112  iterations = n;
113  }
114 
115  boolean hasEdgePixels(ImageProcessor ip) {
116  foreground = blackBackground?255:0;
117  if (ip.isInvertedLut())
118  foreground = 255 - foreground;
119  int width = ip.getWidth();
120  int height = ip.getHeight();
121  boolean edgePixels = false;
122  for (int x=0; x<width; x++) { // top edge
123  if (ip.getPixel(x, 0)==foreground)
124  edgePixels = true;
125  }
126  for (int x=0; x<width; x++) { // bottom edge
127  if (ip.getPixel(x, height-1)==foreground)
128  edgePixels = true;
129  }
130  for (int y=0; y<height; y++) { // left edge
131  if (ip.getPixel(0, y)==foreground)
132  edgePixels = true;
133  }
134  for (int y=0; y<height; y++) { // right edge
135  if (ip.getPixel(height-1, y)==foreground)
136  edgePixels = true;
137  }
138  return edgePixels;
139  }
140 
141  ImageProcessor expand(ImageProcessor ip, boolean hasEdgePixels) {
142  if (hasEdgePixels) {
143  ImageProcessor ip2 = ip.createProcessor(ip.getWidth()+2, ip.getHeight()+2);
144  if (foreground==0) {
145  ip2.setColor(255);
146  ip2.fill();
147  }
148  ip2.insert(ip, 1, 1);
149  //new ImagePlus("ip2", ip2).show();
150  return ip2;
151  } else
152  return ip;
153  }
154 
155  ImageProcessor shrink(ImageProcessor ip, ImageProcessor ip2, boolean hasEdgePixels) {
156  if (hasEdgePixels) {
157  int width = ip.getWidth();
158  int height = ip.getHeight();
159  for (int y=0; y<height; y++)
160  for (int x=0; x<width; x++)
161  ip.putPixel(x, y, ip2.getPixel(x+1, y+1));
162  }
163  return ip;
164  }
165 }