5 Replies Latest reply: Mar 6, 2012 9:51 AM by 833392 RSS

    Draw a line after zoom in

    833392
      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
          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
            Hi Maxideon,

            Simply great. Thanks a lot. :)

            Regards
            Raja.
            • 3. Re: Draw a line after zoom in
              833392
              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
                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
                  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.