2012-03-07 28 views
3

我希望能夠加載WPF資源路徑的詞典並將它們逐個輸出到文件(jpg,bmp,無所謂)。這將在MVC應用程序訪問的類庫中呈現給http流,所以我純粹在代碼內部(沒有XAML頁面)執行此操作。將WPF路徑轉換爲位圖文件

我已經能夠加載字典並遍歷路徑,但是當我將圖像保存到磁盤時,它們是空白的。我知道我錯過了一些微不足道的東西,比如將路徑應用到一塊幾何圖形,或者將它添加到某個包含矩形的東西中,但是我的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> 

和類讀取和輸出的文件:

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); 
     } 
    } 
} 

回答

6

經過大量的谷歌搜索和試驗和錯誤,我似乎已經達成了一個解決方案。這post指出我在正確的方向。 有幾個問題:

  • 我現在設置路徑的大小和容器
  • 堆棧面板容器有一些細微差別是造成問題的,所以我用帆布取而代之
  • 最重要的是,需要在容器元素上調用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(); 
    }