Reputation: 9871
i'm currently experimenting using PixelShaders introduced with .net 3.5 sp1 to improve image processing performance. everything is much faster , but til yet i just had effects applied to some elements in my wpf forms, that i actually want to avoid.
we have a bunch of image processing functionality and i'd like to replace some othe the stuff piece by piece with pixel shaders to gain some performance. is there a way to apply such a pixel shader to an ImageSource without having to display it?
Upvotes: 4
Views: 1348
Reputation: 34393
What is generally done in C++ / DirectX to achive this is:
Preparation (done once)
Rendering (done multiple times)
Upvotes: 4
Reputation: 741
For who still needs this: I just created this article here that shows how to do it in WPF. http://www.codeproject.com/Articles/642151/Pixel-shaders-in-a-background-thread-in-WPF
The relevant code copied below. it is from a class with some stored variables
1.the Image img is embedded in a Viewbox (also off-screen)
//prepare images
img = new Image();
img.Stretch = Stretch.None;
viewbox = new Viewbox();
viewbox.Stretch = Stretch.None;
viewbox.Child = img; //control to render
2.img and viewbox are sized to the correct proportions, also some layout functions are called on viewbox. this make the controls render with the shader applied.
/// <summary>
/// Loads the image and viewbox for off-screen rendering.
/// </summary>
public void LoadImage(double width, double height)
{
img.BeginInit();
img.Width = width;
img.Height = height;
img.Source = Source;
img.EndInit();
viewbox.Measure(new Size(img.Width, img.Height));
viewbox.Arrange(new Rect(0, 0, img.Width, img.Height));
viewbox.UpdateLayout();
}
3.And to get the contents of the image, a "screenshot" if you will:
void SaveUsingEncoder(BitmapEncoder encoder, Stream stream)
{
RenderTargetBitmap bitmap = new RenderTargetBitmap((int)(img.Width * DpiX / WPF_DPI_X), (int)(img.Height * DpiY / WPF_DPI_Y), DpiX, DpiY, PixelFormats.Pbgra32);
bitmap.Render(viewbox);
BitmapFrame frame = BitmapFrame.Create(bitmap);
encoder.Frames.Add(frame);
encoder.Save(stream);
}
Also, if you want to run this in a separate thread you will need to create a thread with
thread.SetApartmentState(ApartmentState.STA);
for more info and a demo project, see the article.
Upvotes: 2