One approach, suggested here, is to rely on the graphics context's scale()
method and construct to an inverse transform to convert between mouse coordinates and image coordinates. In the example below, note how the original image is 256 x 256, while the displayed image is scaled by SCALE = 2.0
. The mouse is hovering over the center the image; the tooltip shows an arbitrary point in the display and the center point (127, 127) in the original.

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.geom.AffineTransform;
import java.awt.geom.NoninvertibleTransformException;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.JPanel;
/** @see https://stackoverflow.com/a/2244285/230513 */
public class InverseTransform {
private static final double SCALE = 2.0;
public static void main(String[] args) {
JFrame frame = new JFrame("Inverse Test");
BufferedImage image = getImage(256, 'F');
AffineTransform at = new AffineTransform();
at.scale(SCALE, SCALE);
frame.add(new ImageView(image, at));
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
private static BufferedImage getImage(int size, char c) {
final Font font = new Font("Serif", Font.BOLD, size);
BufferedImage bi = new BufferedImage(
size, size, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = bi.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setPaint(Color.white);
g2d.fillRect(0, 0, size, size);
g2d.setPaint(Color.blue);
g2d.setFont(font);
FontMetrics fm = g2d.getFontMetrics();
int x = (size - fm.charWidth(c)) / 2;
int y = fm.getAscent() + fm.getDescent() / 4;
g2d.drawString(String.valueOf(c), x, y);
g2d.setPaint(Color.black);
g2d.drawLine(0, y, size, y);
g2d.drawLine(x, 0, x, size);
g2d.fillOval(x - 3, y - 3, 6, 6);
g2d.drawRect(0, 0, size - 1, size - 1);
g2d.dispose();
return bi;
}
private static class ImageView extends JPanel {
private BufferedImage image;
private AffineTransform at;
private AffineTransform inverse;
private Graphics2D canvas;
private Point oldPt = new Point();
private Point newPt;
@Override
public Dimension getPreferredSize() {
return new Dimension( // arbitrary multiple of SCALE
(int)(image.getWidth() * SCALE * 1.25),
(int)(image.getHeight() * SCALE * 1.25));
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
try {
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
inverse = g2d.getTransform();
inverse.invert();
g2d.translate(this.getWidth() / 2, this.getHeight() / 2);
g2d.transform(at);
g2d.translate(-image.getWidth() / 2, -image.getHeight() / 2);
inverse.concatenate(g2d.getTransform());
g2d.drawImage(image, 0, 0, this);
} catch (NoninvertibleTransformException ex) {
ex.printStackTrace(System.err);
}
}
ImageView(final BufferedImage image, final AffineTransform at) {
this.setBackground(Color.lightGray);
this.image = image;
this.at = at;
this.canvas = image.createGraphics();
this.canvas.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
this.canvas.setColor(Color.BLACK);
this.addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseMoved(MouseEvent e) {
Point m = e.getPoint();
Point i = e.getPoint();
try {
inverse.inverseTransform(m, i);
setToolTipText("<html>Mouse: " + m.x + "," + m.y
+ "<br>Inverse: " + i.x + "," + i.y + "</html>");
} catch (NoninvertibleTransformException ex) {
ex.printStackTrace();
}
}
});
}
}
}