2008-11-17 2 views
4

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

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

ответ

1

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

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

  • Источник: ImageSource
  • DPix, DpiY: двойники, содержащие ДПИ источника
  • IMG: WPF управления Image
  • ViewBox: WPF управления ViewBox
  • WPF_DPI_X, WPF_DPI_Y: Const удваивается со значением 96,0

1.the Image 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.And, чтобы получить содержание изображения, в «кадр», если вы:

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

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

3

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

Что обычно делается в C++/DirectX для того чтобы достигнуть этого:

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

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

рендеринга (сделано несколько раз)

  • Update входные ресурсы (текстуры, буферы) по мере необходимости
  • Рендер
  • Скопируйте содержимое цели рендеринга на поверхность вне экрана через GetRenderTarget
  • Заблокируйте поверхность вне экрана и прочитайте ее содержимое на ЦПУ
Смежные вопросы