RenderTargetBitmap渲染WPF Canvas异常,如何仅渲染画布内容?
解决WPF Canvas居中时渲染图片带空白的问题
我懂你遇到的这个坑!当Canvas在父容器里居中显示时,直接用RenderTargetBitmap.Render(canvas)会把它在布局里的偏移空白也渲染进去——这是因为WPF的控件渲染会包含它在父容器中的位置信息,而不是只渲染它自身的内容区域。下面给你两个靠谱的解决办法:
方法一:用DrawingVisual单独渲染Canvas的内容
这个方法会跳过布局偏移,只渲染Canvas内部的所有元素,完美保留居中显示的同时,输出干净的图片:
// 获取Canvas自身的实际尺寸 var canvasSize = canvas.RenderSize; RenderTargetBitmap rtb = new RenderTargetBitmap( (int)canvasSize.Width, (int)canvasSize.Height, 96d, 96d, PixelFormats.Default); // 创建DrawingVisual来绘制Canvas的内容 DrawingVisual visual = new DrawingVisual(); using (DrawingContext dc = visual.RenderOpen()) { // 把Canvas的所有子元素绘制到DrawingVisual里 foreach (UIElement child in canvas.Children) { dc.DrawVisual(child, child.TransformToVisual(canvas)); } } // 渲染并保存图片 rtb.Render(visual); BitmapEncoder pngEncoder = new PngBitmapEncoder(); pngEncoder.Frames.Add(BitmapFrame.Create(rtb)); using (System.IO.MemoryStream ms = new System.IO.MemoryStream()) { pngEncoder.Save(ms); System.IO.File.WriteAllBytes("D://logo.png", ms.ToArray()); }
方法二:通过平移抵消布局偏移
如果你不想遍历子元素,可以计算Canvas在父容器中的偏移量,然后用TranslateTransform把内容平移回去,这样渲染出来的图片就不会有空白了:
Rect rect = new Rect(canvas.RenderSize); RenderTargetBitmap rtb = new RenderTargetBitmap( (int)rect.Width, (int)rect.Height, 96d, 96d, PixelFormats.Default); // 获取Canvas相对于父容器的偏移 GeneralTransform transform = canvas.TransformToVisual(canvas.Parent as UIElement); Point offset = transform.Transform(new Point(0, 0)); // 创建一个DrawingVisual,把Canvas平移抵消偏移 DrawingVisual visual = new DrawingVisual(); using (DrawingContext dc = visual.RenderOpen()) { dc.PushTransform(new TranslateTransform(-offset.X, -offset.Y)); dc.DrawVisual(canvas, null); dc.Pop(); } rtb.Render(visual); BitmapEncoder pngEncoder = new PngBitmapEncoder(); pngEncoder.Frames.Add(BitmapFrame.Create(rtb)); using (System.IO.MemoryStream ms = new System.IO.MemoryStream()) { pngEncoder.Save(ms); System.IO.File.WriteAllBytes("D://logo.png", ms.ToArray()); }
额外提示
- 记得用
using包裹MemoryStream,避免资源泄漏(你原来的代码里ms.Close()可以去掉,用using自动释放更安全) - 两种方法都能保留Canvas的居中显示效果,同时输出只包含Canvas内容的图片,选哪个看你自己的场景偏好就行~
内容的提问来源于stack exchange,提问作者Megid
相关产品推荐
相关产品推荐

