2010-10-02 43 views
2

我寫了一個非常簡單的WPF應用程序來測試渲染控件的能力,該控件具有關聯的像素着色器到RenderTargetBitmap。然後我將位圖寫入文件(jpeg)。控件呈現在位圖上,但像素着色器效果未應用於控件。無法將像素着色器渲染到RenderTargetBitmap!請幫忙!

的代碼和XAML低於:

namespace TestPixelShader 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 
     } 

     private void OnSaveSnapshot(object sender, RoutedEventArgs e) 
     { 
      SaveFileDialog dlg = new SaveFileDialog(); 
      dlg.DefaultExt = "jpg"; 

      if ((bool)dlg.ShowDialog() == true) 
      { 
       String fileName = dlg.FileName; 

       int Height = (int)CanvasControl.ActualHeight; 
       int Width = (int)CanvasControl.ActualWidth; 

       RenderTargetBitmap bmp = new RenderTargetBitmap(
        Width, Height, 96, 96, PixelFormats.Pbgra32); 
       bmp.Render(CanvasControl); 

       string Extension = System.IO.Path.GetExtension(fileName).ToLower(); 

       BitmapEncoder encoder; 
       if (Extension == ".gif") 
        encoder = new GifBitmapEncoder(); 
       else if (Extension == ".png") 
        encoder = new PngBitmapEncoder(); 
       else if (Extension == ".jpg") 
        encoder = new JpegBitmapEncoder(); 
       else 
        return; 

       encoder.Frames.Add(BitmapFrame.Create(bmp)); 
       using (Stream stm = File.Create(fileName)) 
       { 
        encoder.Save(stm); 
       } 
      } 
     } 
    } 
} 

XAML:

<Window x:Class="TestPixelShader.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:TestPixelShader" 
    Height="400" 
    Width="300" 
    Title="Test Pixel Shader"> 

    <Grid> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="*"/> 
      <RowDefinition Height="Auto" /> 
     </Grid.RowDefinitions> 
     <Canvas Grid.Column="0" x:Name="CanvasControl" Margin="5" 
       HorizontalAlignment="Stretch" 
       VerticalAlignment="Stretch" > 
      <Canvas.Effect> 
       <local:TestPixelShaderEffect /> 
      </Canvas.Effect> 
      <Canvas.Background> 
       <ImageBrush ImageSource="/TestPixelShader;component/Images/DSCF0225.JPG" /> 
      </Canvas.Background> 
     </Canvas> 
     <Button x:Name="SaveSnapshotButton" Grid.Row="1" Click="OnSaveSnapshot" Height="40" 
       Content="Take Snapshot" Margin="5"/> 
    </Grid> 
</Window> 
+0

可能清理你的代碼示例嗎? – 2010-10-02 18:50:45

+0

這是一個http://stackoverflow.com/questions/545676/save-wpf-image-with-shader-effects-applied的副本? – 2010-10-02 19:13:34

+0

不,我不相信這是所引用問題的重複。我試圖渲染到RTB,但是我使用的是PS 3.0,而Kris指出3.0沒有軟件回退,因此將被忽略。這似乎是我的問題的根源。我需要使用3.0,因爲2.0沒有足夠的能力。任何其他建議? – BigPrimate 2010-10-03 02:08:45

回答

2

什麼的Pixel Shader版本,你定位?

我試過你的代碼,它爲PS 2.0着色器正確保存了圖像。 RenderTargetBitmap使用軟件渲染器,PS 3.0沒有軟件回退功能,因此如果使用PS 3.0着色器,它將被忽略。

+0

這是非常令人失望的,我需要PS 3.0的一些功能,但也需要能夠將屏幕快照保存爲一個文件的WPF控件。我認爲RenderTargetBitmap是我最大的希望。有什麼建議麼?我想我可以以某種方式使用DirectX,但我仍然需要將WPF控件呈現在屏幕外。這非常令人沮喪!謝謝您的幫助! – BigPrimate 2010-10-03 02:03:35

+0

如果您不需要在屏幕外進行屏幕截圖,那麼最簡單的方式就是使用屏幕截圖,但使用D3D或使用軟件自己做是最好的選擇。我對D3D沒有多少經驗,但是您可以使用Slim Dx或「Windows API代碼包」使用託管代碼訪問它。你的着色器有多複雜,是否可以將它分成多個PS 2.0着色器? – Kris 2010-10-03 14:33:34

1
public class SnapshotHelper 
{ 
    public static BitmapSource Capture(Rect absoluteControlRect) 
    { 
     using (var screenBmp = new System.Drawing.Bitmap(
      (int)absoluteControlRect.Width, 
      (int)absoluteControlRect.Height, 
      PixelFormat.Format32bppArgb)) 
     { 
      using (var bmpGraphics = System.Drawing.Graphics.FromImage(screenBmp)) 
      { 
       bmpGraphics.CopyFromScreen((int)absoluteControlRect.Left, (int)absoluteControlRect.Top, 0, 0, screenBmp.Size); 
       return System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
        screenBmp.GetHbitmap(), 
        IntPtr.Zero, 
        Int32Rect.Empty, 
        BitmapSizeOptions.FromEmptyOptions()); 
      } 
     } 
    } 

    public static Rect GetAbsoltutePlacement(FrameworkElement visual) 
    { 
     Point absolutePos = visual.PointToScreen(new Point(0, 0)); 
     return new Rect(absolutePos.X, absolutePos.Y, visual.ActualWidth, visual.ActualHeight); 
    } 

} 

用法:

var rect = SnapshotHelper.GetAbsoltutePlacement(yourControl); 
var image = SnapshotHelper.Capture(rect);