/Users/lyon/j4p/src/ip/hak/MyPanel.java

1    package ip.hak; 
2     
3    import java.awt.*; 
4    import java.awt.event.ActionEvent; 
5    import java.awt.event.ActionListener; 
6    import java.awt.event.ItemEvent; 
7    import java.awt.event.ItemListener; 
8    import java.awt.image.ColorModel; 
9    import java.awt.image.MemoryImageSource; 
10   import java.awt.image.PixelGrabber; 
11    
12   public class MyPanel extends Panel implements ItemListener, ActionListener { 
13    
14       int w,h; 
15       SmallImage si1, si2; 
16       Button compButton; 
17       ImageComponent mi; 
18       Label nl, il1, il2, cl, wl, hl, sl; 
19       TextField tf[][] = new TextField[3][2]; 
20       Checkbox cb[] = new Checkbox[3]; 
21       Label nof; 
22       TextField noftf; 
23       int isize[][] = new int[3][2]; 
24       Image im[] = new Image[2]; 
25       boolean imageState[] = new boolean[2]; 
26       Dimension di; 
27       ColorModel cm; 
28       short r[][][] = new short[3][][]; 
29       short g[][][] = new short[3][][]; 
30       short b[][][] = new short[3][][]; 
31       Image iar[]; 
32       int nf; 
33       SmallImageFrame sif = null; 
34       Polygon sp[]; 
35       Polygon dp[]; 
36       Polygon tp[]; 
37       ip.gui.ImageSequence is = new ip.gui.ImageSequence(); 
38    
39       public MyPanel(int wid, int hei) { 
40           w = wid; 
41           h = hei; 
42           setSize(w, h); 
43           init(); 
44           reLocate(); 
45           imageState[0] = imageState[1] = false; 
46       } 
47    
48       public void makeSmallImageFrame(Image ig) { 
49           sif = new SmallImageFrame("Morph Image"); 
50    
51           sif.loadImage(ig); 
52           sif.init(); 
53           sif.setVisible(true); 
54       } 
55    
56    
57       public void setImageState(int ind) { 
58           imageState[ind] = true; 
59       } 
60    
61       public void initPoint() { 
62           Dimension d = si2.getSize(); 
63           Point pl = si2.getLocation(); 
64    
65           P4 p4 = new P4(new Point(pl.x + d.width / 2, pl.y + d.height / 2), 0, 0); 
66           add(p4); 
67       } 
68    
69       public void setImageSize(int wid, int hei, int index) { 
70           isize[index][0] = wid; 
71           isize[index][1] = hei; 
72           tf[index][0].setText("" + wid); 
73           tf[index][1].setText("" + hei); 
74       } 
75    
76       public void init() { 
77           setLayout(null); 
78           int inten = 200; 
79           Color bgColor = new Color(inten, inten, inten); 
80           setBackground(bgColor); 
81           si1 = new SmallImage(10, 10, this, 0); 
82           add(si1); 
83           si2 = new SmallImage(10, 10, this, 1); 
84           add(si2); 
85           mi = new ImageComponent(20, 20, this); 
86           add(mi); 
87    
88           compButton = new Button("Compute"); 
89           add(compButton); 
90           compButton.addActionListener(this); 
91    
92           il1 = new Label("Image 1"); 
93           add(il1); 
94           il2 = new Label("Image 2"); 
95           add(il2); 
96           cl = new Label("Custom"); 
97           add(cl); 
98           wl = new Label("Width"); 
99           add(wl); 
100          hl = new Label("Height"); 
101          add(hl); 
102          sl = new Label("Set"); 
103          add(sl); 
104          for (int i = 0; i < 3; i++) 
105              for (int j = 0; j < 2; j++) { 
106                  tf[i][j] = new TextField("0"); 
107                  add(tf[i][j]); 
108                  tf[i][j].setEditable(false); 
109              } 
110          for (int i = 0; i < 3; i++) { 
111              cb[i] = new Checkbox(); 
112              add(cb[i]); 
113              cb[i].addItemListener(this); 
114          } 
115          cb[0].setState(true); 
116   
117   
118          nof = new Label("Number of Frame "); 
119          add(nof); 
120          noftf = new TextField("10"); 
121          add(noftf); 
122      } 
123   
124      public void reLocate() { 
125          Dimension siz = getSize(); 
126          w = siz.width; 
127          h = siz.height; 
128          int qw = w / 4; 
129          int qh = h / 4; 
130          int g = 10; 
131   
132          // Small Image 
133          int sish = (3 * qh - 3 * g) / 2; 
134          si1.setSize(sish, sish); 
135          si1.setLocation(g, g); 
136   
137          si2.setSize(sish, sish); 
138          si2.setLocation(g, sish + 2 * g); 
139   
140          // Main Image 
141          mi.setSize(3 * qh - 2 * g, 3 * qh - 2 * g); 
142          mi.setLocation(sish + 3 * g, g); 
143   
144          // Buttons 
145          Dimension d = new Dimension(80, 25); 
146          compButton.setSize(d.width, d.height); 
147          compButton.setLocation(3 * qw + (qw - d.width) / 2, qh * 3 + (qh - d.height) / 2); 
148   
149          // Width, Height, Set Label 
150          d = new Dimension(50, 20); 
151          int gv = (qh - d.height * 4) / 5; 
152          int gh = (qw * 2 - d.width * 4) / 5; 
153          wl.setSize(d.width, d.height); 
154          wl.setLocation(gh + 2, qh * 3 + d.height + gv * 2); 
155          hl.setSize(d.width, d.height); 
156          hl.setLocation(gh, qh * 3 + d.height * 2 + gv * 3); 
157          sl.setSize(d.width, d.height); 
158          sl.setLocation(gh + 6, qh * 3 + d.height * 3 + gv * 4); 
159   
160          il1.setSize(d.width, d.height); 
161          il1.setLocation(d.width + gh * 2 + 2, qh * 3 + gv); 
162          il2.setSize(d.width, d.height); 
163          il2.setLocation(d.width * 2 + gh * 3 + 2, qh * 3 + gv); 
164          cl.setSize(d.width, d.height); 
165          cl.setLocation(d.width * 3 + gh * 4 + 2, qh * 3 + gv); 
166   
167          // Text Fields 
168          for (int i = 0; i < 3; i++) 
169              for (int j = 0; j < 2; j++) { 
170                  tf[i][j].setSize(d.width, d.height); 
171                  tf[i][j].setLocation(d.width * (i + 1) + gh * (i + 2), qh * 3 + d.height * (j + 1) + gv * (j + 2)); 
172              } 
173   
174          // CheckBoxes 
175          for (int i = 0; i < 3; i++) { 
176              cb[i].setSize(20, 20); 
177              cb[i].setLocation(d.width * (i + 1) + gh * (i + 2) + 15, qh * 3 + d.height * 3 + gv * 4); 
178          } 
179   
180          // Number of Frame Label & TextField 
181          d = new Dimension(100, 20); 
182          nof.setSize(d.width, d.height); 
183          nof.setLocation(qw * 2 + g, qh * 3 + (qh - d.height) / 2); 
184          noftf.setSize(40, d.height); 
185          noftf.setLocation(qw * 2 + 2 * g + d.width, qh * 3 + (qh - d.height) / 2); 
186   
187          repaint(); 
188      } 
189   
190      public Dimension getWnH() { 
191          // get selected checkbox 
192          int id = 0; 
193          for (int i = 0; i < 3; i++) 
194              if (cb[i].getState()) { 
195                  id = i; 
196                  break; 
197              } 
198   
199          // Check 2 images are already loaded. 
200          if (!imageState[0] || !imageState[1]) { 
201              MessageDialog md = new MessageDialog(new Frame(), "Error!!!", false, "Load image first!", 200, 100); 
202              return null; 
203          } 
204   
205          // Check width & height are valid. 
206          String sw = tf[id][0].getText(); 
207          String sh = tf[id][1].getText(); 
208          Dimension d = new Dimension(Integer.parseInt(sw), Integer.parseInt(sh)); 
209          if (d.width <= 0 || d.height <= 0) { 
210              MessageDialog md = new MessageDialog(new Frame(), "Error!!!", false, "Width or Height should be greater than 0.", 300, 100); 
211              return null; 
212          } 
213          return d; 
214      } 
215   
216      public void doCompute() { 
217          di = getWnH(); 
218          if (di == null) 
219              return; 
220   
221   
222          // get & check the # of Frame 
223          String sn = noftf.getText(); 
224          nf = Integer.parseInt(sn); 
225          if (nf <= 0) { 
226              MessageDialog md = new MessageDialog(new Frame(), "Error!!!", false, "Number of Frame should be greater than 0.", 300, 100); 
227              return; 
228          } 
229   
230          r[2] = new short[di.width][di.height]; 
231          g[2] = new short[di.width][di.height]; 
232          b[2] = new short[di.width][di.height]; 
233   
234          write2Memory(); 
235      } 
236   
237      public void write2Memory() { 
238   
239          // get 2 Image 
240          im[0] = si1.getResizedImage(di.width, di.height); 
241          im[1] = si2.getResizedImage(di.width, di.height); 
242          image2Short(0); 
243          image2Short(1); 
244   
245          sp = sif.getSourcePoly(); 
246          dp = sif.getDestPoly(); 
247          checkPolygon(sp, dp); //test 
248          tp = new Polygon[sp.length]; 
249   
250          float t = 1f / nf; 
251   
252          iar = new Image[nf]; 
253          mi.switchMessage(); 
254          float i = 0.0f; 
255          for (int j = 0; j < nf; j++) { 
256              makeTP(i); 
257              checkPolygon(sp, tp); //test 
258              double a[][][] = new double[sp.length][][]; 
259   
260              for (int it = 0; it < sp.length; it++) { 
261                  a[it] = infer4PointA(sp[it], tp[it]); 
262              } 
263              inverseBilinearXform(a, tp); 
264              morphImage(i); 
265              iar[j] = short2Image(); 
266              is.add(iar[j]); 
267              i += t; 
268          } 
269          mi.switchMessage(); 
270          is.save(); 
271          mi.showImage(iar, di); 
272      } 
273   
274      public void checkPolygon(Polygon[] s, Polygon[] d) { 
275          for (int j = 0; j < s.length; j++) { 
276              int xp1[] = s[j].xpoints; 
277              int yp1[] = s[j].ypoints; 
278              int xp2[] = d[j].xpoints; 
279              int yp2[] = d[j].ypoints; 
280   
281   
282              if (xp1.length != xp2.length || xp1.length != yp1.length || xp1.length != yp2.length) 
283                  System.out.println("length is diff"); 
284              for (int i = 0; i < xp1.length; i++) { 
285                  if (xp1[i] != xp2[i] || yp1[i] != yp2[i]) 
286                      System.out.println("point is diff"); 
287              } 
288          } 
289      } 
290   
291      public void makeTP(float t1) { 
292          for (int j = 0; j < tp.length; j++) { 
293              int xp1[] = sp[j].xpoints; 
294              int yp1[] = sp[j].ypoints; 
295              int xp2[] = dp[j].xpoints; 
296              int yp2[] = dp[j].ypoints; 
297   
298              int psize = xp1.length; 
299              int xp3[] = new int[psize]; 
300              int yp3[] = new int[psize]; 
301   
302              for (int k = 0; k < psize; k++) { 
303                  xp3[k] = xp1[k] + (int) (t1 * (xp2[k] - xp1[k])); 
304                  yp3[k] = yp1[k] + (int) (t1 * (yp2[k] - yp1[k])); 
305              } 
306              tp[j] = new Polygon(xp3, yp3, psize); 
307          } 
308      } 
309   
310      public double[][] infer4PointA(Polygon s, Polygon d) { 
311          // D is destination 
312          // S is source 
313          int xd[] = d.xpoints; 
314          int yd[] = d.ypoints; 
315          int xs[] = s.xpoints; 
316          int ys[] = s.ypoints; 
317   
318          // d4 is a 2x4 
319          double d4 [][] = { 
320              {xd[0], xd[1], xd[2], xd[3]}, 
321              {yd[0], yd[1], yd[2], yd[3]}, 
322          }; 
323          // s4 is a 4x4 
324          double s4[][] = { 
325              {xs[0], xs[1], xs[2], xs[3]}, 
326              {ys[0], ys[1], ys[2], ys[3]}, 
327              {xs[0] * ys[0], xs[1] * ys[1], xs[2] * ys[2], xs[3] * ys[3]}, 
328              {1, 1, 1, 1}, 
329          }; 
330          math.Mat4 s4Mat = new math.Mat4(s4); 
331          math.Mat4 s4MatInverse = s4Mat.invert(); 
332          // 2x4*4x4 = 2x4 
333          double[][] a = s4MatInverse.multiply2x4(d4); 
334          return a; 
335      } 
336   
337      public void inverseBilinearXform(double a[][][], Polygon d[]) { 
338          int w = di.width; 
339          int h = di.height; 
340          short rn[][] = new short[w][h]; 
341          short gn[][] = new short[w][h]; 
342          short bn[][] = new short[w][h]; 
343          double p[] = new double[2]; 
344          int red, green, blue; 
345          int xp, yp, i, j; 
346          for (int x = 0; x < w; x++) 
347              for (int y = 0; y < h; y++) { 
348                  int s = selectPolygon(d, x, y); 
349                  if (s == -1) 
350                      continue; 
351                  p = inverseMap4(a[s], x, y); 
352                  xp = (int) (p[0]); 
353                  yp = (int) (p[1]); 
354                  if ((xp < w - 1) && (yp < h - 1) && (xp > 0) && (yp > 0)) { 
355                      rn[x][y] = r[1][xp][yp]; 
356                      gn[x][y] = g[1][xp][yp]; 
357                      bn[x][y] = b[1][xp][yp]; 
358                  } 
359              } 
360          r[1] = rn; 
361          g[1] = gn; 
362          b[1] = bn; 
363          //short2Image(); 
364      } 
365   
366      public double[] inverseMap4(double a[][], double xp, double yp) { 
367          double as = 
368                  -a[1][1] * a[0][2] 
369                  + a[1][2] * a[0][1]; 
370          double b = 
371                  a[0][2] * yp + a[1][0] * a[0][1] - a[0][0] * a[1][1] 
372                  - a[1][2] * xp + a[1][2] * a[0][3] - a[0][2] * a[1][3]; 
373          double c = yp * a[0][0] 
374                  - a[1][0] * xp 
375                  + a[1][0] * a[0][3] 
376                  - a[1][3] * a[0][0]; 
377          double y = quadraticRoot(as, b, c); 
378          double x = 
379                  (xp - a[0][1] * y - a[0][3]) / (a[0][0] + a[0][2] * y); 
380          double p[] = {x, y}; 
381          return p; 
382      } 
383   
384      public double quadraticRoot(double a, double b, double c) { 
385          if (a == 0) a = 0.00001; 
386          double sqrtArg = b * b - 4 * a * c; 
387          double aa = 2 * a; 
388          if (sqrtArg < 0) return -b / aa; // ignore imaginary part. 
389          double root1 = (-b + Math.sqrt(sqrtArg)) / aa; 
390          double root2 = (-b - Math.sqrt(sqrtArg)) / aa; 
391          if ((root1 >= 0) && (root1 < di.height)) return root1; 
392          if ((root2 >= 0) && (root2 < di.height)) return root2; 
393          if (root1 > di.height) return di.height; 
394          return 0; 
395      } 
396   
397      public int selectPolygon(Polygon d[], int x, int y) { 
398          for (int i = 0; i < d.length; i++) { 
399              if (d[i].contains(x, y)) 
400                  return i; 
401          } 
402          return -1; 
403      } 
404   
405      public void image2Short(int idx) { 
406          r[idx] = new short[di.width][di.height]; 
407          g[idx] = new short[di.width][di.height]; 
408          b[idx] = new short[di.width][di.height]; 
409   
410          int pels[] = new int[di.width * di.height]; 
411          cm = ColorModel.getRGBdefault(); 
412   
413          PixelGrabber grabber = new PixelGrabber(im[idx], 0, 0, di.width, di.height, pels, 0, di.width); 
414   
415          try { 
416              grabber.grabPixels(); 
417          } catch (InterruptedException e) { 
418          } 
419          ; 
420   
421          int i = 0; 
422          for (int x = 0; x < di.width; x++) 
423              for (int y = 0; y < di.height; y++) { 
424                  i = x + y * di.width; 
425                  b[idx][x][y] = (short) cm.getBlue(pels[i]); 
426                  g[idx][x][y] = (short) cm.getGreen(pels[i]); 
427                  r[idx][x][y] = (short) cm.getRed(pels[i]); 
428              } 
429      } 
430   
431      public void morphImage(float t) { 
432          for (int x = 0; x < di.width; x++) 
433              for (int y = 0; y < di.height; y++) { 
434                  r[2][x][y] = (short) (r[0][x][y] + r[1][x][y] * t - r[0][x][y] * t); 
435                  g[2][x][y] = (short) (g[0][x][y] + g[1][x][y] * t - g[0][x][y] * t); 
436                  b[2][x][y] = (short) (b[0][x][y] + b[1][x][y] * t - b[0][x][y] * t); 
437              } 
438      } 
439   
440      public Image short2Image() { 
441          Toolkit tk = Toolkit.getDefaultToolkit(); 
442          int pels[] = new int[di.width * di.height]; 
443          for (int x = 0; x < di.width; x++) 
444              for (int y = 0; y < di.height; y++) { 
445                  pels[x + y * di.width] = 0xff000000 | (r[2][x][y] << 16) 
446                          | (g[2][x][y] << 8) 
447                          | b[2][x][y]; 
448              } 
449          Image i = tk.createImage(new MemoryImageSource(di.width, di.height, cm, pels, 0, di.width)); 
450          return i; 
451      } 
452   
453   
454      public void paint(Graphics g) { 
455          super.paint(g); 
456          int p2 = h / 4 * 3; 
457          int p1 = (p2 - 30) / 2 + 20; 
458   
459          g.drawLine(p1, 0, p1, p2); 
460          g.drawLine(0, p2, w, p2); 
461      } 
462   
463      public void actionPerformed(ActionEvent e) { 
464          if (e.getSource() == compButton) { 
465              doCompute(); 
466              return; 
467          } 
468      } 
469   
470      public void itemStateChanged(ItemEvent e) { 
471          if (e.getSource() == cb[0]) { 
472              cb[0].setState(true); 
473              cb[1].setState(false); 
474              cb[2].setState(false); 
475              tf[2][0].setEditable(false); 
476              tf[2][1].setEditable(false); 
477              return; 
478          } 
479          if (e.getSource() == cb[1]) { 
480              cb[0].setState(false); 
481              cb[1].setState(true); 
482              cb[2].setState(false); 
483              tf[2][0].setEditable(false); 
484              tf[2][1].setEditable(false); 
485              return; 
486          } 
487          if (e.getSource() == cb[2]) { 
488              cb[0].setState(false); 
489              cb[1].setState(false); 
490              cb[2].setState(true); 
491              tf[2][0].setEditable(true); 
492              tf[2][1].setEditable(true); 
493              tf[2][0].requestFocus(); 
494              return; 
495          } 
496      } 
497  } 
498