【问题标题】:Convert PictureBox Selection Rectangle according to SizeMode根据 SizeMode 转换 PictureBox 选择矩形
【发布时间】:2015-08-06 19:33:24
【问题描述】:

我有两个PictureBoxes pbOriginal 和 pbFace。从 pbOriginal 中的图像中选择“面”后,我克隆矩形选择并将其放入 pbFace。 但是,因为 pbOriginal 使用的是SelectionMode=Stretch,所以实际复制的区域与选择的区域不同。

如何转换 Rectangle 的坐标,使其真正反映拉伸图像的坐标?

【问题讨论】:

  • 您可以通过将 pb.Image.Size.xx 除以 pb.ClienteSize.xx 来获得宽度和高度的拉伸因子。您必须对框架的 X&Y 和 Width&Height 执行此操作。
  • 我已经编辑了你的标题。请参阅“Should questions include “tags” in their titles?”,其中的共识是“不,他们不应该”。
  • 据我所知,这是共识——但这不是规则。我站在不同意的一边。
  • 通常语言和目标标签应该倾斜,如C#WinFormsASP... OTOH主题如@987654327 @ 或 Chart 应该,。由于我们可以按标签过滤 imo 规则是:“关键字通常用作过滤器吗?”
  • 但是,这不是一个规则,因此我是否选择在标题中添加一个 lang 标签。

标签: c# selection picturebox coordinate-systems


【解决方案1】:

这是一个示例,它在您绘制第一个矩形的同时绘制第二个矩形......:

Point mDown = Point.Empty;
Point mCurr = Point.Empty;

private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{   mDown = e.Location;  }

private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
    if (e.Button == System.Windows.Forms.MouseButtons.Left)
       { mCurr = e.Location; pictureBox1.Invalidate(); }
}

private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
    Rectangle r = new Rectangle(mDown.X, mDown.Y, mCurr.X - mDown.X, mCurr.Y - mDown.Y);
    e.Graphics.DrawRectangle(Pens.Orange, r);
    pictureBox2.Invalidate();
}

private void pictureBox2_Paint(object sender, PaintEventArgs e)
{
    if (pictureBox2.Image == null) return;

    float stretch1X = 1f * pictureBox1.Image.Width / pictureBox1.ClientSize.Width;
    float stretch1Y = 1f * pictureBox1.Image.Height / pictureBox1.ClientSize.Height;

    int x = (int)(mDown.X * stretch1X);
    int y = (int)(mDown.Y * stretch1Y);
    int x2 = (int)(mCurr.X * stretch1X);
    int y2 = (int)(mCurr.Y * stretch1Y);

    Rectangle r = new Rectangle(x, y, x2 - x, y2 - y);
    e.Graphics.DrawRectangle(Pens.Orange, r);
}

请注意,它假定您从左上角到右下角绘制..

如果您想复制选择,您可以使用相同的因子和相同的Rectangle 作为DrawImage 调用的来源:

float stretch1X = 1f * pictureBox1.Image.Width / pictureBox1.ClientSize.Width;
float stretch1Y = 1f * pictureBox1.Image.Height / pictureBox1.ClientSize.Height;

Point pt = new Point((int)(mDown.X * stretch1X), (int)(mDown.Y * stretch1Y));
Size sz = new Size((int)((mCurr.X - mDown.X) * stretch1X), 
                   (int)((mCurr.Y - mDown.Y) * stretch1Y));


Rectangle rSrc = new Rectangle(pt, sz);
Rectangle rDest= new Rectangle(Point.Empty, sz);

Bitmap bmp = new Bitmap(sz.Width, sz.Height);
using (Graphics G = Graphics.FromImage(bmp))
    G.DrawImage(pictureBox1.Image, rDest, rSrc , GraphicsUnit.Pixel);
pictureBox2.Image = bmp;

您可能需要编写 MouseUp 事件来存储 finla mCurr 位置并触发复制..

【讨论】:

  • 这不是我真正要求的 - 但我会看看我是否可以破译代码以让它做我想做的事。如果可以的话我会给你答案点击
  • 您的 pbOriginal 是我的图片框 1,而 pbFace 是我的图片框 2。 - 哦,现在我明白了:您正在复制像素,而不仅仅是矩形?您可以使用与源相同的矩形。我已经更新了答案..
  • 如果 PictureBox 设置为 Zoom 会怎样计算?您是如何进行这些计算的?
  • 您的意思是 pbOriginal 在 Zoom 中吗?它应该是一样的。图像始终具有图像中实际的像素数。 ClientSize 是控件的可见区域。拉伸和缩放之间的区别在于缩放保留纵横比,拉伸不保留。因为我分别计算了 y 和 y 的因子,所以它应该总是有效的..
  • 好吧,如果两者都处于缩放模式,您将不得不进行另一轮计算,这次使用第二个 pbs 因子并将它们相除而不是在计算 x&y 或 pt&sz 时相乘..
猜你喜欢
  • 2014-10-17
  • 1970-01-01
  • 1970-01-01
  • 2018-10-23
  • 2018-07-06
  • 2019-04-01
  • 2020-10-28
  • 2016-06-30
  • 1970-01-01
相关资源
最近更新 更多