是否将可视对象的内容保存为WPF中的图像文件?

是否将可视对象的内容保存为WPF中的图像文件?,wpf,image,canvas,Wpf,Image,Canvas,我需要将WPF对象的内容保存为图像文件。在我的应用程序中,我在画布对象上绘制了一张图表。这就是我需要保存的东西。包含所有子对象的画布。您要查找的是类。在我链接的MSDN页面上有一个使用它的示例,还有另一个很好的示例,包括在此处保存到文件: 以下是创建RenderTargetBitmap对象的函数,该对象将在以后的函数中使用 public static RenderTargetBitmap ConvertToBitmap(UIElement uiElement, double resolution

我需要将WPF对象的内容保存为图像文件。在我的应用程序中,我在画布对象上绘制了一张图表。这就是我需要保存的东西。包含所有子对象的画布。

您要查找的是类。在我链接的MSDN页面上有一个使用它的示例,还有另一个很好的示例,包括在此处保存到文件:


以下是创建
RenderTargetBitmap
对象的函数,该对象将在以后的函数中使用

public static RenderTargetBitmap ConvertToBitmap(UIElement uiElement, double resolution)
{
    var scale = resolution / 96d;

    uiElement.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
    var sz = uiElement.DesiredSize;
    var rect = new Rect(sz);
    uiElement.Arrange(rect);

    var bmp = new RenderTargetBitmap((int)(scale * (rect.Width)), (int)(scale * (rect.Height)), scale * 96, scale * 96, PixelFormats.Default);
    bmp.Render(uiElement);

    return bmp;
}
此函数C创建文件的JPEG字符串内容并将其写入文件:

public static void ConvertToJpeg(UIElement uiElement, string path, double resolution)
{
    var jpegString = CreateJpeg(ConvertToBitmap(uiElement, resolution));

    if (path != null)
    {
        try
        {
            using (var fileStream = File.Create(path))
            {
                using (var streamWriter = new StreamWriter(fileStream, Encoding.Default))
                {
                    streamWriter.Write(jpegString);
                    streamWriter.Close();
                }

                fileStream.Close();
            }
        }    

        catch (Exception ex)
        {
            //TODO: handle exception here
        }
    }
 }
此函数用于创建图像内容的JPEG字符串表示:

public static string CreateJpeg(RenderTargetBitmap bitmap)
{
    var jpeg = new JpegBitmapEncoder();
    jpeg.Frames.Add(BitmapFrame.Create(bitmap));
    string result;

    using (var memoryStream = new MemoryStream())
    {
        jpeg.Save(memoryStream);
        memoryStream.Seek(0, SeekOrigin.Begin);

        using (var streamReader = new StreamReader(memoryStream, Encoding.Default))
        {
            result = streamReader.ReadToEnd();
            streamReader.Close();
        }

        memoryStream.Close();
    }

    return result;
}

希望这有帮助。

在Eric Sinc教程的帮助下,我找到了以下解决方案: 它使用win32 SaveDialog选择文件应该放在哪里,并使用PngBitmapEncoder(许多其他BitMapEncoder可用!)将其转换为我们可以保存的内容

请注意,本例中保存的元素是“cnvClasses”,并且输出的大小相当有意地与控件的大小相同

        SaveFileDialog svDlg = new SaveFileDialog();
        svDlg.Filter = "PNG files|*.png|All Files|*.*";
        svDlg.Title = "Save diagram as PNG";
        if (svDlg.ShowDialog().Value == true)
        {
            RenderTargetBitmap render = new RenderTargetBitmap((int)this.cnvClasses.ActualWidth, (int)this.cnvClasses.ActualHeight, 96, 96, PixelFormats.Pbgra32);
            render.Render(cnvClasses);
            PngBitmapEncoder encoder = new PngBitmapEncoder();
            encoder.Frames.Add(BitmapFrame.Create(render));
            using (FileStream fs = new FileStream(svDlg.FileName, FileMode.Create))
                encoder.Save(fs);
        }

哦,请不要将二进制数据写入字符串。字符串用于字符,而不是字节。使用Encoding.Default会导致世界上其他计算机出现不可预测的行为。它可能会破坏图像文件的数据结构。我们生活在一个Unicode世界中,ASCII==字节的时代早已过去。如果有任何问题,请为图像数据返回MemoryStream或byte[]数组。或者更确切地说,请注意,
BitmapEncoder.Save
方法获取一个流,以便它可以将数据直接转储到文件流,而不是所有这些复制