/Users/lyon/j4p/src/ip/gui/frames/NegateFrame.java

1    package ip.gui.frames; 
2     
3    import gui.Clipper; 
4    import ip.gui.dialog.AdaptiveLog; 
5    import ip.gui.dialog.ExponentialLog; 
6    import ip.gui.dialog.GrayLog; 
7    import ip.gui.dialog.RayleighLog; 
8    import ip.transforms.TransformTable; 
9    import j2d.ShortImageBean; 
10   import math.Mat2; 
11   import utils.Print; 
12    
13   import javax.media.jai.KernelJAI; 
14   import java.awt.*; 
15   import java.awt.event.ActionEvent; 
16    
17   public class NegateFrame extends GrabFrame { 
18                   
19       private HistogramFrame rh,gh,bh; 
20       KernelJAI kj = KernelJAI.GRADIENT_MASK_SOBEL_HORIZONTAL; 
21    
22       private int min = Integer.MAX_VALUE; 
23       private int max = Integer.MIN_VALUE; 
24    
25       // used for adaptive image enhancement 
26       private int mosaicWidth = 2; 
27       private int mosaicHeight = 2; 
28    
29       private double rBar = 0; 
30       private double gBar = 0; 
31       private double bBar = 0; 
32    
33       private TransformTable tt = 
34               new TransformTable(256); 
35    
36       private Menu negateMenu = getMenu("Negate"); 
37       private Menu histogramMenu = getMenu("Histogram"); 
38    
39       private MenuItem negate_mi = 
40               addMenuItem(negateMenu, "[E-n]egate"); 
41       private MenuItem add10_mi = 
42               addMenuItem(negateMenu, "[E-1]add 10"); 
43       private MenuItem brighten_mi = 
44               addMenuItem(negateMenu, "[E-b]righten"); 
45       private MenuItem darken_mi = 
46               addMenuItem(negateMenu, "[E-d]arken"); 
47       private MenuItem linear_mi = 
48               addMenuItem(negateMenu, "[E-l]inear transform..."); 
49    
50       private MenuItem histogram_mi = 
51               addMenuItem(histogramMenu, "[E-h]istogram"); 
52       private MenuItem unahe_mi = 
53               addMenuItem(histogramMenu, 
54                       "[E-u]niform non-adaptive histogram equalization"); 
55       private MenuItem enahe_mi = 
56               addMenuItem(histogramMenu, "[E-e]xponential non-adaptive histogram equalization..."); 
57       private MenuItem rnahe_mi = 
58               addMenuItem(histogramMenu, 
59                       "[E-r]ayleigh non-adaptive histogram equalization..."); 
60    
61       private MenuItem auhe_mi = 
62               addMenuItem(histogramMenu, "[E-a]uhe adaptive uniform histogram equalization"); 
63       private MenuItem drawMosaic_mi = 
64               addMenuItem(histogramMenu, "[E-d]raw Mosaic"); 
65       private MenuItem printTT_mi = 
66               addMenuItem(histogramMenu, "[E-T-t]print transform table..."); 
67       private MenuItem printStats_mi = 
68               addMenuItem(histogramMenu, "[E-T-p]rintStats"); 
69       private MenuItem printPMFs_mi = 
70               addMenuItem(histogramMenu, "[E-1]printPMFs"); 
71       private MenuItem printCMFs_mi = 
72               addMenuItem(histogramMenu, "[E-2]printCMF for r"); 
73    
74    
75       public void actionPerformed(ActionEvent e) { 
76    
77           if (match(e, drawMosaic_mi)) { 
78               drawMosaic(); 
79               return; 
80           } 
81           if (match(e, rnahe_mi)) { 
82               rayleighLog(); 
83               return; 
84           } 
85           if (match(e, auhe_mi)) { 
86               auhe(); 
87               return; 
88           } 
89           if (match(e, enahe_mi)) { 
90               eponentialLog(); 
91               return; 
92           } 
93           if (match(e, printCMFs_mi)) { 
94               printCMFs(); 
95               return; 
96           } 
97           if (match(e, printPMFs_mi)) { 
98               printPMFs(); 
99               return; 
100          } 
101          if (match(e, printStats_mi)) { 
102              printStats(); 
103              return; 
104          } 
105          if (match(e, unahe_mi)) { 
106              unahe(); 
107              return; 
108          } 
109          if (match(e, printTT_mi)) { 
110              printTT(); 
111              return; 
112          } 
113          if (match(e, linear_mi)) { 
114              linearLog(); 
115              return; 
116          } 
117          if (match(e, darken_mi)) { 
118              darken(); 
119              return; 
120          } 
121          if (match(e, brighten_mi)) { 
122              brighten(); 
123              return; 
124          } 
125          if (match(e, histogram_mi)) { 
126              histogram(); 
127              return; 
128          } 
129          if (match(e, add10_mi)) { 
130              add10(); 
131              return; 
132          } 
133          if (match(e, negate_mi)) { 
134              negate(); 
135              return; 
136          } 
137          super.actionPerformed(e); 
138   
139      } 
140   
141      /** 
142       mosaic - transform an array of 
143       short into sub-images 
144       */ 
145      public void auhe() { 
146          auhe(mosaicWidth, mosaicHeight); 
147      } 
148   
149      public void drawMosaic() { 
150          AdaptiveLog.doit(this); 
151      } 
152   
153      /** 
154       mosaic - transform an array of 
155       short into sub-images 
156       ignoring fractional parts. 
157       */ 
158      public void auhe(int blocksHigh, int blocksWide) { 
159   
160          int pelsWide = getImageWidth() / blocksWide; 
161          int pelsHigh = getImageHeight() / blocksHigh; 
162          int newWidth = pelsWide * blocksWide; 
163          int newHeight = pelsHigh * blocksHigh; 
164          NegateFrame nf; 
165   
166          for (int x1 = 0; x1 < newWidth; x1 += pelsWide) 
167              for (int y1 = 0; y1 < newHeight; y1 += pelsHigh) { 
168                  nf = subFrame(x1, y1, pelsWide, pelsHigh); 
169                  nf.unahe(); 
170                  assembleMosaic(nf, x1, y1); 
171              } 
172          short2Image(); 
173      } 
174   
175      public void assembleMosaic(NegateFrame nf, int x1, int y1) { 
176          int x2 = getImageWidth() + x1; 
177          int y2 = getImageHeight() + y1; 
178          int xs = 0; 
179          int ys = 0; 
180          for (int x = x1; x < x2; x++) { 
181              for (int y = y1; y < y2; y++) { 
182                  shortImageBean.getR()[x][y] = shortImageBean.getR()[xs][ys]; 
183                  shortImageBean.getG()[x][y] = shortImageBean.getG()[xs][ys]; 
184                  shortImageBean.getB()[x][y] = shortImageBean.getB()[xs][ys]; 
185                  ys++; 
186              } 
187              ys = 0; 
188              xs++; 
189          } 
190      } 
191   
192      public void drawMosaic(int blocksHigh, int blocksWide) { 
193          mosaicWidth = blocksWide; 
194          mosaicHeight = blocksHigh; 
195   
196          int pelsWide = getImageWidth() / blocksWide; 
197          int pelsHigh = getImageHeight() / blocksHigh; 
198          int newWidth = pelsWide * blocksWide; 
199          int newHeight = pelsHigh * blocksHigh; 
200   
201          int x1 = 0, y1 = 0; 
202          Print.println("DrawMosaic" + 
203                  " newWidth=" + newWidth + 
204                  " newHeight=" + newHeight + 
205                  " pelsWide=" + pelsWide + 
206                  " pelsHigh=" + pelsHigh); 
207          Graphics gx = getGraphics(); 
208          for (x1 = 0; x1 < newWidth; x1 += pelsWide) 
209              for (y1 = 0; y1 < newHeight; y1 += pelsHigh) { 
210                  gx.drawRect(x1, y1, pelsWide, pelsHigh); 
211              } 
212      } 
213   
214      public NegateFrame subFrame(int x1, int y1, int w, int h) { 
215          short _r[][] = new short[w][h]; 
216          short _g[][] = new short[w][h]; 
217          short _b[][] = new short[w][h]; 
218          int x2 = x1 + w; 
219          int y2 = y1 + h; 
220          // for loop computes source coordinates 
221          int xd = 0; 
222          int yd = 0; 
223   
224          Print.println("Subframe" + 
225                  " x1=" + x1 + 
226                  " y1=" + y1 + 
227                  " x2=" + x2 + 
228                  " y2=" + y2); 
229          for (int x = x1; x < x2; x++) { 
230              for (int y = y1; y < y2; y++) { 
231                  _r[xd][yd] = shortImageBean.getR()[x][y]; 
232                  _g[xd][yd] = shortImageBean.getG()[x][y]; 
233                  _b[xd][yd] = shortImageBean.getB()[x][y]; 
234                  yd++; 
235              } 
236              yd = 0; 
237              xd++; 
238          } 
239          return new 
240                  NegateFrame(_r, _g, _b, "frame"); 
241      } 
242   
243      private void doMenus() { 
244          negateMenu.add(histogramMenu); 
245          filterMenu.add(negateMenu); 
246      } 
247   
248      public NegateFrame( 
249              short _r[][], short _g[][], short _b[][], 
250              String title) { 
251          super(title); 
252          doMenus(); 
253          System.out.println("New constructor invoked"); 
254          shortImageBean.setR(_r); 
255          setB(_b); 
256          setG(_g); 
257          // show image ...very slow 
258          // but interesting! 
259          short2Image(); 
260      } 
261   
262      public void printTT() { 
263          tt.print(); 
264      } 
265   
266      public void add10() { 
267          shortImageBean.add(10); 
268          short2Image(); 
269      } 
270   
271      public void histogram() { 
272          rh = new HistogramFrame(shortImageBean.getR(), "Red"); 
273          gh = new HistogramFrame(shortImageBean.getG(), "Green"); 
274          bh = new HistogramFrame(shortImageBean.getB(), "Blue"); 
275          rh.myShow(); 
276          gh.myShow(); 
277          bh.myShow(); 
278      } 
279   
280      public void negate() { 
281          shortImageBean.negate(); 
282          short2Image(); 
283      } 
284   
285      private void brighten() { 
286          powImage(this, shortImageBean, 0.9); 
287      } 
288   
289      private void darken() { 
290          powImage(this, shortImageBean, 1.5); 
291      } 
292   
293      public static void powImage(ImageFrameInterface ifi, ShortImageBean nf, double p) { 
294          for (int x = 0; x < nf.getWidth(); x++) 
295              for (int y = 0; y < nf.getHeight(); y++) { 
296                  nf.getR()[x][y] = (short) 
297                          (255 * Math.pow((nf.getR()[x][y] / 255.0), p)); 
298                  nf.getG()[x][y] = (short) 
299                          (255 * Math.pow((nf.getG()[x][y] / 255.0), p)); 
300                  nf.getB()[x][y] = (short) 
301                          (255 * Math.pow((nf.getB()[x][y] / 255.0), p)); 
302              } 
303          ifi.short2Image(); 
304      } 
305   
306      // Uniform Non Adaptive Histogram 
307      // Equalization 
308      public void unahe() { 
309          short lut[] = tt.getLut(); 
310          double h[] = getAverageCMF(); 
311          for (short i = 0; i < lut.length; i++) 
312              lut[i] = (short) (255 * h[i]); 
313          applyLut(lut); 
314      } 
315   
316      // Rayleigh Non Adaptive Histogram 
317      // Equalization 
318      public void rnahe(double alpha) { 
319          short lut[] = tt.getLut(); 
320          double h[] = getAverageCMF(); 
321          double alpha2 = 2 * alpha * alpha; 
322          double v; 
323          double g; 
324          for (short i = 0; i < h.length; i++) { 
325              g = alpha2 * Math.log(1 / (1.0 - h[i])); 
326              v = Math.sqrt(g); 
327              lut[i] = (short) (255 * v); 
328          } 
329          tt.clip(); 
330          applyLut(lut); 
331      } 
332   
333      // Exponential Non Adaptive Histogram 
334      // Equalization 
335      public void enahe(double alpha) { 
336          short lut[] = tt.getLut(); 
337          double h[] = getAverageCMF(); 
338          for (short i = 0; i < 256; i++) 
339              lut[i] = (short) 
340                      (255 * (-Math.log(1.0 - h[i]) / alpha)); 
341          tt.clip(); 
342          applyLut(lut); 
343      } 
344   
345   
346      public double[] getAverageCMF() { 
347          rh = new HistogramFrame(shortImageBean.getR(), "Red"); 
348          gh = new HistogramFrame(shortImageBean.getG(), "Green"); 
349          bh = new HistogramFrame(shortImageBean.getB(), "Blue"); 
350          double CMFr[] = rh.getCMF(); 
351          double CMFg[] = gh.getCMF(); 
352          double CMFb[] = bh.getCMF(); 
353          return Mat2.getAverage(CMFr, CMFg, CMFb); 
354      } 
355   
356      public void applyLut(short lut[]) { 
357          wellConditioned(); //Shorts could be out of range; 
358          for (int x = 0; x < getImageWidth(); x++) 
359              for (int y = 0; y < getImageHeight(); y++) { 
360   
361                  shortImageBean.getR()[x][y] = lut[shortImageBean.getR()[x][y]]; 
362                  shortImageBean.getG()[x][y] = lut[shortImageBean.getG()[x][y]]; 
363                  shortImageBean.getB()[x][y] = lut[shortImageBean.getB()[x][y]]; 
364              } 
365          short2Image(); 
366      } 
367   
368      public void applyLut(short lutr[], short lutg[], short lutb[]) { 
369          wellConditioned(); //Shorts could be out of range; 
370          for (int x = 0; x < getImageWidth(); x++) 
371              for (int y = 0; y < getImageHeight(); y++) { 
372   
373                  shortImageBean.getR()[x][y] = lutr[shortImageBean.getR()[x][y]]; 
374                  shortImageBean.getG()[x][y] = lutg[shortImageBean.getG()[x][y]]; 
375                  shortImageBean.getB()[x][y] = lutb[shortImageBean.getB()[x][y]]; 
376              } 
377          short2Image(); 
378      } 
379   
380      public void wellConditioned() { 
381          for (int x = 0; x < getImageWidth(); x++) 
382              for (int y = 0; y < getImageHeight(); y++) { 
383                  shortImageBean.getR()[x][y] = inRange(shortImageBean.getR()[x][y], x, y); 
384                  shortImageBean.getG()[x][y] = inRange(shortImageBean.getG()[x][y], x, y); 
385                  shortImageBean.getB()[x][y] = inRange(shortImageBean.getB()[x][y], x, y); 
386              } 
387      } 
388   
389      public short inRange(short v, int x, int y) { 
390          if (v > 255) { 
391              Print.println( 
392                      "out of range x=" + x + " y=" + y + 
393                      "v=" + v + " clipping to 255"); 
394              return 255; 
395          } 
396          if (v < 0) { 
397              Print.println( 
398                      "out of range x=" + x + " y=" + y + 
399                      "v=" + v + " clipping to 0"); 
400              return 0; 
401          } 
402          return v; 
403      } 
404   
405      public short linearMap(short v, 
406                             double c, double b) { 
407          // scale gray value to 0..1 range 
408          double f = c * v + b; 
409          // scale f into 0..255 range 
410          // clip f into range 
411          if (f > 255) f = 255; 
412          if (f < 0) f = 0; 
413          return (short) f; 
414      } 
415   
416      public void linearTransform() { 
417          computeStats(); 
418          int Vmin = getMinimum(); 
419          int Vmax = getMaximum(); 
420          int Dmin = 0; 
421          int Dmax = 255; 
422          double deltaV = Vmax - Vmin; 
423          double deltaD = Dmax - Dmin; 
424          double c = deltaD / deltaV; 
425          double b = (Dmin * Vmax - Dmax * Vmin) / deltaV; 
426          linearTransform(c, b); 
427      } 
428   
429      public void linearTransform(double c, double br) { 
430          linearTransform(c, br, shortImageBean); 
431          Clipper clipper = getClipper(); 
432          clipper.clip(shortImageBean); 
433          short2Image(); 
434      } 
435   
436      public static void linearTransform(double c, double br, ShortImageBean b) { 
437          int w = b.getWidth(); 
438          int h = b.getHeight(); 
439          for (int x = 0; x < w; x++) 
440              for (int y = 0; y < h; y++) { 
441                  b.getR()[x][y] = (short) (c * b.getR()[x][y] + br); 
442                  b.getG()[x][y] = (short) (c * b.getG()[x][y] + br); 
443                  b.getB()[x][y] = (short) (c * b.getB()[x][y] + br); 
444              } 
445   
446      } 
447   
448      // The following transform is fast, but 
449      // only works on well conditioned input. 
450      // I.e., r,g,b [0..255]. 
451      public void linearTransform2(double c, double br) { 
452   
453          short lut[] = tt.getLut(); 
454          for (short i = 0; i < 256; i++) 
455              lut[i] = linearMap(i, c, br); 
456          for (int x = 0; x < getImageWidth(); x++) 
457              for (int y = 0; y < getImageHeight(); y++) { 
458                  shortImageBean.getR()[x][y] = lut[shortImageBean.getR()[x][y]]; 
459                  shortImageBean.getG()[x][y] = lut[shortImageBean.getG()[x][y]]; 
460                  shortImageBean.getB()[x][y] = lut[shortImageBean.getB()[x][y]]; 
461              } 
462          short2Image(); 
463      } 
464   
465      public void computeStats() { 
466   
467          min = Integer.MAX_VALUE; 
468          max = Integer.MIN_VALUE; 
469          rBar = 0; 
470          gBar = 0; 
471          bBar = 0; 
472          double N = getImageWidth() * getImageHeight(); 
473          for (int x = 0; x < getImageWidth(); x++) 
474              for (int y = 0; y < getImageHeight(); y++) { 
475                  rBar += shortImageBean.getR()[x][y]; 
476                  gBar += shortImageBean.getG()[x][y]; 
477                  bBar += shortImageBean.getB()[x][y]; 
478                  min = Math.min(shortImageBean.getR()[x][y], min); 
479                  min = Math.min(shortImageBean.getG()[x][y], min); 
480                  min = Math.min(shortImageBean.getB()[x][y], min); 
481                  max = Math.max(shortImageBean.getR()[x][y], max); 
482                  max = Math.max(shortImageBean.getG()[x][y], max); 
483                  max = Math.max(shortImageBean.getB()[x][y], max); 
484              } 
485          rBar /= N; 
486          gBar /= N; 
487          bBar /= N; 
488      } 
489   
490      public void printPMFr() { 
491          rh = new HistogramFrame(shortImageBean.getR(), "Red"); 
492          rh.printPMF(); 
493      } 
494   
495      public void printCMFs() { 
496          rh = new HistogramFrame(shortImageBean.getR(), "Red"); 
497          rh.printCMF(); 
498      } 
499   
500      public void printPMFg() { 
501          gh = new HistogramFrame(shortImageBean.getG(), "Green"); 
502          gh.printPMF(); 
503   
504      } 
505   
506      public void printPMFb() { 
507          bh = new HistogramFrame(shortImageBean.getB(), "Blue"); 
508          bh.printPMF(); 
509   
510      } 
511   
512      public void printPMFs() { 
513          printPMFr(); 
514          printPMFg(); 
515          printPMFb(); 
516      } 
517   
518      public void printStats() { 
519          computeStats(); 
520          Print.println( 
521                  "Min Vij=" + getMinimum() + "\n" + 
522                  "Max Vij=" + getMaximum() + "\n" + 
523                  "rBar = " + getRBar() + "\n" + 
524                  "gBar = " + getGBar() + "\n" + 
525                  "bBar = " + getBBar() 
526          ); 
527   
528      } 
529   
530      public double getRBar() { 
531          return rBar; 
532      } 
533   
534      public double getGBar() { 
535          return gBar; 
536      } 
537   
538      public double getBBar() { 
539          return bBar; 
540      } 
541   
542      public int getMinimum() { 
543          return min; 
544      } 
545   
546      public int getMaximum() { 
547          return max; 
548      } 
549   
550      public void eponentialLog() { 
551          String prompts[] = { 
552              "alpha = " 
553          }; 
554          String defaults[] = { 
555              "4.0"}; 
556          String title = "Exponential Transform Dialog"; 
557   
558   
559          new ExponentialLog( 
560                  this, 
561                  title, 
562                  prompts, 
563                  defaults, 9); 
564      } 
565   
566      public void rayleighLog() { 
567          String prompts[] = { 
568              "alpha = " 
569          }; 
570          String defaults[] = { 
571              "4.0"}; 
572          String title = "Rayleigh Transform Dialog"; 
573   
574   
575          new RayleighLog( 
576                  this, 
577                  title, 
578                  prompts, 
579                  defaults, 9); 
580      } 
581   
582      public void linearLog() { 
583          String prompts[] = { 
584              "Contrast = c =", 
585              "Brightness = b =" 
586          }; 
587          computeStats(); 
588          int Vmin = getMinimum(); 
589          int Vmax = getMaximum(); 
590          int Dmin = 0; 
591          int Dmax = 255; 
592          double deltaV = Vmax - Vmin; 
593          double deltaD = Dmax - Dmin; 
594          double c = deltaD / deltaV; 
595          double b = (Dmin * Vmax - Dmax * Vmin) / deltaV; 
596          Print.println("C=" + c + " b=" + b); 
597   
598          String defaults[] = { 
599              Double.toString(c), 
600              Double.toString(b)}; 
601          String title = "Linear Grayscale Transform Dialog"; 
602   
603   
604          new GrayLog( 
605                  this, 
606                  title, 
607                  prompts, 
608                  defaults, 9); 
609   
610      } 
611   
612      public NegateFrame(String title) { 
613          super(title); 
614          doMenus(); 
615      } 
616   
617      public static void main(String args[]) { 
618          new NegateFrame("NegateFrame"); 
619      } 
620  } 
621   
622