【问题标题】:Downscaling a Rectangle to Display as it would look in the Large Original Image缩小矩形以显示它在大原始图像中的样子
【发布时间】:2019-05-23 09:33:36
【问题描述】:

我在PictureBox 中显示图像,并允许用户通过提供矩形的宽度和高度来指定图像中的区域。矩形的位置以编程方式确定。

图片框中显示的图像已按比例缩小以节省处理时间。因此,如果用户指定 200X200 矩形,这在预览图像中可能看起来很大,但在原始图像中会非常小,可能非常大。

如何缩小或转换矩形以显示它在大图像中的外观。目前我正在使用以下代码来放大大图像中的矩形。请建议。

Rectangle ConvertToLargeRect(Rectangle smallRect, Size largeImageSize, Size smallImageSize)
{
    double xScale = (double)largeImageSize.Width / smallImageSize.Width;
    double yScale = (double)largeImageSize.Height / smallImageSize.Height;
    int x = (int)(smallRect.X * xScale + 0.5);
    int y = (int)(smallRect.Y * yScale + 0.5);
    int right = (int)(smallRect.Right * xScale + 0.5);
    int bottom = (int)(smallRect.Bottom * yScale + 0.5);
    return new Rectangle(x, y, right - x, bottom - y);
}

更新:

【问题讨论】:

  • 能否请您添加插图或输入/预期输出?对我来说,有点不清楚你在找什么。
  • 第二件事,PictureBox 是问题的重要部分吗?因为我在方法中没有看到图片框的任何用法,虽然它可能很重要。根据图片框的大小模式,图片框图像矩形可能位于不同的位置,而不是 (0,0),这样会影响缩小/放大矩形的位置。我们应该考虑图片框大小模式/图像矩形,还是应该忽略它并坚持大小?
  • @RezaAghaei 我正在准备一些插图,请稍等。不需要考虑图片框大小模式,因为它将在此处使用您的代码处理stackoverflow.com/a/53800590/848968。它将始终处于缩放模式。
  • @RezaAghaei 请检查更新。

标签: c# .net winforms system.drawing


【解决方案1】:

我将使用以下方法:

  • TranslatePictureBoxSelectedRectangleToImage
    将图片框上选定的矩形转换为图像上的坐标。

  • TranslateImageSelectedRectangleToPictureBox
    将图像框上的选定矩形转换为图片框上的坐标。

  • ScaleRectangle
    按给定的比例因子缩放矩形。

TranslatePictureBoxSelectedRectangleToImage

public RectangleF TranslatePictureBoxSelectedRectangleToImage(PictureBox p, 
    RectangleF pictureBoxSelectedRectangle)
{
    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 pictureBoxSelectedRectangle;
    var cx = (float)p.Image.Width / (float)imageRect.Width;
    var cy = (float)p.Image.Height / (float)imageRect.Height;
    var r2 = pictureBoxSelectedRectangle;
    r2.Offset(-imageRect.X, -imageRect.Y);
    return new RectangleF(r2.X * cx, r2.Y * cy, r2.Width * cx, r2.Height * cy);
}

TranslateImageSelectedRectangleToPictureBox

public RectangleF TranslateImageSelectedRectangleToPictureBox(PictureBox p, 
    RectangleF imageSelectedRectangle)
{
    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 imageSelectedRectangle;
    var cx = (float)p.Image.Width / (float)imageRect.Width;
    var cy = (float)p.Image.Height / (float)imageRect.Height;
    var r2 = new RectangleF(imageSelectedRectangle.X / cx, imageSelectedRectangle.Y / cy,
        imageSelectedRectangle.Width / cx, imageSelectedRectangle.Height / cy);
    r2.Offset(imageRect.X, imageRect.Y);
    return r2;
}

比例矩形

public RectangleF ScaleRectangle(RectangleF r, float c)
{
    return new RectangleF(r.X * c, r.Y * c, r.Width * c, r.Height * c);
}

示例

在以下假设下使用上述方法:

  • 您有 image1 的原始大小和 image2,这是 image1 的编程调整大小版本,缩放系数为 c。 (意思是c = (float)image2.Width/(float)image1.Width。)
  • 您正在以缩放模式在图片框中显示image2

问题 1 - 将 r1 作为 picureBox1 上的选定矩形,image1 上的矩形大小和位置是多少?

第一种方法展示了如何将图片框上的r1 转换为image2 上的矩形。要将其转换为image1 上的矩形,由于您知道用于从 image1 创建 image2 的缩放因子,因此对第一种方法的结果应用相同的缩放因子就足够了:

//First convert rectangle of pictureBox1 to rectangle of image2
var r2 = TranslatePictureBoxSelectedRectangleToImage(pictureBox1, r1);

//Then convert rectangle of image2 to rectangle of image1
var result = ScaleRectangle(r2, 1f/c);

问题 2 - 将 r1 作为 image1 上的选定矩形,pictureBox1 上的矩形大小和位置是多少?

第二种方法显示了如何将image2 上的r1 转换为pictureBox1 上的矩形。要从 image1 上的矩形进行转换,因为您知道用于从 image1 创建 image2 的缩放因子,因此在 r1 上应用相同的缩放因子以获取 image2 上的矩形就足够了,然后使用第二个方法:

//First convert rectangle of the image1 to rectangle of image2
var r2 = ScaleRectangle(r1, c);

//Then convert rectangle of image2 to rectangle of pictureBox1
var result = TranslateImageSelectedRectangleToPictureBox(pictureBox1, r2);

【讨论】:

  • 但是图片框中的图像不是原始图像。它只是向用户显示预览。当主要处理完成时,将使用原始全分辨率图像。所以,当我显示向用户预览选择窗口(以像素为单位)应该看起来像在全分辨率图像中一样。它不应该看起来更大,因为我们使用小图像进行预览。希望你明白我的意思。
  • 不是真的,我想我听不懂。 PictureBox 是否使用缩放模式? PictureBox 显示的是原图吗?
  • 是的;图片框正在使用ZoomMode。它不显示原始图像,图像在设置到图片框之前以编程方式调整大小。
  • 我添加了一个示例。我也会添加另一个来做相反的事情。
  • 添加了第二个例子来解决反向问题。
猜你喜欢
  • 2017-06-06
  • 2010-11-28
  • 2013-01-16
  • 2013-10-13
  • 2011-12-13
  • 1970-01-01
  • 2020-11-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多