Pregunta

Actualmente estoy experimentando con PixelShaders introducido con .net 3.5 sp1 para mejorar el rendimiento del procesamiento de imágenes. todo es mucho más rápido, pero hasta ahora solo tuve efectos aplicados a algunos elementos en mis formularios wpf, que realmente quiero evitar.

tenemos un montón de funcionalidades de procesamiento de imágenes y me gustaría reemplazar algunas de las cosas pieza por pieza con sombreadores de píxeles para obtener algo de rendimiento. ¿hay alguna manera de aplicar un sombreador de píxeles a ImageSource sin tener que mostrarlo?

¿Fue útil?

Solución

Para quién todavía necesita esto: Acabo de crear este artículo aquí que muestra cómo hacerlo en WPF. http://www.codeproject.com / Artículos / 642151 / Pixel-shaders-in-a-background-thread-in-WPF

El código relevante copiado a continuación. es de una clase con algunas variables almacenadas

  • Fuente: una ImageSource
  • DpiX, DpiY: dobles que contienen Dpi de origen
  • img: control de imagen WPF
  • viewbox: control WPF ViewBox
  • WPF_DPI_X, WPF_DPI_Y: const se duplica con el valor 96.0

1.la imagen img está incrustada en un Viewbox (también fuera de la pantalla)

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

2.img y viewbox tienen el tamaño de las proporciones correctas, también algunas funciones de diseño se llaman en viewbox. Esto hace que los controles se procesen con el sombreador aplicado.

/// <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. Y para obtener el contenido de la imagen, una " captura de pantalla " si vas a:

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

Además, si desea ejecutar esto en un hilo separado, deberá crear un hilo con

thread.SetApartmentState(ApartmentState.STA);

para obtener más información y un proyecto de demostración, consulte el artículo.

Otros consejos

Al ver que aún no recibió ninguna respuesta de los expertos de C #, trataré de abordar esto desde la perspectiva del desarrollador de C ++ DirectX, esperando que si mi respuesta no es útil, al menos lo guíe en la dirección correcta. Sé poco sobre C # y nada sobre cómo se admiten los PixelShaders, por lo tanto, es probable que esté completamente equivocado y lo que escribo aquí no se aplica en absoluto. En tal caso, siéntase libre de comentar o rechazar el voto según sea necesario

Lo que generalmente se hace en C ++ / DirectX para lograr esto es:

Preparación (hecho una vez)

  • Crear objetivo de renderizado usando CreateRenderTarget
  • Cree una superficie fuera de la pantalla con CreateOffscreenPlainSurface
  • Establecer la superficie de destino de renderizado con SetRenderTarget
  • Cree cualquier otro recurso de entrada necesario (texturas, búferes de vértices ...)

Renderizado (hecho varias veces)

  • Actualizar recursos de entrada (texturas, buffers) según sea necesario
  • Render
  • Copie el contenido del objetivo de representación en la superficie fuera de la pantalla a través de GetRenderTarget
  • Bloquee la superficie fuera de la pantalla y lea su contenido en la CPU
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top