Не удается отобразить пиксельный шейдер в RenderTargetBitmap!Пожалуйста помоги! - PullRequest
2 голосов
/ 02 октября 2010

Я написал очень простое приложение 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 ]

3 голосов
/ 02 октября 2010

На какую версию Pixel Shader вы нацеливаетесь?

Я попробовал ваш код, и он правильно сохранил изображение для шейдера PS 2.0.RenderTargetBitmap использует программный рендерер, а PS 3.0 не имеет программного сбоя, поэтому, если вы используете шейдер PS 3.0, он будет проигнорирован.

1 голос
/ 28 января 2014
 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);
...