C# 无窗口位图的WPF渲染控件
因此,我们有一个WPF应用程序,它显示了使用Live charts库创建的一些图表。然而,我得到的任务是在后台渲染图表,并将它们保存到PNG图像中,而不显示WPF窗口。我在网上找到了一篇文章,它采用了UserControl,并且确实做到了这一点,但我自己尝试了一下,只得到了80×50像素的透明图像 不幸的是,我不太熟悉渲染的WPF内部,因此非常感谢您的帮助。这是我的代码,用LiveChart本身最简单的图表示例呈现到最低限度C# 无窗口位图的WPF渲染控件,c#,wpf,C#,Wpf,因此,我们有一个WPF应用程序,它显示了使用Live charts库创建的一些图表。然而,我得到的任务是在后台渲染图表,并将它们保存到PNG图像中,而不显示WPF窗口。我在网上找到了一篇文章,它采用了UserControl,并且确实做到了这一点,但我自己尝试了一下,只得到了80×50像素的透明图像 不幸的是,我不太熟悉渲染的WPF内部,因此非常感谢您的帮助。这是我的代码,用LiveChart本身最简单的图表示例呈现到最低限度 using System; using System.IO; usin
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");
}
}
}
使用系统;
使用System.IO;
使用System.Windows.Media;
使用System.Windows.Media.Imaging;
使用LiveCharts.Wpf;
使用动态图表;
使用动态图表;
命名空间截图2PDF{
班级计划{
[状态线程]
静态void Main(字符串[]参数){
var系列=新系列集合();
var r=新的随机变量();
对于(var i=0;i<30;i++)//30系列
{
var趋势=0d;
var值=新的双精度[10000];
对于(var j=0;j<10000;j++)//10k点
{
趋势+=(r.NextDouble()<.8?1:-1)*r.Next(0,10);
数值[j]=趋势;
}
var系列=新系列{
Values=Values.AsGearedValues().带质量(质量.低),
填充=画笔。透明,
冲程厚度=.5,
PointGeometry=null//当有多个系列时,请使用null几何体
};
系列。添加(系列);
}
var图表=新的CartesianChart();
图表系列=系列;
chart.BeginInit();
chart.EndInit();
//测量并排列瓷砖
图表.度量(新System.Windows.Size){
高度=双正不确定性,
宽度=double.PositiveInfinity
});
chart.Arrange(新系统.Windows.Rect(0,0,,
chart.DesiredSize.Width,
图表(所需尺寸、高度);
chart.UpdateLayout();
RenderTargetBitmap rtb=新的RenderTargetBitmap((int)chart.DesiredSize.Width,(int)chart.DesiredSize.Height,96,96,PixelFormats.Pbgra32);
渲染(图表);
PngBitmapEncoder png=新的PngBitmapEncoder();
png.Frames.Add(BitmapFrame.Create(rtb));
MemoryStream stream=新的MemoryStream();
保存(流);
var image=System.Drawing.image.FromStream(stream);
image.Save(@“D:\bitmap.png”);
}
}
}
好吧,我不知道为什么。如前所述,我不太熟悉WPF的内部渲染机制以及触发它的原因,但解决方案是将图表包装在一个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);
}
完全相同的代码,但在WPF窗口中呈现,会产生一个更大的图像(也明显没有拉伸),并且不是透明的,但背景为白色。将断点放在图表上。Arrange显示desiredsize也是80*50。这只会生成一个透明图像。只是更大。只是使用LiveCharts中最基本的示例。我不知道LiveCharts,但由于您在LineSeries上设置了
Fill=brushs.Transparent
,因此您可能还应该将Stroke
设置为非空和非透明。在窗口应用程序中,可能存在默认样式设置的特性值,但在您的应用程序中没有设置。