This discussion is archived
5 Replies Latest reply: Mar 6, 2012 7:51 AM by 833392 RSS

Draw a line after zoom in

833392 Newbie
Currently Being Moderated
Hi All,

I want to draw a line after zooming in/out the image. If the image is not scaled, then ever thing is fine. But once I scaled the image and draw the line, the position is not coming correctly. Can you correct me, what's my mistake?
package imagetest;

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.*;

public class ZoomAndDraw extends JPanel
{
    private java.awt.image.BufferedImage image = null;
    private Line2D.Double line = null;
    private double scale = 1.0;
    private int value = 16;
    private double translateX = 0.0;
    private double translateY = 0.0;
    private MouseManager manager = null;

    public ZoomAndDraw()
    {
        line = new Line2D.Double();
        readImage();

        manager = new MouseManager(this);
        addMouseListener(manager);
        addMouseMotionListener(manager);
    }

    private void readImage()
    {
        try
        {
            image = javax.imageio.ImageIO.read(new java.io.File("D:/IMG.JPG"));
        }
        catch (Exception ex)
        {
        }
    }

    @Override
    public Dimension getPreferredSize()
    {
        if (image != null)
        {
            int w = (int) (scale * image.getWidth());
            int h = (int) (scale * image.getHeight());
            return new Dimension(w, h);
        }
        return new Dimension(640, 480);
    }

    @Override
    protected void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;

        if (image == null)
        {
            return;
        }

        double x = (getWidth() - scale * image.getWidth()) / 2;
        double y = (getHeight() - scale * image.getHeight()) / 2;
        g2.translate(x, y); // move to center of image
        g2.scale(scale, scale); // scale
        translateX = 0 - x * (1 / scale);
        translateY = 0 - y * (1 / scale);
        g2.translate(translateX, translateY); // move back
        g2.drawImage(image, 0, 0, this);

        g2.setColor(Color.RED);
        g2.draw(line);
        g.dispose();
    }

    public void setLine(Point start, Point end)
    {
        line.setLine(start, end);
        repaint();
    }

    public void addLine(Point start, Point end)
    {
        line.setLine(start, end);
        repaint();
    }

    public void ZoomIn()
    {
        value++;
        scale = (value + 4) / 20.0;
        revalidate();
        repaint();
    }

    public void ZoomOut()
    {
        if (value <= -3)
        {
            return;
        }

        value--;
        scale = (value + 4) / 20.0;
        revalidate();
        repaint();
    }

    class MouseManager extends MouseAdapter
    {
        ZoomAndDraw component;
        Point start;
        boolean dragging = false;

        public MouseManager(ZoomAndDraw displayPanel)
        {
            component = displayPanel;
        }

        @Override
        public void mousePressed(MouseEvent e)
        {
            start = e.getPoint();
            dragging = true;
        }

        @Override
        public void mouseReleased(MouseEvent e)
        {
            if (dragging)
            {
                component.addLine(start, e.getPoint());
                component.repaint();
            }
            dragging = false;
        }

        @Override
        public void mouseDragged(MouseEvent e)
        {
            Point end = e.getPoint();
            if (dragging)
            {
                component.setLine(start, end);
                component.repaint();
            }
            else
            {
                start = end;
            }
        }
    }

    public static void main(String[] args)
    {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        ZoomAndDraw zoomAndDraw = new ZoomAndDraw();

        //Zoom in call
        zoomAndDraw.ZoomIn();
        zoomAndDraw.ZoomIn();
        zoomAndDraw.ZoomIn();

        frame.add(zoomAndDraw);
        frame.setPreferredSize(new Dimension(640, 480));
        frame.setSize(new Dimension(640, 480));
        frame.setVisible(true);
    }
}
Thanks and Regards
Raja.
  • 1. Re: Draw a line after zoom in
    Maxideon Explorer
    Currently Being Moderated
    You're drawing the red line with the same transformation as that of the image. Try this,
    AffineTransform origTx = g2.getTransform();
    
    double x = (getWidth() - scale * image.getWidth()) / 2;
    double y = (getHeight() - scale * image.getHeight()) / 2;
    g2.translate(x, y); // move to center of image
    g2.scale(scale, scale); // scale
    g2.drawImage(image, 0, 0, this);
    
    g2.setTransform(origTx); //reset
    g2.setColor(Color.RED);
    g2.draw(line);
  • 2. Re: Draw a line after zoom in
    833392 Newbie
    Currently Being Moderated
    Hi Maxideon,

    Simply great. Thanks a lot. :)

    Regards
    Raja.
  • 3. Re: Draw a line after zoom in
    833392 Newbie
    Currently Being Moderated
    Hi,

    I'm having one more doubt. Just assume, after calling the ZoomIn(), I am drawing a line.
    Subsequent ZoomIn() calls (let's say 5 times), changed the actual line position. How do I synchronize the zoom in call with the line coordinates?
    public void FireZoomIn()
        {
            new Thread(new Runnable()
            {
                public void run()
                {
                    try
                    {
                        Thread.sleep(3000);
                    }
                    catch (InterruptedException iex)
                    {
                    }
                    int count = 0;
                    while (count++ < 5)
                    {
                        ZoomIn();
                    }
                }
            }).start();
        }
    
    .....
    
    public void mouseReleased(MouseEvent e)
            {
                if (dragging)
                {
                    component.addLine(start, e.getPoint());
                    component.repaint();
    
                    component.FireZoomIn();
                }
                dragging = false;
            }
    Thanks and Regards
    Raja.
  • 4. Re: Draw a line after zoom in
    Maxideon Explorer
    Currently Being Moderated
    Pick a fixed reference frame and save all coordinates in that frame. So for example, lets say I'm scaling everything by 2 and that the panel is so much bigger than the scaled image that the image gets offset by 50 pixels in the x-direction. I then mouse click

    (50,50) to (100,100)

    I have to change the coordinates of the line to

    (0,25) to (25,50)

    to represent untranslated and unscaled coordinates. I reverse transform the mouse coordinates no matter what the current transformation is and save the lines in the untranslated and unscaled (that is, 'normal') coordinate system. Then when I go to draw I apply the current transform and draw everything normally.
  • 5. Re: Draw a line after zoom in
    833392 Newbie
    Currently Being Moderated
    Hi Maxideon,

    Thank you once again. I'll try that. I'll post my code once I will finish that. If not I will come back with my doubts. Please help me out.

    Regards
    Raja.

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points