14

相关问题

我正在尝试做与链接问题相同的事情,但使用 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;
}
4

2 回答 2

12

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

以 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 Art。所以这是另一个用词的尝试。

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

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

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


再次使用 (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;


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

于 2011-02-14T16:57:32.043 回答
0

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

pX1 = scaledX1/scaled_width
pY1 = scaledY1/scaled_height

unscaledX1 = ceiling(unscaled_width * pX1)
unscaledY1 = ceiling(unscaled_height * pY1)
于 2011-02-14T16:53:28.410 回答