如何检索 WinForms PictureBox 的缩放因子?

Posted

技术标签:

【中文标题】如何检索 WinForms PictureBox 的缩放因子?【英文标题】:How to retrieve zoom factor of a WinForms PictureBox? 【发布时间】:2012-05-15 11:01:16 【问题描述】:

我需要鼠标指针在 PictureBox 上的精确位置。

我使用 PictureBox 的 MouseMove 事件。

在这个 PictureBox 上,我使用“缩放”属性来显示图像。

在原始(未缩放)图像上获取鼠标位置的正确方法是什么?

有没有办法找到比例因子并使用它?

我认为需要使用 imageOriginalSize/imageShowedSize 来检索这个比例因子。

我使用这个功能:

float scaleFactorX = mypic.ClientSize.Width / mypic.Image.Size.Width;
float scaleFactorY = mypic.ClientSize.Height / mypic.Image.Size.Height;

是否可以使用该值来获取光标在图像上的正确位置?

【问题讨论】:

我想你可以试试: Point cursorPosition = mypic.PointToClient(Cursor.Position);点 positionOverImage = new Point(cursorPosition.X / scaleFactorX, cursorPosition.Y / scaleFactorY);。但是,我想当您使用这种方法计算缩放因子时,可能会出现一些准确性问题。我建议您自行缩放图像。 谢谢,但不起作用。位置不正确,使用pointtoclient和eventmouseargs位置时我得到相同的值。 请贴出代码 sn-p 计算您当前使用的坐标。 矩形 sourceRec = new Rectangle((int)(e.X / currentScale), (int)(e.Y / currentScale), 1, 1); 当您说您需要鼠标相对于未拉伸图像的坐标时,您希望未拉伸图像具有的锚点是什么?是固定在左上角吗?锚定在中心? 【参考方案1】:

我今天必须解决同样的问题。我希望它适用于任何宽度:高度比的图像。

这是我在原始全尺寸图像上找到点“unscaled_p”的方法。

            Point p = pictureBox1.PointToClient(Cursor.Position);
            Point unscaled_p = new Point();

            // image and container dimensions
            int w_i = pictureBox1.Image.Width; 
            int h_i = pictureBox1.Image.Height;
            int w_c = pictureBox1.Width;
            int h_c = pictureBox1.Height;

第一个技巧是确定图像相对于容器是水平还是垂直更大,这样您就可以知道哪个图像尺寸完全填满了容器。

            float imageRatio = w_i / (float)h_i; // image W:H ratio
            float containerRatio = w_c / (float)h_c; // container W:H ratio

            if (imageRatio >= containerRatio)
            
                // horizontal image
                float scaleFactor = w_c / (float)w_i;
                float scaledHeight = h_i * scaleFactor;
                // calculate gap between top of container and top of image
                float filler = Math.Abs(h_c - scaledHeight) / 2;  
                unscaled_p.X = (int)(p.X / scaleFactor);
                unscaled_p.Y = (int)((p.Y - filler) / scaleFactor);
            
            else
            
                // vertical image
                float scaleFactor = h_c / (float)h_i;
                float scaledWidth = w_i * scaleFactor;
                float filler = Math.Abs(w_c - scaledWidth) / 2;
                unscaled_p.X = (int)((p.X - filler) / scaleFactor);
                unscaled_p.Y = (int)(p.Y / scaleFactor);
            

            return unscaled_p;

请注意,由于缩放使图像居中,因此必须考虑“填充”长度以确定图像未填充的尺寸。结果“unscaled_p”是未缩放图像上与“p”相关的点。

希望有帮助!

【讨论】:

完美解决一个小错误:对于比例,您不应该使用完整控件的宽度和高度,而是使用 Control.ClientSize 的宽度和高度,所以没有边框。很多时候,差异并不明显,直到您显示边框并进行一些计算。您会看到一些像素丢失了【参考方案2】:

如果我对你的理解正确,我相信你会想做这样的事情:

假设:PictureBox 适合图像的宽度/高度,PictureBox 的边框与实际图像之间没有空间。

ratioX = e.X / pictureBox.ClientSize.Width;
ratioY = e.Y / pictureBox.ClientSize.Height;

imageX = image.Width * ratioX;
imageY = image.Height * ratioY;

这应该会给你原始图像中像素的点。

【讨论】:

我错过了(float)的比率,这样做,目前如果你说有var ratioX,那么它很可能是int,意思是ratioX/Y将永远是零。

以上是关于如何检索 WinForms PictureBox 的缩放因子?的主要内容,如果未能解决你的问题,请参考以下文章

C# WinForms | Picturebox白色出血右侧和底部边缘

如何捕捉面板上的鼠标滚轮?

如何在面板上捕获鼠标滚轮?

c#picturebox指向文件系统

WinForms:如何显示 Usb3 Vision 网络摄像头的输出

错题解析