From bcc46597c9743e24097ce66ce82598a1ab3ab8c3 Mon Sep 17 00:00:00 2001 From: knut Date: Sat, 21 Apr 2007 22:23:51 +0000 Subject: [PATCH] Selection rectangle "roi" working. --- src/album/editor/Editor.java | 453 ++++++++++++++++++----------------- 1 file changed, 234 insertions(+), 219 deletions(-) diff --git a/src/album/editor/Editor.java b/src/album/editor/Editor.java index fb9c6f5..440d324 100644 --- a/src/album/editor/Editor.java +++ b/src/album/editor/Editor.java @@ -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(); + g.transform(this.coordToScreen); - AffineTransform screenToCoord = new AffineTransform(); - screenToCoord.translate(side/2d, side/2d); - screenToCoord.scale(side, side); - - g.transform(screenToCoord); - 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; + } } }