我已经尝试了几种不同的方法,但是似乎无法获得有效的组合。
在C#,Visual Studio中创建WPF应用。
System.Windows.Shapes.Polyline可以很好地实时绘制到Canvas中,但是我希望能够以更高的分辨率绘制到非可视组件上,然后再渲染到Image上。
如果我在用户界面中可见的Canvas上创建折线,则可以正常工作:
// Make rendertarget size of full page
RenderTargetBitmap rtb = new RenderTargetBitmap((int)wPage, (int)hPage, 96, 96, PixelFormats.Default);
// Render the polyline
rtb.Render(lineVirt);
// Apply to background image
imgBG.Source = rtb;
但是,如果在UI上不可见的Canvas上创建折线,则图像不会呈现任何内容。这可能已经足够公平了。我的猜测是该组件认识到它是不可见的,因此不会费心渲染。
我曾考虑过将Canvas放置在UI中放置在其他控件下的某个位置,但这似乎是一种可怕的黑客手段。
本质上,我需要的是一种干净快速的方法来在图像上绘制指定宽度和颜色的多点线。我以为Polyline可以很好地工作,但似乎只能在可见的容器中工作。
我有什么选择?
你根本不需要渲染的Canvas或任何其他可见的Panel。
只需使用Visual层上可用的基本图形基元即可。
DrawGeometry
下面的方法Geometry
使用位图的渲染大小(即将其DPI考虑在内的大小)绘制到BitmapSource上,并返回生成的BitmapSource。
public static BitmapSource DrawGeometry(
BitmapSource source, Pen pen, Geometry geometry)
{
var visual = new DrawingVisual();
var rect = new Rect(0, 0, source.Width, source.Height);
using (var dc = visual.RenderOpen())
{
dc.DrawImage(source, rect);
dc.DrawGeometry(null, pen, geometry);
}
var target = new RenderTargetBitmap(
(int)rect.Width, (int)rect.Height, 96, 96, PixelFormats.Default);
target.Render(visual);
return target;
}
为了绘制位图的像素单位并因此忽略其DPI,请按如下所示修改方法:
var rect = new Rect(0, 0, source.PixelWidth, source.PixelHeight);
using (var dc = visual.RenderOpen())
{
dc.DrawRectangle(new ImageBrush(source), null, rect);
dc.DrawGeometry(null, pen, geometry);
}
以下方法使用上述方法绘制多段线作为IEnumerable<Point>
。
public static BitmapSource DrawPolyline(
BitmapSource source, Pen pen, IEnumerable<Point> points)
{
var geometry = new PathGeometry();
if (points.Count() >= 2)
{
var figure = new PathFigure { StartPoint = points.First() };
figure.Segments.Add(new PolyLineSegment(points.Skip(1), true));
geometry.Figures.Add(figure);
}
return DrawGeometry(source, pen, geometry);
}
它会像
var source = new BitmapImage(new Uri(...));
var pen = new Pen
{
Brush = Brushes.Blue,
Thickness = 2,
};
var points = new List<Point>
{
new Point(100, 100),
new Point(1000, 100),
new Point(1000, 1000),
new Point(100, 1000),
new Point(100, 100),
};
image.Source = DrawPolyline(source, pen, points);
惊人的!感谢您提供如此详细的答案。疯狂的事情是我尝试了类似的方法,但没有成功。不知道我出了什么问题,但这确实有所帮助。