Obtendo um DrawingContext para um writeableBitmap wpf

Existe uma maneira de obter um DrawingContext (ou algo semelhante) para um WriteableBitmap ? DrawLine seja, algo para permitir que você chame tipos de methods simples de DrawLine / DrawRectangle / etc, em vez de manipular diretamente os pixels brutos.

Eu encontrei a solução de seis letras mais viável. No entanto, há um “drawingContext.Close ()” em falta. Segundo o MSDN, “Um DrawingContext deve ser fechado antes que seu conteúdo possa ser renderizado”. O resultado é a seguinte function de utilidade:

 public static BitmapSource CreateBitmap( int width, int height, double dpi, Action 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; } 

Isso pode ser facilmente usado assim:

 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 você não se importa em usar o System.Drawing você pode fazer algo como:

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

Eu estou querendo saber a mesma coisa, como atualmente eu faço algo como:

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

Eu estou tentando usar o WriteableBitmap para permitir o access multithread ao buffer de pixel, que atualmente não é permitido nem com um DrawingContext nem um RenderTargetBitmap. Talvez algum tipo de rotina WritePixels baseada no que você recuperou do RenderTargetBitmap funcionaria?

Parece que a palavra é não .


Para referência futura, planejamos usar uma porta das extensões de bitmap graváveis ​​do WPF.

Para uma solução usando código puramente existente, qualquer uma das outras sugestões mencionadas abaixo funcionará.

Uma maneira diferente de resolver esse problema é usar um RenderTargetBitmap como um armazenamento de apoio, como no exemplo de WriteableBitmap . Em seguida, você pode criar e emitir comandos de desenho do WPF para ele sempre que desejar. Por exemplo:

 // 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 você quiser redesenhar este RenderTargetBitmap cada frame, você pode pegar o evento CompositionTarget.Rendering , assim:

 CompositionTarget.Rendering += MyRenderingHandler;