Spa*_*chu 4 wpf render path bitmap resourcedictionary
我希望能够加载路径的WPF资源字典并将它们逐个输出到文件(jpg,bmp,这没关系).这将在一个类库中,MVC应用程序将访问该类以呈现为http流,因此我只在代码中执行此操作(没有XAML页面).
我已经能够加载字典并遍历路径,但是当我将图像保存到磁盘时,它们是空白的.我知道我遗漏了一些微不足道的东西,比如将路径应用到几何体,或者将其添加到包含矩形的东西中,但我的WPF体验有限.
我正在使用以下代码:
我有一个包含多个路径的WPF资源字典,如下所示:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Path x:Key="Path1" Data="M 100,200 C 100,25 400,350 400,175 H 280" Fill="White" Margin="10,10,10,10" Stretch="Fill"/>
<Path x:Key="Path2" Data="M 10,50 L 200,70" Fill="White" Margin="10,10,10,10" Stretch="Fill"/>
</ResourceDictionary>
Run Code Online (Sandbox Code Playgroud)
以及读取和输出文件的类:
public class XamlRenderer
{
public void RenderToDisk()
{
ResourceDictionary resource = null;
Thread t = new Thread(delegate()
{
var s = new FileStream(@"C:\Temp\myfile.xaml", FileMode.Open);
resource = (ResourceDictionary)XamlReader.Load(s);
s.Close();
foreach (var item in resource)
{
var resourceItem = (DictionaryEntry)item;
var path = (System.Windows.Shapes.Path)resourceItem.Value;
var panel = new StackPanel();
var greenBrush = new SolidColorBrush {Color = Colors.Green};
path.Stroke = Brushes.Blue;
path.StrokeThickness = 2;
path.Fill = greenBrush;
panel.Children.Add(path);
panel.UpdateLayout();
string filepath = @"C:\Temp\Images\" + resourceItem.Key + ".jpg";
SaveImage(panel, 64, 64, filepath);
}
});
t.SetApartmentState(ApartmentState.STA);
t.Start();
}
public void SaveImage(Visual visual, int width, int height, string filePath)
{
var bitmap =
new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32);
bitmap.Render(visual);
var image = new PngBitmapEncoder();
image.Frames.Add(BitmapFrame.Create(bitmap));
using (Stream fs = File.Create(filePath))
{
image.Save(fs);
}
}
}
Run Code Online (Sandbox Code Playgroud)
经过大量的谷歌搜索和反复试验,我似乎已经找到了解决方案.这篇文章指出了我正确的方向.有一些问题:
Measure()并且Arrange()需要在容器元素上被调用.在UpdateLayout()不需要调用.一旦这些问题得到解决,图像就会呈现给磁盘(尽管我还没有解决长宽比问题).
这是更新的代码:
public void RenderToDisk()
{
ResourceDictionary resource = null;
Thread t = new Thread(delegate()
{
var s = new FileStream(@"C:\Temp\myfile.xaml", FileMode.Open);
resource = (ResourceDictionary)XamlReader.Load(s);
s.Close();
foreach (var item in resource)
{
var resourceItem = (DictionaryEntry)item;
var path = (System.Windows.Shapes.Path)resourceItem.Value;
path.Margin = new Thickness(10);
path.HorizontalAlignment = HorizontalAlignment.Center;
path.VerticalAlignment = VerticalAlignment.Center;
path.Width = 48;
path.Height = 48;
path.Stroke = Brushes.White;
path.Fill = Brushes.Black;
var canvas = new Canvas();
canvas.Width = 64;
canvas.Height = 64;
canvas.Margin = new Thickness(0);
canvas.Background = Brushes.Transparent;
canvas.Children.Add(path);
canvas.Measure(new Size(canvas.Width, canvas.Height));
canvas.Arrange(new Rect(new Size(canvas.Width, canvas.Height)));
string filepath = @"C:\Temp\Images\" + resourceItem.Key + ".png";
SaveImage(canvas, (int)canvas.Width, (int)canvas.Height, filepath);
}
});
t.SetApartmentState(ApartmentState.STA);
t.Start();
}
Run Code Online (Sandbox Code Playgroud)