Domanda

Attualmente sto sperimentando l'utilizzo di PixelShaders introdotto con .net 3.5 sp1 per migliorare le prestazioni di elaborazione delle immagini. tutto è molto più veloce, ma fino ad ora ho avuto effetti applicati ad alcuni elementi nelle mie forme di wpf, che in realtà voglio evitare.

abbiamo un sacco di funzionalità di elaborazione delle immagini e vorrei sostituire alcune delle cose pezzo per pezzo con pixel shader per ottenere alcune prestazioni. c'è un modo per applicare un pixel shader simile a un ImageSource senza doverlo visualizzare?

È stato utile?

Soluzione

Per chi ha ancora bisogno di questo: Ho appena creato questo articolo qui che mostra come farlo in WPF. http://www.codeproject.com / Articoli / 642.151 / pixel-shader-in-a-background-thread-in-WPF

Il codice pertinente copiato di seguito. proviene da una classe con alcune variabili memorizzate

  • Fonte: una fonte di immagini
  • DpiX, DpiY: raddoppia contenente Dpi di origine
  • img: controllo immagine WPF
  • viewbox: controllo ViewBox WPF
  • WPF_DPI_X, WPF_DPI_Y: const raddoppia con valore 96.0

1. the Image img è incorporato in una Viewbox (anche 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 e viewbox sono dimensionati nelle proporzioni corrette, anche alcune funzioni di layout sono chiamate su viewbox. questo rende i controlli render con lo shader applicato.

/// <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.E per ottenere il contenuto dell'immagine, uno "screenshot" se vuoi:

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

Inoltre, se vuoi eseguirlo in un thread separato dovrai creare un thread con

thread.SetApartmentState(ApartmentState.STA);

per maggiori informazioni e un progetto demo, vedi l'articolo.

Altri suggerimenti

Vedendo che non hai ancora ricevuto risposta dagli esperti di C #, proverò ad approcciarlo dal punto di vista dello sviluppatore di DirectX C ++, sperando che se la mia risposta non è utile, almeno ti indicherà la giusta direzione. So poco di C # e nulla di come sono supportati PixelShaders, quindi la possibilità è completamente sbagliata e ciò che scrivo qui non si applica affatto. In tal caso, non esitare a commentare o votare in basso secondo necessità

Ciò che viene generalmente fatto in C ++ / DirectX per raggiungere questo obiettivo è:

Preparazione (eseguita una volta)

  • Crea target di rendering usando CreateRenderTarget
  • Crea superficie fuori schermo usando CreateOffscreenPlainSurface
  • Imposta la superficie di destinazione del rendering usando SetRenderTarget
  • Crea qualsiasi altra risorsa di input necessaria (Textures, Buffer di vertici ...)

Rendering (eseguito più volte)

  • Aggiorna le risorse di input (trame, buffer) secondo necessità
  • Render
  • Copia il contenuto del target di rendering nell'area off-screen tramite GetRenderTarget
  • Blocca la superficie fuori schermo e leggi il suo contenuto sulla CPU
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top