package ip.gui;
import ip.gui.frames.ShortCutFrame;
import ip.gui.frames.TopFrame;
import ip.gui.frames.XformFrame;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import math.Mat3;
public class DotArray extends ShortCutFrame
implements MouseListener, MouseMotionListener {
XformFrame xf = null;
MenuBar mb = new MenuBar();
Menu transformMenu = getMenu("Transform");
Menu pointMenu = getMenu("Point...");
MenuItem revert_mi = addMenuItem(
transformMenu, "[l]oad image from file");
MenuItem applyBilinear4Points_mi = addMenuItem(
transformMenu, "[a]applyBilinear4Points");
MenuItem movePointd_mi = addMenuItem(
pointMenu, "[d]ont move points");
MenuItem printPoints_mi = addMenuItem(
pointMenu, "[p]rint points");
MenuItem selection = movePointd_mi;
private Polygon p = new Polygon();
Image img = null;
boolean doRevert = false;
short rn[][];
short gn[][];
short bn[][];
Mat3 at;
int x1 = 0;
int y1 = 0;
int xPoints = 5; int yPoints = 5; boolean busy = false;
int width;
int height;
int centroid[] = {width / 2, height / 2};
int xtranslate = 10;
int ytranslate = 50;
int pointToMove = -1;
public Polygon getPolygon() {
return at.transform(p);
}
public void actionPerformed(ActionEvent e) {
if (match(e, printPoints_mi)) {
printPoints();
return;
}
if (match(e, movePointd_mi)) {
pointToMove = -1;
return;
}
if (match(e, applyBilinear4Points_mi)) {
xf.revert();
applyBilinear();
return;
}
if (match(e, revert_mi)) {
revert();
return;
}
super.actionPerformed(e);
}
public DotArray(String title, TopFrame _xf) {
super(title);
xf = _xf;
width = xf.getImageWidth();
height = xf.getImageHeight();
init();
addMouseListener(this);
addMouseMotionListener(this);
transformMenu.add(pointMenu);
mb.add(transformMenu);
setMenuBar(mb);
setSize(width, height);
}
private void init() {
for (int i = 0; i <= yPoints; i++)
for (int j = 0; j <= xPoints; j++)
p.addPoint((int) (j * width / xPoints), (int) (i * height / yPoints));
centroid = Mat3.centroid(p);
setPose(0, 1, 1);
}
private void revert() {
xf.revert();
width = xf.getImageWidth();
height = xf.getImageHeight();
img = xf.getImage();
doRevert = true;
p = new Polygon();
init();
setSize(width + 2 * xtranslate, height + ytranslate + 15);
repaint();
}
public void setPose(double theta, double sx, double sy) {
Mat3 tr1 = new Mat3();
Mat3 tr2 = new Mat3();
Mat3 rt = new Mat3();
Mat3 sc = new Mat3();
centroid = rt.centroid(p);
tr1.setTranslation(centroid[0], centroid[1]);
sc.setScale(sx, sy);
rt.setRotation(theta);
tr2.setTranslation(-centroid[0], -centroid[1]);
at = tr1.multiply(rt);
at = at.multiply(sc);
at = at.multiply(tr2);
}
public void update(Graphics g) {
paint(g);
}
public void paint(Graphics g) {
if (doRevert) {
if ((img != null))
g.drawImage(img, xtranslate, ytranslate, width, height, this);
}
Polygon pt = at.transform(p);
g.translate(xtranslate, ytranslate);
for (int i = 0; i <= yPoints; i++)
for (int j = 0; j <= xPoints; j++) {
if (j != (xPoints))
g.drawLine(pt.xpoints[j + i * (xPoints + 1)],
pt.ypoints[j + i * (xPoints + 1)],
pt.xpoints[j + 1 + i * (xPoints + 1)],
pt.ypoints[j + 1 + i * (xPoints + 1)]);
if (i != (yPoints))
g.drawLine(pt.xpoints[j + i * (xPoints + 1)],
pt.ypoints[j + i * (xPoints + 1)],
pt.xpoints[j + (i + 1) * (xPoints + 1)],
pt.ypoints[j + (i + 1) * (xPoints + 1)]);
}
for (int i = 0; i < pt.npoints; i++)
g.drawRect(pt.xpoints[i] - 2, pt.ypoints[i] - 2, 4, 4);
}
public void applyBilinear() {
rn = new short[width][height];
gn = new short[width][height];
bn = new short[width][height];
for (int i = 0; i < yPoints; i++)
for (int j = 0; j < xPoints; j++) {
Polygon sourcePoly = new Polygon();
sourcePoly.addPoint((int) (j * width / xPoints), (int) (i * height / yPoints));
sourcePoly.addPoint((int) ((j + 1) * width / xPoints), (int) (i * height / yPoints));
sourcePoly.addPoint((int) ((j + 1) * width / xPoints), (int) ((i + 1) * height / yPoints));
sourcePoly.addPoint((int) (j * width / xPoints), (int) ((i + 1) * height / yPoints));
Polygon destPoly = new Polygon();
destPoly.addPoint(p.xpoints[j + i * (xPoints + 1)], p.ypoints[j + i * (xPoints + 1)]);
destPoly.addPoint(p.xpoints[j + 1 + i * (xPoints + 1)], p.ypoints[j + 1 + i * (xPoints + 1)]);
destPoly.addPoint(p.xpoints[j + 1 + (i + 1) * (xPoints + 1)], p.ypoints[j + 1 + (i + 1) * (xPoints + 1)]);
destPoly.addPoint(p.xpoints[j + (i + 1) * (xPoints + 1)], p.ypoints[j + (i + 1) * (xPoints + 1)]);
solve(sourcePoly, destPoly);
}
xf.setR(rn);
xf.setG(gn);
xf.setB(bn);
xf.short2Image();
}
int Dist(Point a, Point b) {
return (int) (Math.sqrt(((b.x - a.x) * (b.x - a.x)) + ((b.y - a.y) * (b.y - a.y))));
}
public void solve(Polygon S, Polygon D) {
int w = width;
int h = height;
double xStart1, xEnd1,yStart1, yEnd1;
double xStart2, xEnd2,yStart2, yEnd2;
Point s0,s1,s2,s3,d0,d1,d2,d3;
int MAX = 0;
int MAX1 = 0;
int xc, yc, xp, yp;
s0 = new Point(S.xpoints[0], S.ypoints[0]);
s1 = new Point(S.xpoints[1], S.ypoints[1]);
s2 = new Point(S.xpoints[2], S.ypoints[2]);
s3 = new Point(S.xpoints[3], S.ypoints[3]);
d0 = new Point(D.xpoints[0], D.ypoints[0]);
d1 = new Point(D.xpoints[1], D.ypoints[1]);
d2 = new Point(D.xpoints[2], D.ypoints[2]);
d3 = new Point(D.xpoints[3], D.ypoints[3]);
MAX = Dist(d0, d1);
MAX1 = Dist(d1, d2);
if (MAX1 > MAX) MAX = MAX1;
MAX1 = Dist(d2, d3);
if (MAX1 > MAX) MAX = MAX1;
MAX1 = Dist(d3, d0);
if (MAX1 > MAX) MAX = MAX1;
MAX1 = Dist(s0, s1);
if (MAX1 > MAX) MAX = MAX1;
MAX1 = Dist(s1, s2);
if (MAX1 > MAX) MAX = MAX1;
MAX1 = Dist(s2, s3);
if (MAX1 > MAX) MAX = MAX1;
MAX1 = Dist(s3, s0);
if (MAX1 > MAX) MAX = MAX1;
MAX = MAX + 20;
for (int i = 0; i < MAX; i++) {
xStart1 = d0.x + ((d3.x - d0.x) * i / MAX);
xEnd1 = d1.x + ((d2.x - d1.x) * i / MAX);
yStart1 = d0.y + ((d3.y - d0.y) * i / MAX);
yEnd1 = d1.y + ((d2.y - d1.y) * i / MAX);
xStart2 = s0.x + ((s3.x - s0.x) * i / MAX);
xEnd2 = s1.x + ((s2.x - s1.x) * i / MAX);
yStart2 = s0.y + ((s3.y - s0.y) * i / MAX);
yEnd2 = s1.y + ((s2.y - s1.y) * i / MAX);
for (int j = 0; j < MAX; j++) {
xc = (int) (xStart1 + ((xEnd1 - xStart1) * j / MAX));
yc = (int) (yStart1 + ((yEnd1 - yStart1) * j / MAX));
xp = (int) (xStart2 + ((xEnd2 - xStart2) * j / MAX));
yp = (int) (yStart2 + ((yEnd2 - yStart2) * j / MAX));
if ((xp < w) && (yp < h) &&
(xp >= 0) &&
(yp >= 0) && (xc < w) && (yc < h) &&
(xc >= 0) && (yc >= 0)) {
rn[xc][yc] = xf.getR()[xp][yp];
gn[xc][yc] = xf.getG()[xp][yp];
bn[xc][yc] = xf.getB()[xp][yp];
}
}
}
}
public void movePoints(MouseEvent e) {
int i = pointToMove;
p.xpoints[i] = getX(e);
p.ypoints[i] = getY(e);
repaint();
}
public void printPoints() {
for (int i = 0; i < p.xpoints.length; i++) {
System.out.println("af.setPoint(" + i + "," + p.xpoints[i] + "," + p.ypoints[i] + ");");
}
}
public void setPoint(int i, int x, int y) {
p.xpoints[i] = x;
p.ypoints[i] = y;
repaint();
}
private int getX(MouseEvent e) {
return (int) (e.getX() - xtranslate);
}
private int getY(MouseEvent e) {
return (int) (e.getY() - ytranslate);
}
public void mousePressed(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseClicked(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
busy = false;
repaint();
}
public void mouseDragged(MouseEvent e) {
e.consume();
double dx = getX(e);
double dy = getY(e);
double sx, sy;
double ray = 100000;
if (!busy) {
busy = true;
pointToMove = -1;
for (int i = 0; i < p.npoints; i++) {
sx = (p.xpoints[i] - dx) * (p.xpoints[i] - dx);
sy = (p.ypoints[i] - dy) * (p.ypoints[i] - dy);
if ((sx + sy) < ray) {
ray = sx + sy;
pointToMove = i;
}
}
}
if (pointToMove != -1) {
movePoints(e);
return;
}
repaint();
}
public void mouseMoved(MouseEvent e) {
}
}