/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