WPF渲染控件到不带窗口的位图

时间:2018-08-07 08:17:41

标签: c# wpf

因此,我们有一个WPF应用程序,其中显示了一些使用Live Charts库创建的图表。但是我得到了在后台渲染图表并将其保存到PNG图像而不显示WPF窗口的任务。我在网上找到了一篇使用UserControl并能做到这一点的文章,但是我自己尝试一下,却只能得到80 x 50像素的透明图像。

不幸的是,我对渲染的WPF内部不是很熟悉,因此非常感谢您的帮助。这是我的代码,使用LiveChart本身的最简单图表示例将代码渲染到最低限度。

using System;
using System.IO;
using System.Windows.Media;
using System.Windows.Media.Imaging;

using LiveCharts.Wpf;
using LiveCharts.Geared;
using LiveCharts;

namespace Screenshot2Pdf {
    class Program {
        [STAThread]
        static void Main(string[] args) {
            var Series = new SeriesCollection();
            var r = new Random();

            for (var i = 0; i < 30; i++) // 30 series
            {
                var trend = 0d;
                var values = new double[10000];

                for (var j = 0; j < 10000; j++) // 10k points each
                {
                    trend += (r.NextDouble() < .8 ? 1 : -1) * r.Next(0, 10);
                    values[j] = trend;
                }

                var series = new LineSeries {
                    Values = values.AsGearedValues().WithQuality(Quality.Low),
                    Fill = Brushes.Transparent,
                    StrokeThickness = .5,
                    PointGeometry = null //use a null geometry when you have many series
                };

                Series.Add(series);
            }

            var chart = new CartesianChart();

            chart.Series = Series;

            chart.BeginInit();
            chart.EndInit();

            // Measure and arrange the tile
            chart.Measure(new System.Windows.Size {
                Height = double.PositiveInfinity,
                Width = double.PositiveInfinity
            });
            chart.Arrange(new System.Windows.Rect(0, 0,
               chart.DesiredSize.Width,
               chart.DesiredSize.Height));

            chart.UpdateLayout();

            RenderTargetBitmap rtb = new RenderTargetBitmap((int)chart.DesiredSize.Width, (int)chart.DesiredSize.Height, 96, 96, PixelFormats.Pbgra32);
            rtb.Render(chart);

            PngBitmapEncoder png = new PngBitmapEncoder();
            png.Frames.Add(BitmapFrame.Create(rtb));
            MemoryStream stream = new MemoryStream();
            png.Save(stream);
            var image = System.Drawing.Image.FromStream(stream);

            image.Save(@"D:\bitmap.png");
        }
    }
}

1 个答案:

答案 0 :(得分:0)

好吧,我不确定为什么。如前所述,我对WPF的内部渲染机制及其触发机制不是很熟悉,但是解决方案是将Chart封装在Viewbox中。以下代码可以解决问题:

        var viewbox = new Viewbox();
        viewbox.Child = chart;
        viewbox.Measure(chart.RenderSize);
        viewbox.Arrange(new Rect(new Point(0, 0), chart.RenderSize));
        chart.Update(true, true); //force chart redraw
        viewbox.UpdateLayout();

        // RenderTargetBitmap rtb = new RenderTargetBitmap((int)chart.DesiredSize.Width, (int)chart.DesiredSize.Height, 96, 96, PixelFormats.Pbgra32);
        var rtb = new RenderTargetBitmap(500, 500, 96, 96, PixelFormats.Default);
        rtb.Render(chart);

        var encoder = new PngBitmapEncoder();
        encoder.Frames.Add(BitmapFrame.Create(rtb));

        using (var stream = File.OpenWrite(@"D:\bitmap.png")) {
            encoder.Save(stream);
        }