Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
ContrastEnhancer.java
1 package ij.plugin;
2 import ij.*;
3 import ij.process.*;
4 import ij.gui.*;
5 import ij.measure.*;
6 import java.awt.*;
7 
9 public class ContrastEnhancer implements PlugIn, Measurements {
10 
11  int max, range;
12  boolean classicEqualization;
13 
14  static boolean equalize;
15  static boolean normalize;
16  static double saturated = 0.5;
17 
18  public void run(String arg) {
19  ImagePlus imp = IJ.getImage();
20  imp.trimProcessor();
21  if (!showDialog(imp))
22  return;
23  Undo.setup(Undo.TRANSFORM, imp);
24  if (equalize)
25  equalize(imp);
26  else
27  stretchHistogram(imp, saturated);
28  if (equalize || normalize)
29  imp.getProcessor().resetMinAndMax();
30  imp.updateAndDraw();
31  }
32 
33  boolean showDialog(ImagePlus imp) {
34  int bitDepth = imp.getBitDepth();
35  GenericDialog gd = new GenericDialog("Enhance Contrast");
36  gd.addNumericField("Saturated Pixels:", saturated, 1, 4, "%");
37  if (bitDepth!=24)
38  gd.addCheckbox("Normalize", normalize);
39  gd.addCheckbox("Equalize Histogram", equalize);
40  gd.showDialog();
41  if (gd.wasCanceled())
42  return false;
43  saturated = gd.getNextNumber();
44  if (bitDepth!=24)
45  normalize = gd.getNextBoolean();
46  else
47  normalize = false;
48  equalize = gd.getNextBoolean();
49  if (saturated<0.0) saturated = 0.0;
50  if (saturated>100.0) saturated = 100;
51  return true;
52  }
53 
54  public void stretchHistogram(ImagePlus imp, double saturated) {
55  stretchHistogram(imp.getProcessor(), saturated);
56  }
57 
58  public void stretchHistogram(ImageProcessor ip, double saturated) {
59  ImageStatistics stats = ImageStatistics.getStatistics(ip, MIN_MAX, null);
60  int hmin, hmax;
61  int threshold;
62  int[] histogram = stats.histogram;
63  if (saturated>0.0)
64  threshold = (int)(stats.pixelCount*saturated/200.0);
65  else
66  threshold = 0;
67  int i = -1;
68  boolean found = false;
69  int count = 0;
70  do {
71  i++;
72  count += histogram[i];
73  found = count>threshold;
74  } while (!found && i<255);
75  hmin = i;
76 
77  i = 256;
78  count = 0;
79  do {
80  i--;
81  count += histogram[i];
82  found = count>threshold;
83  //IJ.log(i+" "+count+" "+found);
84  } while (!found && i>0);
85  hmax = i;
86 
87  //IJ.log(hmin+" "+hmax+" "+threshold);
88  if (hmax>hmin) {
89  double min = stats.histMin+hmin*stats.binSize;
90  double max = stats.histMin+hmax*stats.binSize;
91  if (normalize)
92  normalize(ip, min, max);
93  else
94  ip.setMinAndMax(min, max);
95  }
96  }
97 
98  void normalize(ImageProcessor ip, double min, double max) {
99  int min2 = 0;
100  int max2 = 255;
101  int range = 256;
102  if (ip instanceof ShortProcessor)
103  {max2 = 65535; range=65536;}
104  else if (ip instanceof FloatProcessor)
105  normalizeFloat(ip, min, max);
106 
107  //double scale = range/max-min);
108  int[] lut = new int[range];
109  for (int i=0; i<range; i++) {
110  if (i<=min)
111  lut[i] = 0;
112  else if (i>=max)
113  lut[i] = max2;
114  else
115  lut[i] = (int)(((double)(i-min)/(max-min))*max2);
116  }
117  ip.applyTable(lut);
118  }
119 
120  void normalizeFloat(ImageProcessor ip, double min, double max) {
121  double scale = max>min?1.0/(max-min):1.0;
122  int size = ip.getWidth()*ip.getHeight();
123  float[] pixels = (float[])ip.getPixels();
124  double v;
125  for (int i=0; i<size; i++) {
126  v = pixels[i] - min;
127  if (v<0.0) v = 0.0;
128  v *= scale;
129  if (v>1.0) v = 1.0;
130  pixels[i] = (float)v;
131 
132  }
133  }
134 
135  public void equalize(ImagePlus imp) {
136  if (imp.getBitDepth()==32) {
137  IJ.showMessage("Contrast Enhancer", "Equalization of 32-bit images not supported.");
138  return;
139  }
140  classicEqualization = IJ.altKeyDown();
141  equalize(imp.getProcessor());
142  }
143 
154  public void equalize(ImageProcessor ip) {
155 
156  int[] histogram = ip.getHistogram();
157  ip.resetRoi();
158  if (ip instanceof ShortProcessor) { // Short
159  max = 65535;
160  range = 65535;
161  } else { //bytes
162  max = 255;
163  range = 255;
164  }
165 
166  double sum;
167 
168  sum = getWeightedValue(histogram, 0);
169  for (int i=1; i<max; i++)
170  sum += 2 * getWeightedValue(histogram, i);
171  sum += getWeightedValue(histogram, max);
172 
173  double scale = range/sum;
174  int[] lut = new int[range+1];
175 
176  lut[0] = 0;
177  sum = getWeightedValue(histogram, 0);
178  for (int i=1; i<max; i++) {
179  double delta = getWeightedValue(histogram, i);
180  sum += delta;
181  lut[i] = (int)Math.round(sum*scale);
182  sum += delta;
183  }
184  lut[max] = max;
185 
186  ip.applyTable(lut);
187  }
188 
189  private double getWeightedValue(int[] histogram, int i) {
190  int h = histogram[i];
191  if (h<2 || classicEqualization) return (double)h;
192  return Math.sqrt((double)(h));
193  }
194 
195 }