【问题标题】:Adapt Rectangle's region to a different size将 Rectangle 的区域调整为不同的大小
【发布时间】:2018-05-15 20:04:55
【问题描述】:

在 Windows 窗体下,我截取具有特定窗口大小的特定窗口的全尺寸屏幕截图,将其保存到 Bitmap 对象中,然后,我声明了一个 Rectangle 结构来裁剪该 Bitmap 的一个区域,因为稍后我只需要操作屏幕截图的一个非常特定的部分/区域...

为了让这个问题更简单,假设窗口和位图大小为 640x480,矩形的 X,Y 为:436,150,宽度,高度为:146,170,我从屏幕截图(位图)中裁剪的是气球图像。这个窗口是一个电子游戏。

问题在于,当窗口大小增加时,气球图像也会增加,这很明显,因此对于 640x480 的窗口大小,我的矩形的 x、y 和宽度/高度将无法正确捕获/裁剪整个气球图像当游戏窗口变大时...

我需要知道如何计算我的矩形在窗口大小发生变化时正确裁剪气球图像所需的 x,y 宽度/高度。我需要调整矩形。

所以,如果这是我预定义的大小和矩形:

{ new Size(640, 480), new Rectangle(436, 150, 146, 170) }

据此,矩形在 800x600 和 1280x768 的窗口大小中正确裁剪相同等效区域时应具有的近似适应值或多或少如下:

{ new Size(800, 600), new Rectangle(546, 186, 186, 212) }
{ new Size(1280, 768), new Rectangle(830, 232, 240, 274) }

...只是近似值,但并不完美,因为我不确定这是计算和自动化此数学运算的方法,因此我是手动完成的。

我希望我的问题和问题得到理解。提前谢谢你。

【问题讨论】:

    标签: c# .net winforms gdi+


    【解决方案1】:

    也许您想多了,但您需要做的就是捕捉原始尺寸和新尺寸(X 和 Y)之间的百分比变化,然后将该百分比应用于原始尺寸的属性矩形来获取新的矩形。

    例如:

    public static Rectangle GetNewRectangle(Size oldSize, Rectangle oldRectangle, 
        Size newSize)
    {
        var percentChangeX = (double)newSize.Width / oldSize.Width;
        var percentChangeY = (double)newSize.Height / oldSize.Height;
    
        return new Rectangle
        {
            X = (int)(oldRectangle.X * percentChangeX),
            Y = (int)(oldRectangle.Y * percentChangeY),
            Width = (int)(oldRectangle.Width * percentChangeX),
            Height = (int)(oldRectangle.Height * percentChangeY)
        };
    }
    

    示例用法:

    // Helper method to display size and rectangle properties
    private static string GetDisplayValues(Size size, Rectangle rect)
    {
        return $" - size: {size.Width} x {size.Height}\n" +
               $" - rect: {rect.X}, {rect.Y} : {rect.Width} x {rect.Height}\n";
    }
    
    private static void Main()
    {
        var size = new Size(640, 480);
        var rect = new Rectangle(436, 150, 146, 170);                        
        Console.WriteLine($"Original:\n{GetDisplayValues(size, rect)}");
    
        var newSize = new Size(800, 600);
        var newRect = GetNewRectangle(size, rect, newSize);
        Console.WriteLine($"Resized:\n{GetDisplayValues(newSize, newRect)}");
    
        GetKeyFromUser("\nDone! Press any key to exit...");
    }
    

    输出

    【讨论】:

    • 感谢您的回答。对于 4:3 的纵横比工作正常,就像在你的例子中一样,但是对于 16:9 的纵横比(比如 1280x768),它给了我一个与我需要裁剪的区域不对应的“X”和“宽度”。这就是为什么我想太多了,这个问题的所有其他答案都是同样的问题。只是一个问题:您认为这是计算比例因子的算法的逻辑问题,或者确定这可能是关于当纵横比分辨率发生变化时游戏如何管理对象位置/大小的问题?
    • 抱歉 16:9 我的意思是 5:3。从 4:3 长宽比到 5:3
    • 我不知道您为什么认为裁剪区域不正确?如果我输入一个新的大小1280x768,我会得到一个新的矩形:872, 240 : 292 x 272。我没有在“现实生活”中测试的好方法,但我打开 mspaint.exe 并在0, 0 : 640 x 480 处绘制了一个彩色矩形,并在其中绘制了一个大小为436, 150 : 146 x 170 的“选择区域”框。然后我选择了彩色区域并将其调整为1280 x 768。内部“选择区域”的大小被调整为我上面的代码输出的确切尺寸。您能否提供不正确的具体数据?
    • 感谢您的澄清和测试。在我的问题中,您可以看到矩形相对应具有 1280x768 的值的近似值,但是 872 的 X 坐标远大于 830,并且宽度值相同,所以我得到的矩形使用这个1280x768 的通用百分比因子计算是“错误的”,这意味着 X 和宽度应该更小以裁剪我需要的部分,但别担心,我认为这应该是关于游戏如何处理纵横比 /不同纵横比的项目位置/大小。
    • 这就是为什么我很困惑,过度思考它的原因,因为我试图以与您的解决方案和其他人的解决方案相同的方式计算比例因子,但我注意到我的当应用于不同的纵横比时,生成的矩形是不正确的,然后我在 StackOverflow 中结束了询问,因为我认为也许我计算得不好。但是您的代码当然可以,现在我发现问题出在视频游戏本身上。感谢您的帮助。
    【解决方案2】:

    试试这个:

    如果宽度为 640:

    X = 436 / 640 = 0.68125 (68.125%)
    W = 146 / 640 = 0.22125 (22.125%)
    

    如果身高 480:

    Y = 150 / 480 = 0.3125 (31.25%)
    H = 170 / 480 = 0.3541666666666666666666666667 (35.41666666666666666666666667%)
    

    考虑表单的大小为this.Width,高度为this.Height

    decimal pX = 0.68125;
    decimal pW = 0.22125;
    decimal pY = 0.3125;
    decimal pH = 0.3541666666666666666666666667;
    
    Rectangle rect = new Rectangle(this.Width * pX, this.Height * pY, this.Width * pW, this.Height * pH);
    

    【讨论】:

      【解决方案3】:

      给定一个源位图和一个在其边界内的选择矩形:

      RectangleF SourceRect = new Rectangle(Point.Empty, SourceBitmap.Size);
      Rectangle SelectionRect = new Rectangle([Point], [Size]);
      

      SourceBitmap改变其大小时,选择矩形的新大小是使用SourceBitmap的旧大小和新大小之间的关系给出的比例因子计算的:

      RectangleF DestinationRect = new RectangleF(Point.Empty, InflatedBitmap.Size); 
      
      SizeF ScaleFactor = new SizeF(DestinationRect.Width / SourceRect.Width, 
                                    DestinationRect.Height / SourceRect.Height);
      
      PointF NewPosition = new PointF(SelectionRect.X * ScaleFactor.Width, SelectionRect.Y * ScaleFactor.Height);
      SizeF NewSize = new SizeF(SelectionRect.Width * ScaleFactor.Width, SelectionRect.Height * ScaleFactor.Height);
      
      RectangleF InflatedSelection = new RectangleF(NewPosition, NewSize);
      

      使用 SourceBitmap 和大小为:

      的选择矩形
      RectangleF SourceRect = new RectangleF(0, 0, 640, 480);
      RectangleF SelectionRect = new RectangleF(436, 150, 146, 170);
      

      如果膨胀位图的大小为:

      RectangleF DestinationRect1 = new RectangleF(0, 0, 800, 600);
      RectangleF DestinationRect2 = new RectangleF(0, 0, 1280, 768);
      

      比例因子为(1.25, 1.25)(2, 1.6) 的膨胀选择将是(向下舍入):

      RectangleF InflatedSelection1 = new RectangleF(545, 187, 182, 212);
      RectangleF InflatedSelection2 = new RectangleF(872, 240, 292, 272);
      

      【讨论】:

        猜你喜欢
        • 2014-02-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多