none
C# zoom problems RRS feed

  • Question

  • All,

    I am still having problem with Zoom. I make a small program, that when I click, it zooms in to a picture. the problem I am  having is  after I zoom  the 1st time getting the  right values to do the next zoom in a new location I did not zoom to the place place. This  is because I am  get the back the round location when  I click. I tried doing a slope of a line equation, but it is still not working.

    here is my code: 

      private void pictureBox1_Click(object sender, EventArgs e)
            {
                MouseEventArgs arg = (MouseEventArgs)e;
    
    
    
                if (zoomFactor > 15)
                {
                    zoomFactor = 15;
                    return;
    
                }
               
                float M = zoomFactor - 1;
                float Bx = arg.Location.X - (M * Xclick);
                float By = arg.Location.Y - (M* yclick);
                float NewX = (arg.Location.X - Bx) /M;
                float NewY = (arg.Location.Y - By) /M;
    
                if (zoomFactor == 1)
                {
                    NewX = arg.Location.X;
                }
    
                if (zoomFactor == 1)
                {
                    NewY = arg.Location.Y;
                } 
    
                Xclick = NewX;
                yclick = NewY;
    
    
    
                CalXTXT.Text = Convert.ToString(NewX);
                CalYTXT.Text = Convert.ToString(NewY);
    
    
                zoomFactor = zoomFactor * 1.5F;
                imagex = Xclick * (-1) * (zoomFactor - 1F);
                imagey = yclick * (-1) * (zoomFactor - 1F);
    
                imgWidthTXT.Text = Convert.ToString(pictureBox1.Width * zoomFactor);
                imgHeightTXT.Text = Convert.ToString(pictureBox1.Height * zoomFactor);
    
    
                imgWidth = pictureBox1.Width * zoomFactor;
                imgHeight = pictureBox1.Height * zoomFactor;
    
    
    
                //  Zoom(zoom, ImageX, ImageY);
                Updatenow = true;
                Panflag = false;
                RecalcImage = true;
                pictureBox1.Refresh();
            }
    
    
    
    
    
    
           private void pictureBox1_Paint(object sender, PaintEventArgs e)
            {
                if (Updatenow)
                {
                    Graphics g = e.Graphics;
                    Rectangle rect = this.ClientRectangle;
                    Pen borderPen = new Pen(borderColor, 1);
    
    
    
    
                    // g.DrawRectangle(borderPen, rect.X, rect.Y, rect.Width - 1, rect.Height - 1);
                    if (RecalcImage)
                    {
                        if (Panflag)
                        {
                            Console.WriteLine(" Zoom Factor is " + zoomFactor);
                            if (rect.Width < imgWidth)
                                imagex = (zoomPointX * (-1) * (zoomFactor - 1));
                            else
                                imagex = (float)(rect.Width - imgWidth) / 2;
    
                            if (rect.Height < imgHeight)
                                imagey = (zoomPointY * (-1) * (zoomFactor - 1));
                            else
                                imagey = (float)(rect.Height - imgHeight) / 2;
    
                            Panflag = false;
                        }
    
    
    
                        g.DrawImage(currentFrame, imagex, imagey, imgWidth, imgHeight);
                        //  currentFrame = (Bitmap) pictureBox2.Image; ;
                        Updatenow = false;
                    }
    
                }
    
            }
    
    
    
    
    

    Can some one help me ?

    Thursday, April 2, 2020 2:33 AM

All replies

  • Hi btb900,

    Thank you for posting here.

    Please take a look at these articles to see if their code can give you new ideas.

    A Beautiful Magnifying Glass Effect of Image in WinForm

    PictureBox Zoom

    Note: This response contains a reference to a third party World Wide Web site. Microsoft is providing this information as a convenience to you. Microsoft does not control these sites and has not tested any software or information found on these sites; Therefore, Microsoft cannot make any representations regarding the quality, safety, or suitability of any software or information found there. There are inherent dangers in the use of any software found on the Internet, and Microsoft cautions you to make sure that you completely understand the risk before retrieving any software from the Internet.

    Best Regards,

    Timon


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Thursday, April 2, 2020 6:21 AM
  • thanks,

    so I download the code for PictureBox Zoom and I do not think that programs works. I download the other program a it was a lot more userful, but his never tries to find the points in the zooms. So I do not help me with that.

    Sunday, April 5, 2020 11:21 PM
  • You have not made it clear what you are expecting.  It can be quite tricky to keep the coordinate systems straight.

    Let's say you have a 640x480 window, and you are zoomed in 10:1 with the upper left corner is 100,100.  So:

    Screen 0,0 => image 100,100
    Screen 640,0 => Image 164,100
    Screen 0.480 => Image 100,148
    Screen 640,480 => Image 164,148.

    Now, let's say your user clicks in the very middle.  That's screen 320,240, which is 132,124 in the image.  What do you want the program to do next?

    You might consider having a general purpose function to translate screen coordinates to image coordinates, and vice versa.


    Tim Roberts | Driver MVP Emeritus | Providenza &amp; Boekelheide, Inc.

    Monday, April 6, 2020 12:18 AM
  •  I was told that G.Draw handled the different screen sizes.  but I want to be able to click in a area and zoom in and then click in a new area and zoom in again where I click at... but I cannot seem to find the new area x and y, so zoom in there...

     
    Monday, April 6, 2020 2:29 AM
  • You didn't answer my question.

    Graphics.Draw handles different screen and window sizes just fine, but Graphics.Draw isn't involved with your mouse at all.  The coordinates you get are raw screen pixel coordinates, and it is entirely up to you to figure out what they mean to your application.

    It's just math.  I'll show this to you in individual steps, but this can all be combined into one formula.

    So, you know that arg.Location.X and Y have the window coordinates of your click.  Assuming zoomFactor is accurate, that means the image coordinates of that click are

        clickPoint.X = zoomPoint.X + arg.Location.X / zoomFactor
        clickPoint.Y = zoomPoint.Y + arg.Location.Y / zoomFactor

    Right?  If zoomFactor is 3, then each pixel on your screen is 1/3 pixel on the image. And if I read between the lines of your code, zoomPoint.X and Y are the image coordinate of the upper left pixel.

    That's really it. Just set your new zoomPoint and multiply the zoomFactor by 1.5.


    Tim Roberts | Driver MVP Emeritus | Providenza &amp; Boekelheide, Inc.

    Monday, April 6, 2020 3:30 AM
  •  so

    what is zoomPoint.X and zoomPoint.Y ? I have an  zoomPointX and zoomPointY but they are just Yclick and Xclick. 

            float zoomPointX,  zoomPointY;
    
    
    
            public void Zoom(float zoomFactor, float zoomPointX, float zoomPointY)
            {
                this.zoomFactor = zoomFactor;
                //zoomPosition = zoomPoint;
                RecalcImage = true;
                this.zoomPointX = zoomPointX;
                this.zoomPointY = zoomPointY;
            }
    
    I passed the with zoom.
    Monday, April 6, 2020 4:46 AM
  •    float zoom = this zoomFactor;
                Xclick = imagex + arg.Location.X / zoom;
                yclick = imagey + arg.Location.Y / zoom;
    

    I tried this but it did not work. Meaning could not zoom in to  a new area after  I clicked on it. so just zoom in somewhere else 

    I used imagex and imagey because  of this:

        try
                                    {
                                        g.DrawImage(currentFrame, imagex, imagey, imgWidth, imgHeight);
                                    
                                    }
                                    catch (Exception err)
                                    {
                                      
                                    }
    

     that are used in this function 
    Monday, April 6, 2020 5:28 AM
  • Look, you need two pieces of information: the point in the image that maps to (0,0) in your window, and the zoom factor.  Given those two pieces of information, you can display the zoomed image.

    When you get a click, all you need to do is recompute those two things and trigger a repaint.  It looks like you were using zoomPointX and Y to be the start point of the image.


    Tim Roberts | Driver MVP Emeritus | Providenza &amp; Boekelheide, Inc.

    Monday, April 6, 2020 6:28 AM
  • so the problem i that is I do this 

     

      imagex = (zoomPointX * (-1) * (zoomFactor - 1));
      imagey = ( zoomPointY * (-1) * (zoomFactor -1));

        imgWidth = pictureBox1.Width * zoomFactor;
                imgHeight = pictureBox1.Height * zoomFactor;

    zoomPointX and zoomPointY is just where the user clicks at, so g.Draw will start during the bitmap at 

    negative where you click at. This means that the where you click at will start in the same location in the picture book and eveything else will change.
    the problem is, I do not know what the X and Y points from the bitmap will be at (0,0) on the picturebox. 

     g.DrawImage(currentFrame, imagex, imagey, imgWidth, imgHeight);

    so I click on 100 100 , on a picture that is is 500 X 500, with a zoom = 1.5 then DrawImage will draw from   -100 X -100 to   750, 750 . But since the picture box is only from 0,0 to 500 500
    parts of the bitmap will not be displayed.

    I am sure that is how click and Zoom works in picture boxes with g.DrawImages.
    I could be wrong.

    Anyhow, I do not know what x and y points from the bitmap will be at the picturebox's (0, 0) location.
    I do not even know how to find it.

    I know how to find what X and Y points from the bitmap that will be at  (PictureBox.Width, PictureBox.Heigth) of the pictureBox , I think.
    it is :
           float oldWidth = picturebox.Width;
                   float oldHeight = picturebox.Height;

                   float newWidth = zoomFactor * oldWidth;
                   float newHeight = zoomFactor * oldHeight; 
    stopPointX =  (oldWidth -  imagex / newWigth)  *  oldWidth;
    and that will where the  X point from the Bitmap that  will  be at the width of the picturebox. I think.

    what do you think ?

    but if you do  negative where you click at  times  zoomFactor - 1 and have:
     imgWidth = pictureBox1.Width * zoomFactor;
                imgHeight = pictureBox1.Height * zoomFactor;

    then 

     g.DrawImage(currentFrame, imagex, imagey, imgWidth, imgHeight)

    will keep where you click at on the bitmap in the same location in the Picturebox.
    and everything else will change, so  from a user point of view, it looks like it zoom in to where you click at. 

    so  I am sure that :

    public void DrawImage (System.Drawing.Image image, int x, int y, int width, int height);

    will start drawing the image at the given x and the Y of the picture box( in my case).

    what do you think Tim?

    Monday, April 6, 2020 2:19 PM
  • > the problem is, I do not know what the X and Y
    > points from the bitmap will be at (0,0) on the
    > picturebox.

    Then you are tracking the wrong information.

    > so I click on 100 100 , on a picture that is is 500 X 500,
    > with a zoom = 1.5 then DrawImage will draw from   
    > -100 X -100 to   750, 750 . But since the picture box is
    > only from 0,0 to 500 500 parts of the bitmap will not
    > be displayed.

    Write this down on paper.  You can figure out what information you need.  Let's say you start displaying a 500x500 image at a zoom of 1.  So the "picture offset" is 0,0, the zoom is 1.  You click on 100,100.  Since the zoom is 1, you clicked at 100,100 in the image.  NOW, your "picture offset" is (100,100) and the zoom is 1.5.

    Now let's say you click at (100,100) again.  So, what point in the image does that map to?  Because of the zoom factor, we know that -- in IMAGE coordinates -- that's 100/1.5 x 100/1.5 from the upper left, which is 66.6,66.6.  But we now from our "picture offset" that the upper left is really 100x100 in image coordinates.

    So, the NEW picture offset is 100+66.6 x 100+66.6, and the NEW zoomfactor is 2.25.  Your 500,500 window (in screen coordinates) will show 166x166 through 389x389 (in image coordinates).

    Don't you see the math?  As long as you know the "picture offset" (which is the image coordinate at 0,0) and the zoom factor, you can do any translation that you need.  It's easy.


    Tim Roberts | Driver MVP Emeritus | Providenza &amp; Boekelheide, Inc.



    Monday, April 6, 2020 6:51 PM
  • Tim,

    just want to see if we are on the same page here. but if you click on (100, 100) the second time.

    the values in still (100, 100)  for both the bmp and the picturebox. Right ? because of all my testing if you click on a location, to zoom in, that location stays the same, no mater how many times you click on it. do you agree ?

    So the thing I am lost at, is if you off set is (100,100) when you click on it again, that you are saying you really click on (100 + 100 /1.5) which is 133 and that is not right,  because where you click at does not move. it stay in the same location  for both the bmp and the picturebox. 

    so the bmp location for (100, 100) is he picturebox location for (100, 100)  and it only changes if you click somewhere else,

    do you have any example code that works ? because I am lost right now.

      

    Monday, April 6, 2020 8:29 PM
  • could you give me the mathematical equation you're talking about?
    Monday, April 6, 2020 8:59 PM
  • ok I tied this :
       public   float fOffsetX = 0.0f;
           public  float fOffsetY = 0.0f;
    
            public float fStartPanX = 0.0F;
            public float fStartPanY = 0.0F;
            bool panflag;
          
            float fScaleX = 1.0F;
            float fScaleY = 1.0F;
            float fMouseX;
            float fMouseY;
    
            float fMouseCurrentFrameX_AfterZoom;
            float fMouseCurrentFrameY_AfterZoom;
            float fMouseCurrentFrameX_BeforeZoom;
            float fMouseCurrentFrameY_BeforeZoom;
            public void Zoom(float zoomFactor, float zoomPointX, float zoomPointY)
            {
    
    
                VideoPlayerToCurrentFrame(zoomPointX, zoomPointY, out fMouseCurrentFrameX_BeforeZoom, out fMouseCurrentFrameY_BeforeZoom);
    
                this.zoomPointX = fMouseCurrentFrameX_BeforeZoom;
                this.zoomPointY = fMouseCurrentFrameY_BeforeZoom;
    
                this.zoomFactor = zoomFactor;
             
                RecalcImage = true;
                fScaleX =  zoomFactor;
                fScaleY = zoomFactor;
              
    
                VideoPlayerToCurrentFrame(zoomPointX, zoomPointY, out fMouseCurrentFrameX_AfterZoom, out fMouseCurrentFrameY_AfterZoom);
    
                fOffsetX += (fMouseCurrentFrameX_BeforeZoom - fMouseCurrentFrameX_AfterZoom );
                fOffsetY += (fMouseCurrentFrameY_BeforeZoom - fMouseCurrentFrameY_AfterZoom );
             
    
            }
    
    
    
    
    
    
    
    
    
    
    
            void CurrentFrameToVideoPlayer( float fVideoX, float fVideoY, out float nVideoPlayerX, out float nVideoPlayerY)
            {
                nVideoPlayerX = (fVideoX - fOffsetX) * fScaleX;
                nVideoPlayerY = (fVideoY - fOffsetY) * fScaleY;
            }
    
            void VideoPlayerToCurrentFrame(float nVideoPlayerX, float nVideoPlayerY, out float fVideoX, out float fVideoY)
            {
                fVideoX = (float)((nVideoPlayerX) / (fOffsetX + fScaleX));
                fVideoY = (float)((nVideoPlayerY) / (fOffsetY + fScaleY));
            }
    
    
    but it is still not working ...
    Thursday, April 9, 2020 6:00 AM