Ottenere un DrawingContext per una wpf WriteableBitmap
Domanda
C'è un modo per ottenere un DrawingContext
(o qualcosa di simile) per a WriteableBitmap
?Cioè.qualcosa che ti permetta di chiamare semplice DrawLine
/DrawRectangle
/etc tipi di metodi, invece di manipolare direttamente i pixel grezzi.
Soluzione 4
Sembra la parola è no.
Per riferimento futuro, prevediamo di utilizzare una porta di Estensioni bitmap scrivibili per WPF.
Per una soluzione che utilizza codice puramente esistente, funzionerà qualsiasi altro suggerimento menzionato di seguito.
Altri suggerimenti
Ho trovato la soluzione di sixlettervariables quella più praticabile.Tuttavia, manca un "drawingContext.Close()".Secondo MSDN, "Un DrawingContext deve essere chiuso prima che il suo contenuto possa essere visualizzato".Il risultato è la seguente funzione di utilità:
public static BitmapSource CreateBitmap(
int width, int height, double dpi, Action<DrawingContext> render)
{
DrawingVisual drawingVisual = new DrawingVisual();
using (DrawingContext drawingContext = drawingVisual.RenderOpen())
{
render(drawingContext);
}
RenderTargetBitmap bitmap = new RenderTargetBitmap(
width, height, dpi, dpi, PixelFormats.Default);
bitmap.Render(drawingVisual);
return bitmap;
}
Questo può quindi essere facilmente utilizzato in questo modo:
BitmapSource image = ImageTools.CreateBitmap(
320, 240, 96,
drawingContext =>
{
drawingContext.DrawRectangle(
Brushes.Green, null, new Rect(50, 50, 200, 100));
drawingContext.DrawLine(
new Pen(Brushes.White, 2), new Point(0, 0), new Point(320, 240));
});
Se non ti dispiace usare System.Drawing
potresti fare qualcosa del tipo:
var wb = new WriteableBitmap( width, height, dpi, dpi,
PixelFormats.Pbgra32, null );
wb.Lock();
var bmp = new System.Drawing.Bitmap( wb.PixelWidth, wb.PixelHeight,
wb.BackBufferStride,
PixelFormat.Format32bppPArgb,
wb.BackBuffer );
Graphics g = System.Drawing.Graphics.FromImage( bmp ); // Good old Graphics
g.DrawLine( ... ); // etc...
// ...and finally:
g.Dispose();
bmp.Dispose();
wb.AddDirtyRect( ... );
wb.Unlock();
Mi chiedo la stessa cosa, dato che attualmente faccio qualcosa del tipo:
DrawingVisual drawingVisual = new DrawingVisual();
using (DrawingContext drawingContext = drawingVisual.RenderOpen())
{
//
// ... draw on the drawingContext
//
RenderTargetBitmap bmp = new RenderTargetBitmap(width, height, dpi, dpi, PixelFormats.Default);
bmp.Render(drawingVisual);
image.Source = bmp;
}
Sto cercando di utilizzare WriteableBitmap per consentire l'accesso multithread al buffer pixel, che attualmente non è consentito né con DrawingContext né con RenderTargetBitmap.Forse una sorta di routine WritePixels basata su ciò che hai recuperato da RenderTargetBitmap funzionerebbe?
Un modo diverso per risolvere questo problema è utilizzare a RenderTargetBitmap
come negozio di supporto, proprio come in WriteableBitmap
esempio.Quindi puoi creare ed inviare comandi di disegno WPF ogni volta che vuoi.Per esempio:
// create the backing store in a constructor
var backingStore =
new RenderTargetBitmap(200,200,97,97,PixelFormats.Pbgra32);
myImage.Source = backingStore;
// whenever you want to update the bitmap, do:
var drawingVisual = new DrawingVisual();
var drawingContext = drawingVisual.RenderOpen();
{
// your drawing commands go here
drawingContext.DrawRectangle(
Brushes.Red, new Pen(),
new Rect(this.RenderSize));
}
Render(drawingContext);
drawingContext.Close();
backingStore.Render(drawingVisual);
Se vuoi ridisegnarlo RenderTargetBitmap
ogni fotogramma, puoi catturare il CompositionTarget.Rendering
evento, in questo modo:
CompositionTarget.Rendering += MyRenderingHandler;