在缩放模式 Picturebox 中平移矩形位置 [英] Translate Rectangle Position in Zoom Mode Picturebox

查看:20
本文介绍了在缩放模式 Picturebox 中平移矩形位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在确定图像中的矩形区域并在图片框中将其显示给用户.
由于图像有时可能非常大,因此我使用的是其 SizeMode 设置为 Zoom 的 PictureBox.

我正在使用以下代码来转换矩形 (X, Y) 坐标:

public Point TranslateZoomMousePosition(点坐标){//测试以确保我们的图像不为空if (pictureBox5.Image == null) 返回坐标;//确保我们的控件宽度和高度不是 0 并且我们的//图片宽高不为0if (pictureBox5.Width == 0 || pictureBox5.Height == 0 || pictureBox5.Image.Width == 0 || pictureBox5.Image.Height == 0) 返回坐标;//这是一个有点棘手的问题.本质上,需要检查//图像的纵横比与控件的纵横比//确定它是如何呈现的float imageAspect = (float)pictureBox5.Image.Width/pictureBox5.Image.Height;float controlAspect = (float)pictureBox5.Width/pictureBox5.Height;浮动新X =坐标.X;浮动新Y =坐标.Y;if (imageAspect > controlAspect){//这意味着我们受到宽度的限制,//意味着图像从左到右填满了整个控件float ratioWidth = (float)pictureBox5.Image.Width/pictureBox5.Width;newX *= ratioWidth;浮动比例 = (float)pictureBox5.Width/pictureBox5.Image.Width;float displayHeight = scale * pictureBox5.Image.Height;float diffHeight = pictureBox5.Height - displayHeight;差异高度/= 2;newY -= diffHeight;newY/= 比例;}别的{//这意味着我们受到高度的限制,//意思是图片从上到下填满了整个控件float ratioHeight = (float)pictureBox5.Image.Height/pictureBox5.Height;newY *= ratioHeight;浮动比例 = (float)pictureBox5.Height/pictureBox5.Image.Height;float displayWidth = scale * pictureBox5.Image.Width;float diffWidth = pictureBox5.Width - displayWidth;diffWidth/= 2;newX -= diffWidth;newX/= 比例;}返回新点((int)newX,(int)newY);}

在确定的位置添加框架控件:

pictureBox5.Controls.Clear();var c = new FrameControl();c.Size = new Size(myrect.Width, myrect.Height);c.Location=TranslateZoomMousePosition(newPoint(myrect.Location.X,myrect.Location.Y));pictureBox5.Controls.Add(c);

但是确定的框架/矩形位置不正确.
我做错了什么?

更新:我正在尝试使用类似的代码将图像上的矩形转换为图片框上的框架控件

public Rectangle GetRectangeOnPictureBox(PictureBox p, Rectangle selectionRect,Bitmap bit){var method = typeof(PictureBox).GetMethod("ImageRectangleFromSizeMode",System.Reflection.BindingFlags.NonPublic |System.Reflection.BindingFlags.Instance);var imageRect = (Rectangle)method.Invoke(p, new object[] { p.SizeMode });if (p.Image == null)返回选择矩形;int cx = bit.Width/imageRect.Width;int cy = bit.Height/imageRect.Height;矩形 trsRectangle = new Rectangle(selectionRect.X * cx, selectionRect.Y * cy, selectionRect.Width * cx, selectionRect.Height * cy);trsRectangle.Offset(imageRect.X, imageRect.Y);返回 trsRectangle;}

这会产生无效的结果.请指教

解决方案

您可以通过这种方式将图片框上的选定矩形转换为图像上的矩形:

public RectangleF GetRectangeOnImage(PictureBox p, Rectangle selectionRect){var method = typeof(PictureBox).GetMethod("ImageRectangleFromSizeMode",System.Reflection.BindingFlags.NonPublic |System.Reflection.BindingFlags.Instance);var imageRect = (Rectangle)method.Invoke(p, new object[] { p.SizeMode });if (p.Image == null)返回选择矩形;var cx = (float)p.Image.Width/(float)imageRect.Width;var cy = (float)p.Image.Height/(float)imageRect.Height;var r2 = Rectangle.Intersect(imageRect, selectionRect);r2.Offset(-imageRect.X, -imageRect.Y);return new RectangleF(r2.X * cx, r2.Y * cy, r2.Width * cx, r2.Height * cy);}

注意:您可以找到 ImageRectangleFromSizeMode 方法

这是结果:

I'm determining the rectangular area in an image and showing it to the user in a PictureBox.
Since the image can sometimes be very large, I'm using a PictureBox with its SizeMode set to Zoom.

I'm using the following code to translate the Rectangle (X, Y) coordinates:

public Point TranslateZoomMousePosition(Point coordinates)
{
    // test to make sure our image is not null
    if (pictureBox5.Image == null) return coordinates;
    // Make sure our control width and height are not 0 and our 
    // image width and height are not 0
    if (pictureBox5.Width == 0 || pictureBox5.Height == 0 || pictureBox5.Image.Width == 0 || pictureBox5.Image.Height == 0) return coordinates;
    // This is the one that gets a little tricky. Essentially, need to check 
    // the aspect ratio of the image to the aspect ratio of the control
    // to determine how it is being rendered
    float imageAspect = (float)pictureBox5.Image.Width / pictureBox5.Image.Height;
    float controlAspect = (float)pictureBox5.Width / pictureBox5.Height;
    float newX = coordinates.X;
    float newY = coordinates.Y;
    if (imageAspect > controlAspect)
    {
        // This means that we are limited by width, 
        // meaning the image fills up the entire control from left to right
        float ratioWidth = (float)pictureBox5.Image.Width / pictureBox5.Width;
        newX *= ratioWidth;
        float scale = (float)pictureBox5.Width / pictureBox5.Image.Width;
        float displayHeight = scale * pictureBox5.Image.Height;
        float diffHeight = pictureBox5.Height - displayHeight;
        diffHeight /= 2;
        newY -= diffHeight;
        newY /= scale;
    }
    else
    {
        // This means that we are limited by height, 
        // meaning the image fills up the entire control from top to bottom
        float ratioHeight = (float)pictureBox5.Image.Height / pictureBox5.Height;
        newY *= ratioHeight;
        float scale = (float)pictureBox5.Height / pictureBox5.Image.Height;
        float displayWidth = scale * pictureBox5.Image.Width;
        float diffWidth = pictureBox5.Width - displayWidth;
        diffWidth /= 2;
        newX -= diffWidth;
        newX /= scale;
    }
    return new Point((int)newX, (int)newY);
}

Adding a frame control at the determined position:

pictureBox5.Controls.Clear();
var c = new FrameControl();
c.Size = new Size(myrect.Width, myrect.Height);
c.Location=TranslateZoomMousePosition(newPoint(myrect.Location.X,myrect.Location.Y));
pictureBox5.Controls.Add(c);

But the determined frame/rectangle location is not correct.
What am I i doing wrong?

Update: I'm trying to translate a Rectangle on an image to a Frame Control on a PictureBox using similar code

public Rectangle GetRectangeOnPictureBox(PictureBox p, Rectangle selectionRect,Bitmap bit)
    {
        var method = typeof(PictureBox).GetMethod("ImageRectangleFromSizeMode",
            System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
        var imageRect = (Rectangle)method.Invoke(p, new object[] { p.SizeMode });
        if (p.Image == null)
            return selectionRect;
        int cx = bit.Width / imageRect.Width;
        int cy = bit.Height / imageRect.Height;
        Rectangle trsRectangle = new Rectangle(selectionRect.X * cx, selectionRect.Y * cy, selectionRect.Width * cx, selectionRect.Height * cy);

        trsRectangle.Offset(imageRect.X, imageRect.Y);
        return trsRectangle;
    }

This produces invalid result.Please advice

解决方案

You can translate selected rectangle on the picture box to the rectangle on image this way:

public RectangleF GetRectangeOnImage(PictureBox p, Rectangle selectionRect)
{
    var method = typeof(PictureBox).GetMethod("ImageRectangleFromSizeMode",
        System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
    var imageRect = (Rectangle)method.Invoke(p, new object[] { p.SizeMode });
    if (p.Image == null)
        return selectionRect;
    var cx = (float)p.Image.Width / (float)imageRect.Width;
    var cy = (float)p.Image.Height / (float)imageRect.Height;
    var r2 = Rectangle.Intersect(imageRect, selectionRect);
    r2.Offset(-imageRect.X, -imageRect.Y);
    return new RectangleF(r2.X * cx, r2.Y * cy, r2.Width * cx, r2.Height * cy);
}

Note: You can find ImageRectangleFromSizeMode method source code here and use it as write such method as part of your application code.

Example - Crop Image of PictureBox having SizeMode = Zoom

As an example, the following code will crop the given rectangle of the picture box 1 and will set the result as image of picture box 2:

var selectedRectangle = new Rectangle(7, 30, 50, 40);
var result = GetRectangeOnImage(pictureBox1, selectedRectangle);
using (var bm = new Bitmap((int)result.Width, (int)result.Height))
{
    using (var g = Graphics.FromImage(bm))
        g.DrawImage(pictureBox1.Image, 0, 0, result, GraphicsUnit.Pixel);
    pictureBox2.Image = (Image)bm.Clone();
}

Here is the input image:

And this is the result:

这篇关于在缩放模式 Picturebox 中平移矩形位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆