如何将缩放图像上的 XY 坐标和高度/宽度转换为原始大小的图像?

发布于 2024-10-17 08:21:07 字数 1617 浏览 4 评论 0原文

相关问题

我是尝试做与链接问题中相同的事情,但使用 C#。我正在显示缩放图像并允许用户选择要裁剪的区域。但是,我不能只从缩放的图像选择中获取 x1y1、x2y2 坐标并从原始图像中进行裁剪。我尝试过像另一个问题一样做一些基本数学,但这显然也不是正确的方法(它肯定更接近)。

编辑

原始图像尺寸:w = 1024 h = 768

缩放图像尺寸:w = 550 h = 412

我从图像开始,例如1024x768 。我希望它能尽可能大地装入 550x550 的盒子中。我使用以下方法来获取缩放后的图像大小(同时保持纵横比)。然后我对这些新尺寸进行基本调整。

至于选择区域,它可以是 (0,0) 到 (100,100) 之间的任意值。

private static Rectangle MaintainAspectRatio(Image imgPhoto, Rectangle thumbRect)
{
    int sourceWidth = imgPhoto.Width; int sourceHeight = imgPhoto.Height; int sourceX = 0; int sourceY = 0; int destX = 0; int destY = 0;

    float nPercent = 0;
    float nPercentW = 0;
    float nPercentH = 0;

    nPercentW = ((float)thumbRect.Width / (float)sourceWidth);
    nPercentH = ((float)thumbRect.Height / (float)sourceHeight);

    //if we have to pad the height pad both the top and the bottom
    //with the difference between the scaled height and the desired height
    if (nPercentH < nPercentW)
    {
        nPercent = nPercentH;
        destX = (int)((thumbRect.Width - (sourceWidth * nPercent)) / 2);
    }
    else
    {
        nPercent = nPercentW;
        destY = (int)((thumbRect.Height - (sourceHeight * nPercent)) / 2);
    }

    int destWidth = (int)(sourceWidth * nPercent);
    int destHeight = (int)(sourceHeight * nPercent);

    Rectangle retRect = new Rectangle(thumbRect.X, thumbRect.Y, destWidth, destHeight);
    return retRect;
}

Related Question

I am trying to do the same thing as in the linked question, but with C#. I am showing a scaled image and am allowing a user to select an area to crop. However, I can't just take the x1y1, x2y2 coordinates from the scaled image selection and crop that from the original. I've tried doing some basic math like in the other question, but that's obviously not the right approach either (it's definitely closer).

Edit

Original Image Dimensions: w = 1024 h = 768

Scaled Image Dimensions: w = 550 h = 412

I start with an image, say 1024x768. I want it to fit as large as possible in a 550x550 box. I'm using the following method to get the scaled image size (while maintaining aspect ratio). Then I do a basic resize to those new dimensions.

As for a selection area, it can be anything (0,0) to (100,100).

private static Rectangle MaintainAspectRatio(Image imgPhoto, Rectangle thumbRect)
{
    int sourceWidth = imgPhoto.Width; int sourceHeight = imgPhoto.Height; int sourceX = 0; int sourceY = 0; int destX = 0; int destY = 0;

    float nPercent = 0;
    float nPercentW = 0;
    float nPercentH = 0;

    nPercentW = ((float)thumbRect.Width / (float)sourceWidth);
    nPercentH = ((float)thumbRect.Height / (float)sourceHeight);

    //if we have to pad the height pad both the top and the bottom
    //with the difference between the scaled height and the desired height
    if (nPercentH < nPercentW)
    {
        nPercent = nPercentH;
        destX = (int)((thumbRect.Width - (sourceWidth * nPercent)) / 2);
    }
    else
    {
        nPercent = nPercentW;
        destY = (int)((thumbRect.Height - (sourceHeight * nPercent)) / 2);
    }

    int destWidth = (int)(sourceWidth * nPercent);
    int destHeight = (int)(sourceHeight * nPercent);

    Rectangle retRect = new Rectangle(thumbRect.X, thumbRect.Y, destWidth, destHeight);
    return retRect;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

ぃ双果 2024-10-24 08:21:07

如果没有更多细节,我猜您实际上遇到了舍入错误......
- 当您将(上、左)坐标缩放回原始坐标时,您需要向下舍入(向左上方)。
- 当您将(右下)坐标缩放回原始坐标时,需要向上舍入(朝右下角)

取一个简单的示例,将 12x12 网格作为原始坐标,将 4x4 网格作为缩放后的版本。
- 缩放版本上的 (1,1):(2,2) = (3,3):(8,8)
- 2x2 像素 = 缩放版本面积的 25%
- 6x6 像素 = 原始版本面积的 25%

如果简单地乘以相同的缩放因子,则会得到 (3,3):(6,6)。

OriginalTop = INT(ScaledTop * YScalingFactor);
OriginalLeft = INT(ScaledLeft * XScalingFactor);

OriginalBottom = INT((ScaledBottom + 1) * YScalingFactor) - 1;
OriginalRight = INT((ScaledRight + 1) * XScalingFactor) - 1;

编辑

解释我想说的话的更好方法是画一张图。我对 ASCII 艺术很烂。所以这是另一种文字尝试。

像素不是一个点。它本身就是一个小矩形。

当您使用像素表示矩形的左上角时,您将包括来自像素最左上角的点的区域。

当您使用像素来表示矩形的右下时,您将该区域一直包含到像素的右下最点。

使用 (12x12) =>再次以 (4x4) 为例,每个缩放后的像素代表原始图像中的整个 3x3 像素集。当谈论左上角时,您选择原始中 3x3 像素组的左上角像素。当谈论右下角时,您选择原始中 3x3 像素组的右下角。

编辑:仅使用整数。

NewTop    = ((   OldTop    ) * NewHeight / OldHeight);
NewLeft   = ((   OldLeft   ) * NewWidth  / OldWidth );

NewBottom = ((OldBottom + 1) * NewHeight / OldHeight) - 1;
NewRight  = ((OldRight  + 1) * NewWidth  / OldWidth ) - 1;

唯一的考虑是确保乘法后数据类型不会溢出。但对于图像,你就不会,除非它是一个地狱般的图像。

Without a bit more detail, I'm guessing that you're actually suffering from rounding errors...
- When you scale the (top,left) co-ordinate back to the original, you need to round down (towards the top left).
- When you scale the (bottom,right) co-ordinate back to the original, you need to round up (towards the bottom right)

Take a simple example of a 12x12 grid as the original, and a 4x4 grid as the scaled version.
- (1,1):(2,2) on the scaled version = (3,3):(8,8)
- 2x2 pixel = 25% of the area of the scaled version
- 6x6 pixel = 25% of the area of the original version

If one was to simply multiply by the same scaling factors, this would give (3,3):(6,6).

OriginalTop = INT(ScaledTop * YScalingFactor);
OriginalLeft = INT(ScaledLeft * XScalingFactor);

OriginalBottom = INT((ScaledBottom + 1) * YScalingFactor) - 1;
OriginalRight = INT((ScaledRight + 1) * XScalingFactor) - 1;

EDIT:

A better way of explaining what I'm trying to say would be to draw a picutre. And I suck at ASCII Art. So here's another try with words.

A pixel isn't a point. It's a small rectangle in it's own right.

When you use a pixel to represent the top left of a rectangle, you're including the area from the top-left most Point of the pixel.

When you use a pixel to represent the Bottom Right of a rectangle, you're including the area all the way to the Bottom Right most Point of the pixel.

Using the (12x12) => (4x4) example again, every scaled pixel represents a whole 3x3 set of pixels in the original. When talking about the top left, you pick the top left pixel of the 3x3 pixel group in the original. And when talking about the bottom right, you pick the bottom right of the 3x3 pixel group in the original.

EDIT: Using just integers.

NewTop    = ((   OldTop    ) * NewHeight / OldHeight);
NewLeft   = ((   OldLeft   ) * NewWidth  / OldWidth );

NewBottom = ((OldBottom + 1) * NewHeight / OldHeight) - 1;
NewRight  = ((OldRight  + 1) * NewWidth  / OldWidth ) - 1;

The only consideration is making sure that you don't overflow your data type after the multiplication. But with images, you won't, unless it's a hell of an image.

⒈起吃苦の倖褔 2024-10-24 08:21:07

您可以获得缩放图像的百分比位置,并将它们转换回未缩放图像的坐标:

pX1 = scaledX1/scaled_width
pY1 = scaledY1/scaled_height

unscaledX1 = ceiling(unscaled_width * pX1)
unscaledY1 = ceiling(unscaled_height * pY1)

You can get the percent locations for the scaled images and turn them back into coords for the unscaled image:

pX1 = scaledX1/scaled_width
pY1 = scaledY1/scaled_height

unscaledX1 = ceiling(unscaled_width * pX1)
unscaledY1 = ceiling(unscaled_height * pY1)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文