Selection rectangle "roi" working.

This commit is contained in:
knut 2007-04-21 22:23:51 +00:00
parent c1498adc1f
commit bcc46597c9

View file

@ -19,11 +19,11 @@ import javax.swing.border.*;
*/
public class Editor
extends JComponent
implements MouseListener, MouseMotionListener
{
// Given from input image
BufferedImage img;
double imgScale; // coordinates per bitmap pixel
Rectangle imgRec;
// What we choose
double rotation; // radians
@ -32,30 +32,29 @@ public class Editor
int side;
// other
// AffineTransform t;
CropFrame mask;
AffineTransform screenToCoord;
AffineTransform coordToScreen;
boolean dirty = true;
// CropFrame mask;
public Editor(BufferedImage img) {
this.img = img;
int w = img.getWidth();
int h = img.getHeight();
imgScale = 1d / Math.sqrt(w * w + h * h);
imgRec = new Rectangle(0, 0, w, h);
resize(imgScale * 680);
roi = new Rect();
roi.top = 0.5f;
roi.bottom = -0.5f;
roi.left = -0.5f;
roi.right = 0.5f;
rescale(imgScale * 680);
/*
Dimension size = new Dimension(680, 680);
setPreferredSize(size);
setMinimumSize(size);
setMaximumSize(size);
roi = new Rect();
roi.top = 0.5;
roi.bottom = -0.5;
roi.left = -0.5;
roi.right = 0.5;
rotation = 0.0;
Rectangle initialMask = new Rectangle(100, 100, 200, 200);
@ -67,18 +66,21 @@ public class Editor
add(mask);
SelectionEditor ml = new SelectionEditor();
addMouseListener(ml);
addMouseMotionListener(ml);
*/
addMouseListener(this);
addMouseMotionListener(this);
}
void resize(double newScale) {
void rescale(double newScale) {
scale = newScale;
side = (int)Math.round(scale / imgScale);
Dimension size = new Dimension(side, side);
dirty = true;
roi.cache = null;
System.out.println("Side: " + side);
setSize(size);
setPreferredSize(size);
setMinimumSize(size);
@ -91,67 +93,53 @@ public class Editor
protected void paintComponent(Graphics g1) {
super.paintComponent(g1);
if (dirty) {
System.out.println("Recalculating");
AffineTransform screenToCoord = new AffineTransform();
screenToCoord.translate(side/2d, side/2d);
screenToCoord.scale(side, -side);
AffineTransform coordToScreen = new AffineTransform();
coordToScreen.scale(1d/side, -1d/side);
coordToScreen.translate(-side/2d, -side/2d);
this.screenToCoord = coordToScreen;
this.coordToScreen = screenToCoord;
dirty = false;
} else {
// System.out.println("using cached transform");
}
Graphics2D g = (Graphics2D)g1;
AffineTransform orig = g.getTransform();
AffineTransform screenToCoord = new AffineTransform();
screenToCoord.translate(side/2d, side/2d);
screenToCoord.scale(side, side);
g.transform(screenToCoord);
g.transform(this.coordToScreen);
AffineTransform imageToCoord = new AffineTransform();
imageToCoord.rotate(rotation * Math.PI / 180d);
imageToCoord.scale(imgScale * scale, imgScale * scale);
imageToCoord.scale(imgScale, -imgScale);
imageToCoord.translate(-img.getWidth()/2d, -img.getHeight()/2d);
g.drawImage(img, imageToCoord, this);
// Crosshair
/*
g.setStroke(new BasicStroke(0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 1f, new float[] { 0.005f, 0.005f }, 0));
g.draw(new Line2D.Double(-0.5, 0, 0.5, 0));
g.draw(new Line2D.Double(0, -0.5, 0, 0.5));
*/
g.setTransform(orig);
g.setXORMode(Color.white); //Color of line varies
g.setStroke(new BasicStroke(0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 1f, new float[] { 5f, 5f }, 0));
g.draw(new Rectangle2D.Double(100, 100, 200, 200));
g.draw(roi.getScreenRectangle());
// roi.cache = null;
}
private class SelectionEditor extends MouseInputAdapter {
public void mousePressed(MouseEvent e) {
int x = e.getX();
int y = e.getY();
mask.setLocation(x, y);
mask.setSize(1, 1);
mask.repaint();
}
public void mouseDragged(MouseEvent e) {
mask.updateFrame(e.getX(), e.getY());
}
public void mouseReleased(MouseEvent e) {
mask.updateFrame(e.getX(), e.getY());
}
}
JComponent createControlPanel() {
@ -203,7 +191,7 @@ public class Editor
int value = zoomSlider.getValue();
if (value != previousValue) {
previousValue = value;
resize(value * 0.01);
rescale(value * 0.01);
}
}
});
@ -228,201 +216,174 @@ public class Editor
reader.setInput(iis, true);
ImageReadParam param = reader.getDefaultReadParam();
// param.setSourceSubsampling(8, 8, 0, 0);
BufferedImage raw = reader.read(0, param);
final BufferedImage raw = reader.read(0, param);
Editor x = new Editor(raw);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Editor x = new Editor(raw);
JFrame frame = new JFrame("Editor");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JFrame frame = new JFrame("Editor");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container c = frame.getContentPane();
c.setLayout(new BorderLayout());
c.add(x.createControlPanel(), BorderLayout.EAST);
c.add(new JScrollPane(x), BorderLayout.CENTER);
Container c = frame.getContentPane();
c.setLayout(new BorderLayout());
c.add(x.createControlPanel(), BorderLayout.EAST);
c.add(new JScrollPane(x), BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
frame.pack();
frame.setVisible(true);
}
});
}
final int resizeBand = 3;
boolean isDragging = false;
Stroke stroke = new BasicStroke(1f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 1f, new float[] { 5f, 5f }, 0);
static class CropFrame extends JComponent implements MouseListener, MouseMotionListener {
/**
*/
private static final long serialVersionUID = 1L;
private int resizeBand = 6;
public void mouseClicked(MouseEvent e) {
// noop
}
Stroke stroke = new BasicStroke(1f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 1f, new float[] { 5f, 5f }, 0);
public CropFrame()
{
setOpaque(false);
public void mouseEntered(MouseEvent e) {
// noop
}
public void mouseExited(MouseEvent e) {
// noop
}
public void mousePressed(MouseEvent e) {
int r = findRegion(e.getX(), e.getY());
if (r < 8) {
edge = r;
isDragging = true;
} else {
isDragging = false;
}
}
//
// 1------(5)-------2
// | |
// | |
// (8) (6)
// | |
// | |
// 4------(7)-------3
//
protected void paintComponent(Graphics g) {
super.paintComponent(g); //paints the background and image
// Draw a rectangle on top of the image.
// g.setColor(Color.WHITE);
g.setXORMode(Color.white); //Color of line varies
((Graphics2D)g).setStroke(stroke);
//depending on image colors
g.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
public void mouseReleased(MouseEvent e) {
if (isDragging) {
updateFrame(e.getPoint());
}
}
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
public void mouseDragged(MouseEvent e) {
if (isDragging) {
updateFrame(e.getPoint());
}
}
boolean is(int who, int alt0, int alt1, int alt2) {
return who == alt0 || who == alt1 || who == alt2;
}
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
int[] oppositeX = new int[] { NE, N, NW, W, SW, S, SE, E };
int[] oppositeY = new int[] { SW, S, SE, E, NE, N, NW, W };
Cursor[] cursors = new Cursor[] {
Cursor.getPredefinedCursor(Cursor.NW_RESIZE_CURSOR),
Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR),
Cursor.getPredefinedCursor(Cursor.NE_RESIZE_CURSOR),
Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR),
Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR),
Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR),
Cursor.getPredefinedCursor(Cursor.SW_RESIZE_CURSOR),
Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR),
Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR),
};
String[] edgeName = new String[] { "NW", "N", "NE", "E", "SE", "S", "SW", "W" };
static final int NW = 0;
static final int N = 1;
static final int NE = 2;
static final int E = 3;
static final int SE = 4;
static final int S = 5;
static final int SW = 6;
static final int W = 7;
int edge = SE;
Rectangle frame = new Rectangle();
void updateFrame(Point p) {
frame = roi.getScreenRectangle();
if (is(edge, NW, W, SW)) {
frame.width += frame.x - p.x;
frame.x = p.x;
}
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
if (is(edge, NE, E, SE)) {
frame.width = p.x - frame.x;
}
public void mousePressed(MouseEvent e) {
int r = findRegion(e.getX(), e.getY());
if (r < 8) {
edge = r;
}
if (is(edge, NW, N, NE)) {
frame.height += frame.y - p.y;
frame.y = p.y;
}
public void mouseReleased(MouseEvent e) {
updateFrame(e.getX() + getX(), e.getY() + getY());
if (is(edge, SW, S, SE)) {
frame.height = p.y - frame.y;
}
public void mouseDragged(MouseEvent e) {
updateFrame(e.getX() + getX(), e.getY() + getY());
if (frame.width < 0) {
frame.x += frame.width;
frame.width = -frame.width;
edge = oppositeX[edge];
}
boolean is(int who, int alt0, int alt1, int alt2) {
return who == alt0 || who == alt1 || who == alt2;
}
int[] oppositeX = new int[] { NE, N, NW, W, SW, S, SE, E };
int[] oppositeY = new int[] { SW, S, SE, E, NE, N, NW, W };
Cursor[] cursors = new Cursor[] {
Cursor.getPredefinedCursor(Cursor.NW_RESIZE_CURSOR),
Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR),
Cursor.getPredefinedCursor(Cursor.NE_RESIZE_CURSOR),
Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR),
Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR),
Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR),
Cursor.getPredefinedCursor(Cursor.SW_RESIZE_CURSOR),
Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR),
Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR),
};
String[] edgeName = new String[] { "NW", "N", "NE", "E", "SE", "S", "SW", "W" };
static final int NW = 0;
static final int N = 1;
static final int NE = 2;
static final int E = 3;
static final int SE = 4;
static final int S = 5;
static final int SW = 6;
static final int W = 7;
int edge = SE;
Rectangle frame = new Rectangle();
void updateFrame(int x, int y) {
getBounds(frame);
if (is(edge, NW, W, SW)) {
frame.width += frame.x - x;
frame.x = x;
}
if (is(edge, NE, E, SE)) {
frame.width = x - frame.x;
}
if (is(edge, NW, N, NE)) {
frame.height += frame.y - y;
frame.y = y;
}
if (is(edge, SW, S, SE)) {
frame.height = y - frame.y;
}
if (frame.width < 0) {
frame.x += frame.width;
frame.width = -frame.width;
edge = oppositeX[edge];
}
if (frame.height < 0) {
frame.y += frame.height;
frame.height = -frame.height;
edge = oppositeY[edge];
}
setBounds(frame);
repaint();
if (frame.height < 0) {
frame.y += frame.height;
frame.height = -frame.height;
edge = oppositeY[edge];
}
roi.setScreenRectangle(frame);
repaint();
}
boolean within(int x, int target) {
return x >= target - resizeBand && x <= target + resizeBand;
}
int findRegion(int ex, int ey) {
int w = getWidth();
int h = getHeight();
int c = 8;
int findRegion(int ex, int ey) {
Rectangle r = roi.getScreenRectangle();
int c = 8;
if (ex > (w - resizeBand)) {
if (ey > (h - resizeBand)) {
c = SE;
} else if (ey < resizeBand) {
c = NE;
} else {
c = E;
}
} else if (ex < resizeBand) {
if (ey > (h - resizeBand)) {
c = SW;
} else if (ey < resizeBand) {
c = NW;
} else {
c = W;
}
if (within(ex, r.x + r.width)) {
if (within(ey, r.y + r.height)) {
c = SE;
} else if (within(ey, r.y)) {
c = NE;
} else {
if (ey > (h - resizeBand)) {
c = S;
} else if (ey < resizeBand) {
c = N;
} else {
c = 8;
}
c = E;
}
} else if (within(ex, r.x)) {
if (within(ey, r.y + r.height)) {
c = SW;
} else if (within(ey, r.y)) {
c = NW;
} else {
c = W;
}
} else {
if (within(ey, r.y + r.height)) {
c = S;
} else if (within(ey, r.y)) {
c = N;
} else {
c = 8;
}
return c;
}
public void mouseMoved(MouseEvent e) {
setCursor(cursors[findRegion(e.getX(), e.getY())]);
}
return c;
}
public void mouseMoved(MouseEvent e) {
setCursor(cursors[findRegion(e.getX(), e.getY())]);
}
static void log(String x) {
@ -430,11 +391,65 @@ public class Editor
}
static class Rect {
double top;
double left;
double bottom;
double right;
class Rect {
float top;
float left;
float bottom;
float right;
Rectangle cache = null;
public void setScreenRectangle(Rectangle frame) {
Point2D.Float screenTopLeft = new Point2D.Float(frame.x, frame.y);
Point2D.Float coordTopLeft = new Point2D.Float();
Point2D.Float screenBottomRight = new Point2D.Float(frame.x + frame.width, frame.y + frame.height);
Point2D.Float coordBottomRight = new Point2D.Float();
if (dirty) {
new Exception().printStackTrace(System.out);
}
screenToCoord.transform(screenTopLeft, coordTopLeft);
screenToCoord.transform(screenBottomRight, coordBottomRight);
top = coordTopLeft.y;
left = coordTopLeft.x;
bottom = coordBottomRight.y;
right = coordBottomRight.x;
// System.out.println("rect: " + left + ", " + top + ", " + right + ", " + bottom);
Rectangle stored = calculateScreenRectangle();
Rectangle delta = new Rectangle();
delta.x = frame.x - stored.x;
delta.y = frame.y - stored.y;
delta.width = frame.width - stored.width;
delta.height = frame.height - stored.height;
System.out.println("delta: " + delta);
cache = frame;
}
Rectangle calculateScreenRectangle() {
Point2D.Float coordTopLeft = new Point2D.Float(left, top);
Point2D.Float screenTopLeft = new Point2D.Float();
Point2D.Float coordBottomRight = new Point2D.Float(right, bottom);
Point2D.Float screenBottomRight = new Point2D.Float();
coordToScreen.transform(coordTopLeft, screenTopLeft);
if (dirty) {
new Exception().printStackTrace(System.out);
}
coordToScreen.transform(coordBottomRight, screenBottomRight);
int x = Math.round(screenTopLeft.x);
int y = Math.round(screenTopLeft.y);
int w = Math.round(screenBottomRight.x - screenTopLeft.x);
int h = Math.round(screenBottomRight.y - screenTopLeft.y);
return new Rectangle(x, y, w, h);
}
public Rectangle getScreenRectangle() {
if (cache == null) {
cache = calculateScreenRectangle();
}
return cache;
}
}
}