【问题标题】:WPF rendering control to Bitmap without WindowWPF 将控件渲染到没有窗口的位图
【发布时间】:2018-08-07 19:31:00
【问题描述】:

所以我们有一个 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");
        }
    }
}

【问题讨论】:

  • 完全相同的代码,但在 WPF 窗口中呈现,会提供更大的图像(也明显未拉伸)且不透明,但具有白色背景。
  • 在chart.Arrange上放断点显示desiredsize也是80*50。
  • 这只是生成一个透明图像。只是更大。
  • 仅使用 LiveCharts 中最基本的示例。 lvcharts.net/App/examples/v1/wpf/30%20Series%2010k%20pts%20each
  • 我不知道 LiveCharts,但由于您在 LineSeries 上设置了 Fill = Brushes.Transparent,您可能还应该将 Stroke 设置为非空且不透明的值。在 Window 应用程序中可能会设置默认样式的属性值,但在您的应用程序中没有设置。

标签: c# wpf


【解决方案1】:

好吧,我不知道为什么。如前所述,我对 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);
        }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-17
    • 2011-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多