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 public class Editor
extends JComponent extends JComponent
implements MouseListener, MouseMotionListener
{ {
// Given from input image // Given from input image
BufferedImage img; BufferedImage img;
double imgScale; // coordinates per bitmap pixel double imgScale; // coordinates per bitmap pixel
Rectangle imgRec;
// What we choose // What we choose
double rotation; // radians double rotation; // radians
@ -32,30 +32,29 @@ public class Editor
int side; int side;
// other // other
// AffineTransform t; AffineTransform screenToCoord;
CropFrame mask; AffineTransform coordToScreen;
boolean dirty = true;
// CropFrame mask;
public Editor(BufferedImage img) { public Editor(BufferedImage img) {
this.img = img; this.img = img;
int w = img.getWidth(); int w = img.getWidth();
int h = img.getHeight(); int h = img.getHeight();
imgScale = 1d / Math.sqrt(w * w + h * h); 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); Dimension size = new Dimension(680, 680);
setPreferredSize(size); setPreferredSize(size);
setMinimumSize(size); setMinimumSize(size);
setMaximumSize(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; rotation = 0.0;
Rectangle initialMask = new Rectangle(100, 100, 200, 200); Rectangle initialMask = new Rectangle(100, 100, 200, 200);
@ -67,18 +66,21 @@ public class Editor
add(mask); add(mask);
SelectionEditor ml = new SelectionEditor(); SelectionEditor ml = new SelectionEditor();
addMouseListener(ml);
addMouseMotionListener(ml);
*/ */
addMouseListener(this);
addMouseMotionListener(this);
} }
void resize(double newScale) { void rescale(double newScale) {
scale = newScale; scale = newScale;
side = (int)Math.round(scale / imgScale); side = (int)Math.round(scale / imgScale);
Dimension size = new Dimension(side, side); Dimension size = new Dimension(side, side);
dirty = true;
roi.cache = null;
System.out.println("Side: " + side);
setSize(size); setSize(size);
setPreferredSize(size); setPreferredSize(size);
setMinimumSize(size); setMinimumSize(size);
@ -91,67 +93,53 @@ public class Editor
protected void paintComponent(Graphics g1) { protected void paintComponent(Graphics g1) {
super.paintComponent(g1); super.paintComponent(g1);
Graphics2D g = (Graphics2D)g1; if (dirty) {
AffineTransform orig = g.getTransform(); System.out.println("Recalculating");
AffineTransform screenToCoord = new AffineTransform(); AffineTransform screenToCoord = new AffineTransform();
screenToCoord.translate(side/2d, side/2d); screenToCoord.translate(side/2d, side/2d);
screenToCoord.scale(side, side); screenToCoord.scale(side, -side);
g.transform(screenToCoord); 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();
g.transform(this.coordToScreen);
AffineTransform imageToCoord = new AffineTransform(); AffineTransform imageToCoord = new AffineTransform();
imageToCoord.rotate(rotation * Math.PI / 180d); imageToCoord.rotate(rotation * Math.PI / 180d);
imageToCoord.scale(imgScale * scale, imgScale * scale); imageToCoord.scale(imgScale, -imgScale);
imageToCoord.translate(-img.getWidth()/2d, -img.getHeight()/2d); imageToCoord.translate(-img.getWidth()/2d, -img.getHeight()/2d);
g.drawImage(img, imageToCoord, this); g.drawImage(img, imageToCoord, this);
// Crosshair // Crosshair
/*
g.setStroke(new BasicStroke(0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 1f, new float[] { 0.005f, 0.005f }, 0)); 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.5, 0, 0.5, 0));
g.draw(new Line2D.Double(0, -0.5, 0, 0.5)); g.draw(new Line2D.Double(0, -0.5, 0, 0.5));
*/
g.setTransform(orig); g.setTransform(orig);
g.setXORMode(Color.white); //Color of line varies 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.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() { JComponent createControlPanel() {
@ -203,7 +191,7 @@ public class Editor
int value = zoomSlider.getValue(); int value = zoomSlider.getValue();
if (value != previousValue) { if (value != previousValue) {
previousValue = value; previousValue = value;
resize(value * 0.01); rescale(value * 0.01);
} }
} }
}); });
@ -228,8 +216,10 @@ public class Editor
reader.setInput(iis, true); reader.setInput(iis, true);
ImageReadParam param = reader.getDefaultReadParam(); ImageReadParam param = reader.getDefaultReadParam();
// param.setSourceSubsampling(8, 8, 0, 0); // param.setSourceSubsampling(8, 8, 0, 0);
BufferedImage raw = reader.read(0, param); final BufferedImage raw = reader.read(0, param);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Editor x = new Editor(raw); Editor x = new Editor(raw);
JFrame frame = new JFrame("Editor"); JFrame frame = new JFrame("Editor");
@ -243,92 +233,63 @@ public class Editor
frame.pack(); frame.pack();
frame.setVisible(true); frame.setVisible(true);
} }
});
}
final int resizeBand = 3;
static class CropFrame extends JComponent implements MouseListener, MouseMotionListener { boolean isDragging = false;
/**
*/
private static final long serialVersionUID = 1L;
private int resizeBand = 6;
Stroke stroke = new BasicStroke(1f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 1f, new float[] { 5f, 5f }, 0); Stroke stroke = new BasicStroke(1f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 1f, new float[] { 5f, 5f }, 0);
public CropFrame()
{
setOpaque(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 mouseClicked(MouseEvent e) { public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub // noop
} }
public void mouseEntered(MouseEvent e) { public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub // noop
} }
public void mouseExited(MouseEvent e) { public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub // noop
} }
public void mousePressed(MouseEvent e) { public void mousePressed(MouseEvent e) {
int r = findRegion(e.getX(), e.getY()); int r = findRegion(e.getX(), e.getY());
if (r < 8) { if (r < 8) {
edge = r; edge = r;
isDragging = true;
} else {
isDragging = false;
} }
} }
public void mouseReleased(MouseEvent e) { public void mouseReleased(MouseEvent e) {
updateFrame(e.getX() + getX(), e.getY() + getY()); if (isDragging) {
updateFrame(e.getPoint());
}
} }
public void mouseDragged(MouseEvent e) { public void mouseDragged(MouseEvent e) {
updateFrame(e.getX() + getX(), e.getY() + getY()); if (isDragging) {
updateFrame(e.getPoint());
}
} }
boolean is(int who, int alt0, int alt1, int alt2) { boolean is(int who, int alt0, int alt1, int alt2) {
return who == alt0 || who == alt1 || who == alt2; return who == alt0 || who == alt1 || who == alt2;
} }
int[] oppositeX = new int[] { NE, N, NW, W, SW, S, SE, E }; int[] oppositeX = new int[] { NE, N, NW, W, SW, S, SE, E };
int[] oppositeY = new int[] { SW, S, SE, E, NE, N, NW, W }; int[] oppositeY = new int[] { SW, S, SE, E, NE, N, NW, W };
Cursor[] cursors = new Cursor[] { Cursor[] cursors = new Cursor[] {
@ -354,21 +315,21 @@ public class Editor
int edge = SE; int edge = SE;
Rectangle frame = new Rectangle(); Rectangle frame = new Rectangle();
void updateFrame(int x, int y) { void updateFrame(Point p) {
getBounds(frame); frame = roi.getScreenRectangle();
if (is(edge, NW, W, SW)) { if (is(edge, NW, W, SW)) {
frame.width += frame.x - x; frame.width += frame.x - p.x;
frame.x = x; frame.x = p.x;
} }
if (is(edge, NE, E, SE)) { if (is(edge, NE, E, SE)) {
frame.width = x - frame.x; frame.width = p.x - frame.x;
} }
if (is(edge, NW, N, NE)) { if (is(edge, NW, N, NE)) {
frame.height += frame.y - y; frame.height += frame.y - p.y;
frame.y = y; frame.y = p.y;
} }
if (is(edge, SW, S, SE)) { if (is(edge, SW, S, SE)) {
frame.height = y - frame.y; frame.height = p.y - frame.y;
} }
if (frame.width < 0) { if (frame.width < 0) {
frame.x += frame.width; frame.x += frame.width;
@ -380,37 +341,39 @@ public class Editor
frame.height = -frame.height; frame.height = -frame.height;
edge = oppositeY[edge]; edge = oppositeY[edge];
} }
setBounds(frame); roi.setScreenRectangle(frame);
repaint(); repaint();
} }
boolean within(int x, int target) {
return x >= target - resizeBand && x <= target + resizeBand;
}
int findRegion(int ex, int ey) { int findRegion(int ex, int ey) {
int w = getWidth(); Rectangle r = roi.getScreenRectangle();
int h = getHeight();
int c = 8; int c = 8;
if (ex > (w - resizeBand)) { if (within(ex, r.x + r.width)) {
if (ey > (h - resizeBand)) { if (within(ey, r.y + r.height)) {
c = SE; c = SE;
} else if (ey < resizeBand) { } else if (within(ey, r.y)) {
c = NE; c = NE;
} else { } else {
c = E; c = E;
} }
} else if (ex < resizeBand) { } else if (within(ex, r.x)) {
if (ey > (h - resizeBand)) { if (within(ey, r.y + r.height)) {
c = SW; c = SW;
} else if (ey < resizeBand) { } else if (within(ey, r.y)) {
c = NW; c = NW;
} else { } else {
c = W; c = W;
} }
} else { } else {
if (ey > (h - resizeBand)) { if (within(ey, r.y + r.height)) {
c = S; c = S;
} else if (ey < resizeBand) { } else if (within(ey, r.y)) {
c = N; c = N;
} else { } else {
c = 8; c = 8;
@ -423,18 +386,70 @@ public class Editor
setCursor(cursors[findRegion(e.getX(), e.getY())]); setCursor(cursors[findRegion(e.getX(), e.getY())]);
} }
}
static void log(String x) { static void log(String x) {
System.out.println(x); System.out.println(x);
} }
static class Rect { class Rect {
double top; float top;
double left; float left;
double bottom; float bottom;
double right; 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;
}
} }
} }