package ip.hak;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.image.ColorModel;
import java.awt.image.MemoryImageSource;
import java.awt.image.PixelGrabber;
public class MyPanel extends Panel implements ItemListener, ActionListener {
int w,h;
SmallImage si1, si2;
Button compButton;
ImageComponent mi;
Label nl, il1, il2, cl, wl, hl, sl;
TextField tf[][] = new TextField[3][2];
Checkbox cb[] = new Checkbox[3];
Label nof;
TextField noftf;
int isize[][] = new int[3][2];
Image im[] = new Image[2];
boolean imageState[] = new boolean[2];
Dimension di;
ColorModel cm;
short r[][][] = new short[3][][];
short g[][][] = new short[3][][];
short b[][][] = new short[3][][];
Image iar[];
int nf;
SmallImageFrame sif = null;
Polygon sp[];
Polygon dp[];
Polygon tp[];
ip.gui.ImageSequence is = new ip.gui.ImageSequence();
public MyPanel(int wid, int hei) {
w = wid;
h = hei;
setSize(w, h);
init();
reLocate();
imageState[0] = imageState[1] = false;
}
public void makeSmallImageFrame(Image ig) {
sif = new SmallImageFrame("Morph Image");
sif.loadImage(ig);
sif.init();
sif.setVisible(true);
}
public void setImageState(int ind) {
imageState[ind] = true;
}
public void initPoint() {
Dimension d = si2.getSize();
Point pl = si2.getLocation();
P4 p4 = new P4(new Point(pl.x + d.width / 2, pl.y + d.height / 2), 0, 0);
add(p4);
}
public void setImageSize(int wid, int hei, int index) {
isize[index][0] = wid;
isize[index][1] = hei;
tf[index][0].setText("" + wid);
tf[index][1].setText("" + hei);
}
public void init() {
setLayout(null);
int inten = 200;
Color bgColor = new Color(inten, inten, inten);
setBackground(bgColor);
si1 = new SmallImage(10, 10, this, 0);
add(si1);
si2 = new SmallImage(10, 10, this, 1);
add(si2);
mi = new ImageComponent(20, 20, this);
add(mi);
compButton = new Button("Compute");
add(compButton);
compButton.addActionListener(this);
il1 = new Label("Image 1");
add(il1);
il2 = new Label("Image 2");
add(il2);
cl = new Label("Custom");
add(cl);
wl = new Label("Width");
add(wl);
hl = new Label("Height");
add(hl);
sl = new Label("Set");
add(sl);
for (int i = 0; i < 3; i++)
for (int j = 0; j < 2; j++) {
tf[i][j] = new TextField("0");
add(tf[i][j]);
tf[i][j].setEditable(false);
}
for (int i = 0; i < 3; i++) {
cb[i] = new Checkbox();
add(cb[i]);
cb[i].addItemListener(this);
}
cb[0].setState(true);
nof = new Label("Number of Frame ");
add(nof);
noftf = new TextField("10");
add(noftf);
}
public void reLocate() {
Dimension siz = getSize();
w = siz.width;
h = siz.height;
int qw = w / 4;
int qh = h / 4;
int g = 10;
int sish = (3 * qh - 3 * g) / 2;
si1.setSize(sish, sish);
si1.setLocation(g, g);
si2.setSize(sish, sish);
si2.setLocation(g, sish + 2 * g);
mi.setSize(3 * qh - 2 * g, 3 * qh - 2 * g);
mi.setLocation(sish + 3 * g, g);
Dimension d = new Dimension(80, 25);
compButton.setSize(d.width, d.height);
compButton.setLocation(3 * qw + (qw - d.width) / 2, qh * 3 + (qh - d.height) / 2);
d = new Dimension(50, 20);
int gv = (qh - d.height * 4) / 5;
int gh = (qw * 2 - d.width * 4) / 5;
wl.setSize(d.width, d.height);
wl.setLocation(gh + 2, qh * 3 + d.height + gv * 2);
hl.setSize(d.width, d.height);
hl.setLocation(gh, qh * 3 + d.height * 2 + gv * 3);
sl.setSize(d.width, d.height);
sl.setLocation(gh + 6, qh * 3 + d.height * 3 + gv * 4);
il1.setSize(d.width, d.height);
il1.setLocation(d.width + gh * 2 + 2, qh * 3 + gv);
il2.setSize(d.width, d.height);
il2.setLocation(d.width * 2 + gh * 3 + 2, qh * 3 + gv);
cl.setSize(d.width, d.height);
cl.setLocation(d.width * 3 + gh * 4 + 2, qh * 3 + gv);
for (int i = 0; i < 3; i++)
for (int j = 0; j < 2; j++) {
tf[i][j].setSize(d.width, d.height);
tf[i][j].setLocation(d.width * (i + 1) + gh * (i + 2), qh * 3 + d.height * (j + 1) + gv * (j + 2));
}
for (int i = 0; i < 3; i++) {
cb[i].setSize(20, 20);
cb[i].setLocation(d.width * (i + 1) + gh * (i + 2) + 15, qh * 3 + d.height * 3 + gv * 4);
}
d = new Dimension(100, 20);
nof.setSize(d.width, d.height);
nof.setLocation(qw * 2 + g, qh * 3 + (qh - d.height) / 2);
noftf.setSize(40, d.height);
noftf.setLocation(qw * 2 + 2 * g + d.width, qh * 3 + (qh - d.height) / 2);
repaint();
}
public Dimension getWnH() {
int id = 0;
for (int i = 0; i < 3; i++)
if (cb[i].getState()) {
id = i;
break;
}
if (!imageState[0] || !imageState[1]) {
MessageDialog md = new MessageDialog(new Frame(), "Error!!!", false, "Load image first!", 200, 100);
return null;
}
String sw = tf[id][0].getText();
String sh = tf[id][1].getText();
Dimension d = new Dimension(Integer.parseInt(sw), Integer.parseInt(sh));
if (d.width <= 0 || d.height <= 0) {
MessageDialog md = new MessageDialog(new Frame(), "Error!!!", false, "Width or Height should be greater than 0.", 300, 100);
return null;
}
return d;
}
public void doCompute() {
di = getWnH();
if (di == null)
return;
String sn = noftf.getText();
nf = Integer.parseInt(sn);
if (nf <= 0) {
MessageDialog md = new MessageDialog(new Frame(), "Error!!!", false, "Number of Frame should be greater than 0.", 300, 100);
return;
}
r[2] = new short[di.width][di.height];
g[2] = new short[di.width][di.height];
b[2] = new short[di.width][di.height];
write2Memory();
}
public void write2Memory() {
im[0] = si1.getResizedImage(di.width, di.height);
im[1] = si2.getResizedImage(di.width, di.height);
image2Short(0);
image2Short(1);
sp = sif.getSourcePoly();
dp = sif.getDestPoly();
checkPolygon(sp, dp); tp = new Polygon[sp.length];
float t = 1f / nf;
iar = new Image[nf];
mi.switchMessage();
float i = 0.0f;
for (int j = 0; j < nf; j++) {
makeTP(i);
checkPolygon(sp, tp); double a[][][] = new double[sp.length][][];
for (int it = 0; it < sp.length; it++) {
a[it] = infer4PointA(sp[it], tp[it]);
}
inverseBilinearXform(a, tp);
morphImage(i);
iar[j] = short2Image();
is.add(iar[j]);
i += t;
}
mi.switchMessage();
is.save();
mi.showImage(iar, di);
}
public void checkPolygon(Polygon[] s, Polygon[] d) {
for (int j = 0; j < s.length; j++) {
int xp1[] = s[j].xpoints;
int yp1[] = s[j].ypoints;
int xp2[] = d[j].xpoints;
int yp2[] = d[j].ypoints;
if (xp1.length != xp2.length || xp1.length != yp1.length || xp1.length != yp2.length)
System.out.println("length is diff");
for (int i = 0; i < xp1.length; i++) {
if (xp1[i] != xp2[i] || yp1[i] != yp2[i])
System.out.println("point is diff");
}
}
}
public void makeTP(float t1) {
for (int j = 0; j < tp.length; j++) {
int xp1[] = sp[j].xpoints;
int yp1[] = sp[j].ypoints;
int xp2[] = dp[j].xpoints;
int yp2[] = dp[j].ypoints;
int psize = xp1.length;
int xp3[] = new int[psize];
int yp3[] = new int[psize];
for (int k = 0; k < psize; k++) {
xp3[k] = xp1[k] + (int) (t1 * (xp2[k] - xp1[k]));
yp3[k] = yp1[k] + (int) (t1 * (yp2[k] - yp1[k]));
}
tp[j] = new Polygon(xp3, yp3, psize);
}
}
public double[][] infer4PointA(Polygon s, Polygon d) {
int xd[] = d.xpoints;
int yd[] = d.ypoints;
int xs[] = s.xpoints;
int ys[] = s.ypoints;
double d4 [][] = {
{xd[0], xd[1], xd[2], xd[3]},
{yd[0], yd[1], yd[2], yd[3]},
};
double s4[][] = {
{xs[0], xs[1], xs[2], xs[3]},
{ys[0], ys[1], ys[2], ys[3]},
{xs[0] * ys[0], xs[1] * ys[1], xs[2] * ys[2], xs[3] * ys[3]},
{1, 1, 1, 1},
};
math.Mat4 s4Mat = new math.Mat4(s4);
math.Mat4 s4MatInverse = s4Mat.invert();
double[][] a = s4MatInverse.multiply2x4(d4);
return a;
}
public void inverseBilinearXform(double a[][][], Polygon d[]) {
int w = di.width;
int h = di.height;
short rn[][] = new short[w][h];
short gn[][] = new short[w][h];
short bn[][] = new short[w][h];
double p[] = new double[2];
int red, green, blue;
int xp, yp, i, j;
for (int x = 0; x < w; x++)
for (int y = 0; y < h; y++) {
int s = selectPolygon(d, x, y);
if (s == -1)
continue;
p = inverseMap4(a[s], x, y);
xp = (int) (p[0]);
yp = (int) (p[1]);
if ((xp < w - 1) && (yp < h - 1) && (xp > 0) && (yp > 0)) {
rn[x][y] = r[1][xp][yp];
gn[x][y] = g[1][xp][yp];
bn[x][y] = b[1][xp][yp];
}
}
r[1] = rn;
g[1] = gn;
b[1] = bn;
}
public double[] inverseMap4(double a[][], double xp, double yp) {
double as =
-a[1][1] * a[0][2]
+ a[1][2] * a[0][1];
double b =
a[0][2] * yp + a[1][0] * a[0][1] - a[0][0] * a[1][1]
- a[1][2] * xp + a[1][2] * a[0][3] - a[0][2] * a[1][3];
double c = yp * a[0][0]
- a[1][0] * xp
+ a[1][0] * a[0][3]
- a[1][3] * a[0][0];
double y = quadraticRoot(as, b, c);
double x =
(xp - a[0][1] * y - a[0][3]) / (a[0][0] + a[0][2] * y);
double p[] = {x, y};
return p;
}
public double quadraticRoot(double a, double b, double c) {
if (a == 0) a = 0.00001;
double sqrtArg = b * b - 4 * a * c;
double aa = 2 * a;
if (sqrtArg < 0) return -b / aa; double root1 = (-b + Math.sqrt(sqrtArg)) / aa;
double root2 = (-b - Math.sqrt(sqrtArg)) / aa;
if ((root1 >= 0) && (root1 < di.height)) return root1;
if ((root2 >= 0) && (root2 < di.height)) return root2;
if (root1 > di.height) return di.height;
return 0;
}
public int selectPolygon(Polygon d[], int x, int y) {
for (int i = 0; i < d.length; i++) {
if (d[i].contains(x, y))
return i;
}
return -1;
}
public void image2Short(int idx) {
r[idx] = new short[di.width][di.height];
g[idx] = new short[di.width][di.height];
b[idx] = new short[di.width][di.height];
int pels[] = new int[di.width * di.height];
cm = ColorModel.getRGBdefault();
PixelGrabber grabber = new PixelGrabber(im[idx], 0, 0, di.width, di.height, pels, 0, di.width);
try {
grabber.grabPixels();
} catch (InterruptedException e) {
}
;
int i = 0;
for (int x = 0; x < di.width; x++)
for (int y = 0; y < di.height; y++) {
i = x + y * di.width;
b[idx][x][y] = (short) cm.getBlue(pels[i]);
g[idx][x][y] = (short) cm.getGreen(pels[i]);
r[idx][x][y] = (short) cm.getRed(pels[i]);
}
}
public void morphImage(float t) {
for (int x = 0; x < di.width; x++)
for (int y = 0; y < di.height; y++) {
r[2][x][y] = (short) (r[0][x][y] + r[1][x][y] * t - r[0][x][y] * t);
g[2][x][y] = (short) (g[0][x][y] + g[1][x][y] * t - g[0][x][y] * t);
b[2][x][y] = (short) (b[0][x][y] + b[1][x][y] * t - b[0][x][y] * t);
}
}
public Image short2Image() {
Toolkit tk = Toolkit.getDefaultToolkit();
int pels[] = new int[di.width * di.height];
for (int x = 0; x < di.width; x++)
for (int y = 0; y < di.height; y++) {
pels[x + y * di.width] = 0xff000000 | (r[2][x][y] << 16)
| (g[2][x][y] << 8)
| b[2][x][y];
}
Image i = tk.createImage(new MemoryImageSource(di.width, di.height, cm, pels, 0, di.width));
return i;
}
public void paint(Graphics g) {
super.paint(g);
int p2 = h / 4 * 3;
int p1 = (p2 - 30) / 2 + 20;
g.drawLine(p1, 0, p1, p2);
g.drawLine(0, p2, w, p2);
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == compButton) {
doCompute();
return;
}
}
public void itemStateChanged(ItemEvent e) {
if (e.getSource() == cb[0]) {
cb[0].setState(true);
cb[1].setState(false);
cb[2].setState(false);
tf[2][0].setEditable(false);
tf[2][1].setEditable(false);
return;
}
if (e.getSource() == cb[1]) {
cb[0].setState(false);
cb[1].setState(true);
cb[2].setState(false);
tf[2][0].setEditable(false);
tf[2][1].setEditable(false);
return;
}
if (e.getSource() == cb[2]) {
cb[0].setState(false);
cb[1].setState(false);
cb[2].setState(true);
tf[2][0].setEditable(true);
tf[2][1].setEditable(true);
tf[2][0].requestFocus();
return;
}
}
}