将画布保存为PNG格式的方法 C# WPF

13

我正在尝试在WPF C#中对我的画布进行快照,以便将其保存为png。目前保存的图像不正确,因为它包括左侧和顶部边距。

这是我的代码:

创建一个大小与画布相同的矩形。如果将canvas.Margin.Left和Top设置为0,则保存的图像大小正确,但仍会出现偏移,因此会截断底部和右侧边缘。如果设置Margin.Left和Top,则仍会发生偏移,但整个图像会被保存,但大小不对(margin.Left + ActualWidth而不是只有ActualWidth)。

Rect rect = new Rect(canvas.Margin.Left, canvas.Margin.Top, canvas.ActualWidth, canvas.ActualHeight);

double dpi = 96d;

RenderTargetBitmap rtb = new RenderTargetBitmap((int)rect.Right, (int)rect.Bottom, dpi, dpi, System.Windows.Media.PixelFormats.Default);

rtb.Render(canvas);

BitmapEncoder pngEncoder = new PngBitmapEncoder();
pngEncoder.Frames.Add(BitmapFrame.Create(rtb));

try
{
    System.IO.MemoryStream ms = new System.IO.MemoryStream();

    pngEncoder.Save(ms);
    ms.Close();

    System.IO.File.WriteAllBytes(filename, ms.ToArray());
}
catch (Exception err)
{
    MessageBox.Show(err.ToString(), "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}

为什么要创建MemoryStream?直接创建FileStream并将编码器保存即可。 - Der_Meister
如果画布区域外有元素:https://dev59.com/s8Dqa4cB1Zd3GeqPhqCl - Thomas Weller
关于裁剪底部和右侧边缘,请记住,将double转换为int只会截断小数位。因此,您可能需要尝试 RenderTargetBitmap rtb = new RenderTargetBitmap((int)rect.Right + 1, (int)rect.Bottom + 1, dpi, dpi, System.Windows.Media.PixelFormats.Default); - SourceSeeker
1个回答

20

用这些行替换前四行

Rect bounds = VisualTreeHelper.GetDescendantBounds(canvas);
double dpi = 96d;

RenderTargetBitmap rtb = new RenderTargetBitmap((int)bounds.Width, (int)bounds.Height, dpi, dpi, System.Windows.Media.PixelFormats.Default);

DrawingVisual dv = new DrawingVisual();
using (DrawingContext dc = dv.RenderOpen())
{
    VisualBrush vb = new VisualBrush(canvas);
    dc.DrawRectangle(vb, null, new Rect(new Point(), bounds.Size));
}

rtb.Render(dv);

我按照这篇文章http://mcleodsean.wordpress.com/2008/10/07/bitmap-snapshots-of-wpf-visuals/成功地保存了画布而没有边缘。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接