简体   繁体   中英

Adapt Rectangle's region to a different size

Under Windows Forms, I take a full size screenshot of a specific window that has a specific window size, I save it into a Bitmap object, then, I declared a Rectangle structure to crop a region of that Bitmap, because later I need to manipulate only a very specific part/region of the screenshot...

To make things simpler for this question, lets say the window and bitmap size is 640x480, the Rectangle's X,Y is: 436,150 and the Width,Height is: 146,170, and what I crop from the screenshot (the bitmap) is a balloon image. The window is a videogame.

The problem is that when the window size increase, the balloon image increase too, as obvious, so the x,y and width/height of my rectangle for a window size of 640x480 will not properly capture/crop the entire balloon image when the window of the game has a bigger size...

I need to know how can I calculate the x,y width/height that my rectangle should have to properly crop the balloon image when the window size changes. I need to adapt the rectangle.

So, if this is the predefined size and rectangle I have:

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

From that, the approximated adapted values that the rectangle should have to properly crop the same equivalent area in a window size of 800x600 and 1280x768 it would be more or less these:

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

...are just approximated values, but not perfect, because I did it manually since Im not sure which is the way to calculate and automate this math operation.

I hope my question and problem was understood. Thankyou in advance.

Try this:

if width 640:

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

if heigth 480:

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

Considering the size of the form as this.Width , and the height as 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);

Maybe you're over-thinking it, but all you need to do is capture the percentage change between the original size and the new size (for both X and Y), and then apply that percentage to the properties of the original rectangle to get the new rectangle.

For example:

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)
    };
}

Example usage:

// 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...");
}

Output

在此处输入图片说明

Given a source Bitmap and a selection Rectangle inside its boundaries:

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

When the SourceBitmap changes its size, the new size of the selection rectangle is calculated using the scale factor given by the relation between the old size and the new size of the 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);

With a SourceBitmap and a selection rectangle sized as:

RectangleF SourceRect = new RectangleF(0, 0, 640, 480);
RectangleF SelectionRect = new RectangleF(436, 150, 146, 170);

If the inflated bitmaps are sized as:

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

The Inflated selection with a scale factor of (1.25, 1.25) and (2, 1.6) will be (rounded down):

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM