/Users/lyon/j4p/src/j2d/imageproc/HistogramEQProcessor.java
|
1 // Glenn Josefiak
2 // Fairfield University
3 // SW513
4 // Spring 2003
5
6 package j2d.imageproc;
7
8 import java.awt.*;
9
10 /**
11 * This classes allows adjustment of an image using histogram
12 * equalization.
13 * Reference: Douglas A. Lyon, "Image Processing in Java"
14 */
15 public class HistogramEQProcessor extends ImageProcessor{
16
17 private int lookupTable[] = new int[256];
18
19 private double PMF[][] = new double[3][256];
20 private double CMF[][] = new double[3][256];
21 private double avgCMF[] = new double[256];
22
23 private boolean blnExponential = false;
24 private double dblAlpha = 0.001;
25
26 /**
27 * Create a new HistogramEQProcessor
28 */
29 public HistogramEQProcessor(){
30 for (int j = 0; j< 256; j++){
31 lookupTable[j] = j;
32 }
33 }
34
35 /**
36 * Implementation of ImageProcessor
37 */
38 public void performAlgorithm() throws Exception{
39 int pixels[];
40 int r, g, b;
41
42 pixels = getPixels();
43
44 for (int i = 0; i<pixels.length; i++){
45
46 // Separate RGB components
47 r = (pixels[i] & 0x00FF0000) >> 16;
48 g = (pixels[i] & 0x0000FF00) >> 8;
49 b = (pixels[i] & 0x000000FF);
50
51 // Adjust the pixel
52 r = lookupTable[r];
53 g = lookupTable[g];
54 b = lookupTable[b];
55
56 // store the processed pixel
57 pixels[i] = 0xFF000000 | (r << 16) | (g << 8) | b;
58 }
59
60 setPixels(pixels);
61 }
62
63 /**
64 * Set the parameter for exponential EQ.
65 *
66 * @param alpha parameter for exponential EQ
67 */
68 public void setAlpha(double alpha){
69 if(alpha == dblAlpha) return;
70 makeENAHETable(alpha);
71 dblAlpha = alpha;
72 }
73
74 /**
75 * Sets uniform/exponential EQ option.
76 *
77 * @param state true = exponential; false = uniform
78 */
79 public void setExponential(boolean state){
80 if (state == blnExponential) return;
81 if (state == true){
82 makeENAHETable(dblAlpha);
83 }else{
84 makeUNAHETable();
85 }
86 blnExponential = state;
87 }
88
89 /**
90 * Set the base image reference. Compute aggregate stats on
91 * the image that will be needed for histogram processing.
92 */
93 public void setBaseImage(Image newImage){
94 super.setBaseImage(newImage);
95 computeStats();
96 // compute lookup table
97 if (blnExponential)
98 makeENAHETable(dblAlpha);
99 else
100 makeUNAHETable();
101 }
102
103 /**
104 * Compute PMF, CMF, etc.
105 */
106 private void computeStats(){
107 int pixels[];
108 int r, g, b;
109 int i, j;
110 double increment;
111
112 pixels = getPixels();
113
114 // Zero out all the stats.
115 for (j = 0; j< 256; j++){
116 for ( i= 0; i<3; i++){
117 PMF[i][j] = 0;
118 CMF[i][j] = 0;
119 }
120 avgCMF[j] = 0;
121 }
122
123 // Count lots of pixels
124
125 increment = 1.0/pixels.length;
126 for (i = 0; i<pixels.length; i++){
127
128 // Separate RGB components
129 r = (pixels[i] & 0x00FF0000) >> 16;
130 g = (pixels[i] & 0x0000FF00) >> 8;
131 b = (pixels[i] & 0x000000FF);
132
133 PMF[0][r] += increment;
134 PMF[1][g] += increment;
135 PMF[2][b] += increment;
136 }
137 for (i = 0; i< 3; i++){
138 CMF[i][0] = PMF[i][0];
139 for (j = 1; j < 256; j++){
140 CMF[i][j] = CMF[i][j-1] + PMF[i][j];
141 }
142 }
143 for (i = 0; i < 3; i++){
144 for (j=0; j < 256; j++){
145 avgCMF[j] += CMF[i][j] / 3;
146 }
147 }
148 }
149
150 /**
151 * Create lookup table for Uniform Non Adaptive
152 * Histogram Equalization
153 */
154 private void makeUNAHETable() {
155 for (short i = 0; i < lookupTable.length; i++){
156 lookupTable[i] = (short) (255 * avgCMF[i]);
157 }
158 }
159
160 /**
161 * Create lookup table for Exponential Non Adaptive
162 * Histogram Equalization
163 */
164 private void makeENAHETable(double alpha) {
165 double val;
166 double inverseCMF;
167
168 for (short i = 0; i < lookupTable.length; i++){
169 inverseCMF = 1.0 - avgCMF[i];
170 if (inverseCMF <= 0){
171 // Keep log in defined range at top of CMF; the CMF
172 // may be >1 due to rounding.
173 val = 255;
174 }else{
175 val = 255.0 * (-Math.log(inverseCMF) / alpha);
176 val = Math.min(255, val);
177 val = Math.max(0, val);
178 }
179 lookupTable[i] = (int)val;
180 }
181 }
182 }
183