E 'possibile modificare un WPF BitmapSource in memoria 'unsafe'ly da un altro thread
-
29-09-2019 - |
Domanda
Mi piacerebbe fare un po 'di elaborazione di immagini in un'applicazione WPF. Tuttavia, vorrei modificare i pixel di un BitmapSource in memoria in fase di esecuzione.
Attualmente sto riuscendo a fare questo codice usando 'non sicuro' contro un vecchio System.Drawing.Bitmap stile e funziona un ossequio (bloccare un area di lavoro, violino con i pixel) lavoro fatto. L'approccio è descritto in questo post: http://blogs.msdn.com/b/ericgu/archive/2007/06/20/lost-column-2-unsafe-image-processing.aspx
Per ottenere questo lavoro in WPF Sto quindi la creazione di un WPF BitmapSource utilizzando questo approccio:
BitmapSource destination;
IntPtr hBitmap = bitmap.GetHbitmap();
BitmapSizeOptions sizeOptions = BitmapSizeOptions.FromEmptyOptions();
destination = Imaging.CreateBitmapSourceFromHBitmap(hBitmap, IntPtr.Zero, Int32Rect.Empty, sizeOptions);
destination.Freeze();
return destination;
Tuttavia, questo crea un sacco di copie in memoria e ho davvero voglia di arrivare lì e violino con i bit sottostanti all'interno del BitmapSource proprio come EricGu mostrato nell'esempio Bitmap. È possibile?
Mi rendo conto che PixelShaders probabilmente può fare questo, ma questo è un esercizio accademico che coinvolge più thread (che è supportato durante la modifica di una bitmap in modalità non sicura).
Grazie in anticipo
Soluzione
ti dirò quanto ne so.
Per prima cosa sembrano sapere già circa congelamento bitmap prima di dare di nuovo al thread principale. Questo è un buon inizio.
Ho una volta cercato di ridurre la copia derivando una nuova implementazione da BitmapSource, e sostituire le funzioni virtuali che copiare i dati fuori dalla bitmap. Ha funzionato ma produce perdite di memoria di massa. Mai capito.
È possibile anche, naturalmente, creare un BitmapSource direttamente da un array di byte (e perdere sovraccarico di bitmap GDI). MSDN docs
Avete considerato un WriteableBitmap ? Quella era la risposta del team di WPF alla lamentela comune su tutte le copie.
Modifica : MSDN dice esplicitamente (nella documentazione WritableBitmap.BackBuffer), che può essere utilizzato da un thread in background:
È possibile passare il puntatore a BackBuffer componenti esterni e altri thread per l'elaborazione, ma se lo fai, deve offrire proprio thread coordinazione. In particolare, è necessario assicurare che specifica thread UI aree mutate chiamando il Metodo AddDirtyRect, e che l'IU filo sblocca il buffer chiamando il metodo di sblocco.
Quindi, se si lascia che la thread UI acquisire il blocco e il puntatore, è possibile lasciare che un thread di lavoro di scrittura dei pixel.