[java] Scaling question.

Started by
-1 comments, last by darrinps 20 years, 8 months ago
I posted this in the Graphics Theory area, but since my code is in Java, I thought that it might be a good idea to have it here. I am developing an application that allows users to draw lines on images. The images can be zoomed in and out. The Problem: ------------ When I draw a line on an image that is its original size, everything works just fine, but if I draw a line on an image that the user first scales either + or -, then the line that gets drawn is off in the Y direction, and is wrong in scale. If the scale/zoom was greater than 100%, then the line that gets drawn is too long and too high if the points chosen were in the upper half of the image. If the points chosen were below the mid point of the image, then the line that gets drawn is too low, and still too long. The center point of the line is in the correct location in both cases. If the scale/zoom was less than 100%, then the line that gets drawn is too short and too low if the points chosen were in the upper half of the image. If the points chosen were below the mid point of the image, then the line that gets drawn is too high, and still too short. The center point of the line is still correct though. Note that this is progressive for the offset, but not the scale. In other words, the further the points chosen are from the center of the image, the further off the Y axis is, but this does not affect the line length...it is constnatly too short or too long. Both the line length and Y axis are affected proportionally to the increase or decrease in image size. The more the image is zoomed one way or the other, the more the error in the Y direction will be, and the more the error in the line's length will be seen. What I'm trying to do: ---------------------- What I am doing is getting points where the user clicks on the screen to draw a line. The image is centered on the screen, but the image that gets drawn onto isn't where the image is shown so the points need to be translated. To get the proper point, I traslate by subtracting 1/2 of the view port size minus 1/2 of the original image size. In short: newX = xAxisClickPoint - (portWidth / 2) - (originalImageWidth / 2) newY = yAxisClickPoint - (portHeight / 2) - (originalImageHeight / 2) After this is done, then I call a method to apply the translation, and scaling. Here is the import parts of my coe if that will help. Note that the most interesting parts are marked with "!!!" Any thoughts as to what I am doing wrong would be GREATLY appreciated. Thanks.

    private void drawLine()
    {
        m_jsPane = (JScrollPane) m_tabbedPane.getSelectedComponent();
        m_port = m_jsPane.getViewport();

        GrabAndScrollLabel gnsLabel = (GrabAndScrollLabel) m_port.getView();

        m_currentImageIcon = (ImageIcon) gnsLabel.getIcon();

        m_currentImage = m_currentImageIcon.getImage();

        try
        {
            MediaTracker tracker = new MediaTracker(this);
            tracker.addImage(m_currentImage, 0);
            tracker.waitForID(0);
        }
        catch (InterruptedException ie)
        {
            System.out.println("Interupted in draw");
        }

        int iw = m_currentImage.getWidth(this);
        int ih = m_currentImage.getHeight(this);

        m_buffIm = new BufferedImage(iw, ih, BufferedImage.TYPE_INT_RGB);

        big = m_buffIm.createGraphics();

        big.drawImage(m_currentImage, 0, 0, this);

        //!!! Here is where the points get translated
        Point oldPoint = new Point(m_startX, m_startY);
        Point point1   = resetPoint(oldPoint);

        oldPoint.x = m_endX;
        oldPoint.y = m_endY;

        Point point2 = resetPoint(oldPoint);

        OraLine oraLine = new OraLine(point1, point2, Color.BLUE);

        gnsLabel.getOraImage().getImageModHolder().addShape(oraLine);

        final GrabAndScrollLabel gnsFinal = gnsLabel;

        ImageIcon icon = (ImageIcon) gnsLabel.getIcon();
        ImageIcon newIcon = new ImageIcon(icon.getImage())
        {
            public void paintIcon(Component c, Graphics g, int x, int y)
            {
              super.paintIcon(c, g, x, y);
               
              //!!! Here is the call that gets the changes introduced
              gnsFinal.applyModifications((Graphics2D)g, x, y);
            }
        };

        gnsLabel.setIcon(newIcon);

        m_port.setView(gnsLabel);

        m_jsPane.setViewport(m_port);

        getRootPane().revalidate();
        getRootPane().repaint();
    }

private Point resetPoint(Point oldPoint)
    {
        JScrollPane jsp = (JScrollPane) m_tabbedPane.getSelectedComponent();
        JViewport port = jsp.getViewport();
        GrabAndScrollLabel gnsLabel = (GrabAndScrollLabel) m_port.getView();

        double nImgWidth  = gnsLabel.getOraImage().getOriginalImageWidth();
        double nImgHeight = gnsLabel.getOraImage().getOriginalImageHeight();

        Point newPoint = SwingUtilities.convertPoint(jsp, oldPoint, gnsLabel);

        int nPortWidth  = port.getWidth();
        int nPortHeight = port.getHeight();

        //!!! Here is the offset calculation
        double xOffset = (nPortWidth / 2) - (nImgWidth / 2);
        double yOffset = (nPortHeight / 2) - (nImgHeight / 2);

        if(port.getHeight() < gnsLabel.getHeight())
        {
          //Shunken viewport in vertical direction...no offset
            newPoint.y = oldPoint.y;
        }
        else
        {
            //Apply offset in y direction
            newPoint.y -= yOffset;
        }

        if(port.getWidth() < gnsLabel.getWidth())
        {
          //Shunken viewport in horizontal direction...no offset
            newPoint.x = oldPoint.x;
        }
        else
        {
            //Apply offset in x direction
            newPoint.x -= xOffset;
        }

        return new Point(newPoint);
    }


//This does the translations and scaling
public BufferedImage applyModifications(Graphics2D g2D, int xTrans, int yTrans)
    {
      ImageIcon icon = oraImage.getImageIcon();
      BufferedImage bi = new BufferedImage(icon.getIconWidth(),
                                           icon.getIconHeight(),
                                           BufferedImage.TYPE_INT_ARGB);

      ImageModHolder mods = oraImage.getImageModHolder();

      //!!!
      g2D.translate(xTrans, yTrans);
      g2D.rotate(mods.getRotation());
      g2D.scale(mods.getZoomFactor(), mods.getZoomFactor());

      Iterator shapeIter = mods.getShapeList().iterator();

      while(shapeIter.hasNext())
      {
        OraShape shape = (OraShape)shapeIter.next();
        shape.draw(g2D);
      }

      return bi;
    }
   
Here is an attempt to show what it looks like.

---------------------------------------
|                                     |
|                                     |
|                                     |
|                                     |
|                                     |
|                                     |
|                                     |
|                                     |
|                                     |
|                                     |
|                  __                 | 10%
|                ______               | 20%
|              __________             | 30%
|            ______________           | 40%
|          __________________         | 50%
|        ______________________       | 60%
|      __________________________     | 70%
|    ______________________________   | 80%
|  __________________________________ | 90%
|_____________________________________| 100
---------------------------------------
 
You would get something that looks just like this if you clicked on the very bottom left edge of the image as a start point, and the very bottom right edge as an end point starting at 100% (original size), then going down to 90% and doing the same thing...all the way to 10%. [edited by - darrinps on August 11, 2003 5:45:55 PM] [edited by - darrinps on August 11, 2003 5:46:47 PM]

This topic is closed to new replies.

Advertisement