Применение PixelShaders к закадровым растровым изображениям

StackOverflow https://stackoverflow.com/questions/295337

Вопрос

В настоящее время я экспериментирую с использованием PixelShaders, представленных в .net 3.5 sp1, для повышения производительности обработки изображений.все происходит намного быстрее, но пока я только что не применил эффекты к некоторым элементам в моих формах wpf, которых я действительно хочу избежать.

у нас есть множество функций обработки изображений, и я хотел бы заменить некоторые другие функции по частям пиксельными шейдерами, чтобы повысить производительность.Есть ли способ применить такой пиксельный шейдер к ImageSource без необходимости его отображения?

Это было полезно?

Решение

Для кого это еще нужно:Я только что создал здесь эту статью, в которой показано, как это сделать в WPF.http://www.codeproject.com/Articles/642151/Pixel-shaders-in-a-background-thread-in-WPF

Соответствующий код скопирован ниже.это из класса с некоторыми хранимыми переменными

  • Источник:источник изображения
  • ДпиХ, ДпиY:двойные значения, содержащие Dpi источника
  • изображение:Управление изображениями WPF
  • окно просмотра:Элемент управления ViewBox WPF
  • WPF_DPI_X, WPF_DPI_Y:const удваивается со значением 96,0

1. Изображение img встроено в окно просмотра (также вне экрана)

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

2.img и окно просмотра имеют правильные пропорции, также в окне просмотра вызываются некоторые функции макета.это заставит элементы управления отображаться с применением шейдера.

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

дополнительную информацию и демонстрационный проект см. в статье.

Другие советы

Поскольку вы еще не получили ответа от экспертов по C#, я постараюсь подойти к этому вопросу с точки зрения разработчика C++ DirectX, надеясь, что если мой ответ бесполезен, то, по крайней мере, он укажет вам правильное направление.Я мало знаю о C# и ничего о том, как поддерживаются PixelShaders, поэтому, скорее всего, я совершенно не прав, и то, что я здесь пишу, вообще не применимо.В таком случае не стесняйтесь комментировать или голосовать против по мере необходимости.

Что обычно делается в C++/DirectX для достижения этой цели:

Подготовка (делается один раз)

  • Создайте цель рендеринга с помощью CreateRenderTarget.
  • Создайте поверхность за пределами экрана с помощью CreateOffscreenPlainSurface.
  • Установите целевую поверхность рендеринга с помощью SetRenderTarget
  • Создайте любые другие необходимые входные ресурсы (текстуры, буферы вершин...)

Рендеринг (выполняется несколько раз)

  • Обновите входные ресурсы (текстуры, буферы) по мере необходимости.
  • Оказывать
  • Скопируйте содержимое цели рендеринга на внеэкранную поверхность с помощью GetRenderTarget.
  • Заблокируйте внеэкранную поверхность и прочитайте ее содержимое на процессоре.
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top