I need to be able to take a point on an image and convert it into a point relative to a picturebox with the pictureSizeMode set to zoom

here is the code that the picturebox uses to scale and center the image

Size size = this.image.Size;
 float num = Math.Min((float)(((float)base.ClientRectangle.Width) / ((float)size.Width)), (float)(((float)base.ClientRectangle.Height) / ((float)size.Height)));
 rectangle.Width = (int)(size.Width * num);
rectangle.Height = (int)(size.Height * num);
rectangle.X = (base.ClientRectangle.Width - rectangle.Width) / 2;
 rectangle.Y = (base.ClientRectangle.Height - rectangle.Height) / 2;
return rectangle;

I realize this returns a rectangle, but I need it to accept a point for example 0,0 on an image, if the image was tall it would be scaled by height so the the Y would stay 0 but if the image was say 359px wide and the picuture box was 417 pixles wide the point would go from 0,0 to 35,0.

I can get it to work so long as I use 0,0 but if I need other points I cant seem to make it happen. I'm not very good a geometry.

Any help would be appreciated.

you need to reverse the transformation that the zoom applies. So start by removing the translation , then reverse the scale:

NB. just for clarity, as i know English isnt everyones first language, in this case i mean translation as 'a uniform movement without rotation' in line with the Graphics.TranslateTransform() method :)

//use mouse click rather than click event to access e.Location
        private void pictureBox7_MouseClick(object sender, MouseEventArgs e)
        {
            Point imageLoc = ConvertToImage(e.Location, sender as PictureBox);

            MessageBox.Show("Clicked: " + e.Location.ToString() + Environment.NewLine
            + "Image: " + imageLoc.ToString());
        }

        private Point ConvertToImage(Point clicked, PictureBox control)
        {
            //get size of original image
            Size size = control.BackgroundImage.Size;
            //get value of scale
            float num = Math.Min((float)(((float)control.Width) / ((float)size.Width)), (float)(((float)control.Height) / ((float)size.Height)));

            //scale size to calculate translation
            size.Width = (int)(size.Width * num);
            size.Height = (int)(size.Height * num);
 
            //reverse translation
            clicked.X -= (control.Width - size.Width) / 2;
            clicked.Y -= (control.Height - size.Height) / 2;

            //reverse scale
            clicked.X = (int)(clicked.X / num);
            clicked.Y = (int)(clicked.Y / num);

            //return image coordinates
            return clicked;
        }

Ryshad, That is some beautiful code. And I appreciate the time you put into it. But I am afraid I didn't describe my problem correctly. I am having trouble going from the actual Image coordinates to the Picturebox coordinates as zoomed. That is, exactly what your method there does, just reversed. I want it to accept an Image coordinate and return a zoomed picturebox coordinate.

I need it so that I can keep a selection rectangle from going outside of the image. I have most of the code worked out for the most part. But I'm having trouble with this. Thanks for the efforts you have put in.

and ddanbe, I glanced at that code snippet and I don't have time to run through it to see what it does right now, but I will later tonight. I would really like to get this control taken care of. Its for a little freeware app I am working on to make it easier to quickly and easily edit and mail pictures to your friends and family!

Aah, i see what you need. Sorry, i assumed you were clicking on the zoomed image and needed to convert that back to the original image. Heres an overloaded method which will take a point/rectangle from the original image and convert it to match the zoomed image:

private Point ConvertToZoomed(Point image, PictureBox control)
        {
            //get size of original image
            Size size = control.BackgroundImage.Size;

            //get value of scale
            float num = Math.Min((float)(((float)control.Width) / ((float)size.Width)), (float)(((float)control.Height) / ((float)size.Height)));

            //scale size to calculate translation
            size.Width = (int)(size.Width * num);
            size.Height = (int)(size.Height * num);

            //apply scale to Point
            image.X = (int)(image.X * num);
            image.Y = (int)(image.Y * num);

            //apply translation to Point
            image.X += (control.Width - size.Width) / 2;
            image.Y += (control.Height - size.Height) / 2;

            //return Zoomed Point
            return image;

        }

        private Rectangle ConvertToZoomed(Rectangle selection, PictureBox control)
        {
            //get size of original image
            Size size = control.BackgroundImage.Size;

            //get value of scale
            float num = Math.Min((float)(((float)control.Width) / ((float)size.Width)), (float)(((float)control.Height) / ((float)size.Height)));

            //scale size to calculate translation
            size.Width = (int)(size.Width * num);
            size.Height = (int)(size.Height * num);

            //apply scale to Selection
            selection.X = (int)(selection.X * num);
            selection.Y = (int)(selection.Y * num);
            selection.Width = (int)(selection.Width * num);
            selection.Height = (int)(selection.Height * num);

            //apply translation to Selection
            selection.X += (control.Width - size.Width) / 2;
            selection.Y += (control.Height - size.Height) / 2;

            //return Zoomed Selection
            return selection;

        }
Comments
Great Code

Thanks! I haven't tested it yet. But everything looks right. Thank you very much! I never did very well with geometry, and I had been struggling with this for a few hours before I decided I needed to ask for help. It looks so much simpler now, broken into commented steps.

Thanks again!

This question has already been answered. Start a new discussion instead.