2012-03-07 15 views
3

パスのWPFリソースディクショナリをロードして、ファイル(jpg、bmp、それは関係ありません)に1つずつ出力できます。これは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> 

とファイルを読み出して出力するクラス:

を私はWPFリソースディクショナリには、次のようないくつかのパスを含む必要があり

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(); 
    } 
:ここ

が更新されたコードです

関連する問題