从 WPF 中的图像裁剪对角线区域
Crop a diagonal area from an image in WPF
我想在 canvas 上使用用户绘制的矩形从图像中裁剪。矩形可以移动、调整大小和旋转。
当用户选择 "Get Cropped Image" 时,矩形内的区域应该保存在页面上的第二个图像位置,只要矩形不旋转,我就可以做到这一点。 (直接使用 CroppedBitmap。)但是,当矩形处于一定角度时,我不知道如何执行裁剪。
这就是我想做的(原谅我可怜的 MS Paint 技能):
我的问题是:
1) 如何正确跟踪或计算矩形的点?
并且,
2) 得到点后,如何裁剪旋转的矩形?
编辑:
感谢用户 Rotem, I believe that I have the answer to the second question. Using code modified from the following answers: Answer 1, Answer 2,我看到了不错的结果。不幸的是,我仍然无法跟踪矩形的正确位置点,所以我还不能完全测试它。
public static Bitmap CropRotatedRect(Bitmap source, System.Drawing.Rectangle rect, float angle, bool HighQuality)
{
Bitmap result = new Bitmap((int)rect.Width, (int)rect.Height);
using (Graphics g = Graphics.FromImage(result))
{
g.InterpolationMode = HighQuality ? InterpolationMode.HighQualityBicubic : InterpolationMode.Default;
using (Matrix mat = new Matrix())
{
mat.Translate(-rect.Location.X, -rect.Location.Y);
mat.RotateAt(-(angle), rect.Location);
g.Transform = mat;
g.DrawImage(source, new System.Drawing.Point(0, 0));
}
}
return result;
}
编辑:
第一点的答案比我原先想象的要容易得多。您始终可以通过调用 -
来获取矩形的左上角
double top = Canvas.GetTop(rect);
double left = Canvas.GetLeft(rect);
然后您可以使用宽度和高度计算其余点—
Point topLeft = new Point(left, top);
Point topRight = new Point(left + rect.Width, top);
Point bottomLeft = new Point(left, top + rect.Height);
Point bottomRight = new Point(left + rect.Width, top + rect.Height);
Point centerPoint = new Point(left + (rect.Width / 2), top + (rect.Height / 2));
如果您的矩形是旋转的,那么您必须平移这些点以确定它们真正位于 canvas—
上的位置
public Point TranslatePoint(Point center, Point p, double angle)
{
// get the point relative to (0, 0) by subtracting the center of the rotated shape.
Point relToOrig = new Point(p.X - center.X, p.Y - center.Y);
double angleInRadians = angle * Math.PI / 180;
double sinOfA = Math.Sin(angleInRadians);
double cosOfA = Math.Cos(angleInRadians);
Point translatedPoint = new Point(relToOrig.X * cosOfA - relToOrig.Y * sinOfA,
relToOrig.X * sinOfA + relToOrig.Y * cosOfA);
return new Point(translatedPoint.X + center.X, translatedPoint.Y + center.Y);
}
一旦您能够平移左上角,就可以使用 Rotem 的裁剪方法。您还可以计算矩形其余部分的位置,这样您就可以确定矩形是否在图像的边界内,它是否触及边缘,或者您可能想要做的任何其他事情位置。
我找到了自己问题的答案,并在此过程中进行了适当的编辑。请参阅上面的答案。
我想在 canvas 上使用用户绘制的矩形从图像中裁剪。矩形可以移动、调整大小和旋转。
当用户选择 "Get Cropped Image" 时,矩形内的区域应该保存在页面上的第二个图像位置,只要矩形不旋转,我就可以做到这一点。 (直接使用 CroppedBitmap。)但是,当矩形处于一定角度时,我不知道如何执行裁剪。
这就是我想做的(原谅我可怜的 MS Paint 技能):
我的问题是:
1) 如何正确跟踪或计算矩形的点?
并且,
2) 得到点后,如何裁剪旋转的矩形?
编辑: 感谢用户 Rotem, I believe that I have the answer to the second question. Using code modified from the following answers: Answer 1, Answer 2,我看到了不错的结果。不幸的是,我仍然无法跟踪矩形的正确位置点,所以我还不能完全测试它。
public static Bitmap CropRotatedRect(Bitmap source, System.Drawing.Rectangle rect, float angle, bool HighQuality)
{
Bitmap result = new Bitmap((int)rect.Width, (int)rect.Height);
using (Graphics g = Graphics.FromImage(result))
{
g.InterpolationMode = HighQuality ? InterpolationMode.HighQualityBicubic : InterpolationMode.Default;
using (Matrix mat = new Matrix())
{
mat.Translate(-rect.Location.X, -rect.Location.Y);
mat.RotateAt(-(angle), rect.Location);
g.Transform = mat;
g.DrawImage(source, new System.Drawing.Point(0, 0));
}
}
return result;
}
编辑: 第一点的答案比我原先想象的要容易得多。您始终可以通过调用 -
来获取矩形的左上角double top = Canvas.GetTop(rect);
double left = Canvas.GetLeft(rect);
然后您可以使用宽度和高度计算其余点—
Point topLeft = new Point(left, top);
Point topRight = new Point(left + rect.Width, top);
Point bottomLeft = new Point(left, top + rect.Height);
Point bottomRight = new Point(left + rect.Width, top + rect.Height);
Point centerPoint = new Point(left + (rect.Width / 2), top + (rect.Height / 2));
如果您的矩形是旋转的,那么您必须平移这些点以确定它们真正位于 canvas—
上的位置public Point TranslatePoint(Point center, Point p, double angle)
{
// get the point relative to (0, 0) by subtracting the center of the rotated shape.
Point relToOrig = new Point(p.X - center.X, p.Y - center.Y);
double angleInRadians = angle * Math.PI / 180;
double sinOfA = Math.Sin(angleInRadians);
double cosOfA = Math.Cos(angleInRadians);
Point translatedPoint = new Point(relToOrig.X * cosOfA - relToOrig.Y * sinOfA,
relToOrig.X * sinOfA + relToOrig.Y * cosOfA);
return new Point(translatedPoint.X + center.X, translatedPoint.Y + center.Y);
}
一旦您能够平移左上角,就可以使用 Rotem 的裁剪方法。您还可以计算矩形其余部分的位置,这样您就可以确定矩形是否在图像的边界内,它是否触及边缘,或者您可能想要做的任何其他事情位置。
我找到了自己问题的答案,并在此过程中进行了适当的编辑。请参阅上面的答案。