在屏幕外位图上应用PixelShaders

时间:2008-11-17 11:12:40

标签: c# .net-3.5 image-processing shader

我目前正在尝试使用.net 3.5 sp1引入的PixelShaders来提高图像处理性能。一切都快得多,但直到我只是将效果应用到我的wpf表单中的某些元素,我实际上想要避免。

我们有一堆图像处理功能,我想用像素着色器一块一块地替换其他东西以获得一些性能。 有没有办法将这样的像素着色器应用到ImageSource而不必显示它?

2 个答案:

答案 0 :(得分:3)

看到你还没有从C#专家那里得到任何答案,我将尝试从C ++ DirectX开发人员的角度来解决这个问题,希望如果我的答案没有用,至少会指出你正确的方向。我对C#知之甚少,而且对PixelShaders的支持方式一无所知,因此我可能完全错了,我在这里写的内容根本不适用。在这种情况下,可以根据需要随意评论或投票

通常在C ++ / DirectX中完成的是:

准备(一次完成)

  • 使用CreateRenderTarget
  • 创建渲染目标
  • 使用CreateOffscreenPlainSurface创建离屏表面
  • 使用SetRenderTarget设置渲染目标表面
  • 创建所需的任何其他输入资源(纹理,顶点缓冲区......)

渲染(多次完成)

  • 根据需要更新输入资源(纹理,缓冲区)
  • 渲染
  • 通过GetRenderTarget
  • 将渲染目标的内容复制到屏幕外表面
  • 锁定屏幕外表面并在CPU上读取其内容

答案 1 :(得分:1)

谁还需要这个: 我刚刚在这里创建了这篇文章,展示了如何在WPF中完成它。 http://www.codeproject.com/Articles/642151/Pixel-shaders-in-a-background-thread-in-WPF

下面复制的相关代码。它来自一个带有一些存储变量的类

  • 来源:一个ImageSource
  • DpiX,DpiY:包含源Dpi的双打
  • img:WPF图像控件
  • viewbox:WPF ViewBox控件
  • WPF_DPI_X,WPF_DPI_Y:const加倍,值为96.0

1.图像img嵌入在Viewbox中(也在屏幕外)

//prepare images
img = new Image();
img.Stretch = Stretch.None;
viewbox = new Viewbox();
viewbox.Stretch = Stretch.None;
viewbox.Child = img; //control to render

2.img和viewbox的大小与正确的比例一样,在视图框上也调用了一些布局函数。这样可以在应用着色器的情况下渲染控件。

/// <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.要获取图像的内容,如果您将获得“截图”:

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);
} 

此外,如果要在单独的线程中运行它,则需要使用

创建一个线程
thread.SetApartmentState(ApartmentState.STA);

了解更多信息和演示项目,请参阅文章。