无法将像素着色器渲染到RenderTargetBitmap!请帮忙!

时间:2010-10-02 18:47:52

标签: wpf pixel-shader rendertargetbitmap

我编写了一个非常简单的WPF应用程序来测试将具有关联像素着色器的控件渲染到RenderTargetBitmap的能力。然后我将位图写入文件(jpeg)。控件将渲染到位图上,但像素着色器效果不会应用于控件。

代码和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>

2 个答案:

答案 0 :(得分:3)

您定位的Pixel Shader版本是什么?

我尝试了你的代码,它为PS 2.0着色器正确保存了图像。 RenderTargetBitmap使用软件渲染器,PS 3.0没有软件回退,因此如果您使用PS 3.0着色器,它将被忽略。

答案 1 :(得分: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);