import java.awt.*;
import java.awt.event.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.*;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.event.*;
public class RelativeCoordinates extends JPanel implements ActionListener {
BufferedImage image;
Rectangle clip = new Rectangle(100,100,100,100);
AffineTransform at = new AffineTransform();
public RelativeCoordinates(BufferedImage image) {
this.image = image;
}
public void actionPerformed(ActionEvent e) {
String ac = e.getActionCommand();
if(ac.equals("ZOOM IN"))
setTransform();
if(ac.equals("RESET"))
at.setToIdentity();
repaint();
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g2.drawRenderedImage(image, at);
g2.setPaint(Color.red);
g2.draw(at.createTransformedShape(clip));
}
private void setTransform() {
double xScale = (double)getWidth()/(clip.width+1);
double yScale = (double)getHeight()/(clip.height+1);
double scale = Math.min(xScale, yScale); // scale to fit
Rectangle r = getBounds();
double x = r.getCenterX() - scale*clip.getCenterX();
double y = r.getCenterY() - scale*clip.getCenterY();
at.setToTranslation(x, y);
at.scale(scale, scale);
}
private JPanel getControlPanel() {
JPanel panel = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.weightx = 1.0;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridwidth = GridBagConstraints.REMAINDER;
panel.add(getZoomPanel(), gbc);
panel.add(getClipPanel(), gbc);
return panel;
}
private JPanel getZoomPanel() {
String[] ids = { "zoom in", "reset" };
JPanel panel = new JPanel();
for(int j = 0; j < ids.length; j++) {
JButton button = new JButton(ids[j]);
button.setActionCommand(ids[j].toUpperCase());
button.addActionListener(this);
panel.add(button);
}
return panel;
}
private JPanel getClipPanel() {
SpinnerNumberModel xModel = new SpinnerNumberModel(100, 0, 300, 1);
final JSpinner xSpinner = new JSpinner(xModel);
SpinnerNumberModel yModel = new SpinnerNumberModel(100, 0, 300, 1);
final JSpinner ySpinner = new JSpinner(yModel);
SpinnerNumberModel wModel = new SpinnerNumberModel(100, 50, 400, 1);
final JSpinner wSpinner = new JSpinner(wModel);
SpinnerNumberModel hModel = new SpinnerNumberModel(100, 50, 400, 1);
final JSpinner hSpinner = new JSpinner(hModel);
ChangeListener cl = new ChangeListener() {
public void stateChanged(ChangeEvent e) {
JSpinner spinner = (JSpinner)e.getSource();
int value = ((Integer)spinner.getValue()).intValue();
if(spinner == xSpinner)
clip.x = value;
if(spinner == ySpinner)
clip.y = value;
if(spinner == wSpinner)
clip.width = value;
if(spinner == hSpinner)
clip.height = value;
repaint();
}
};
JPanel panel = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(2,2,2,2);
gbc.weightx = 1.0;
addComponents(new JLabel("x"), xSpinner, panel, gbc, cl);
addComponents(new JLabel("y"), ySpinner, panel, gbc, cl);
addComponents(new JLabel("w"), wSpinner, panel, gbc, cl);
addComponents(new JLabel("h"), hSpinner, panel, gbc, cl);
return panel;
}
private void addComponents(Component c1, Component c2, Container c,
GridBagConstraints gbc, ChangeListener cl) {
gbc.anchor = GridBagConstraints.EAST;
c.add(c1, gbc);
gbc.anchor = GridBagConstraints.WEST;
c.add(c2, gbc);
((JSpinner)c2).addChangeListener(cl);
}
public static void main(String[] args) throws IOException {
String path = "images/owls.jpg";
BufferedImage image = ImageIO.read(new File(path));
RelativeCoordinates test = new RelativeCoordinates(image);
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(test);
f.getContentPane().add(test.getControlPanel(), "Last");
f.setSize(400,400);
f.setLocation(200,200);
f.setVisible(true);
}
}