Getting a DrawingContext for a wpf WriteableBitmap
I found sixlettervariables' solution the most workable one. However, there's a "drawingContext.Close()" missing. According to MSDN, "A DrawingContext must be closed before its content can be rendered".The result is the following utility function:
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;}
This can then easily be used like this:
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)); });
If you don't mind using System.Drawing
you could do something like:
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 Graphicsg.DrawLine( ... ); // etc...// ...and finally:g.Dispose(); bmp.Dispose();wb.AddDirtyRect( ... );wb.Unlock();
I'm wondering the same thing, as currently I do something like:
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;}
I'm trying to use the WriteableBitmap to allow multithreaded access to the pixel buffer, which is currently not allowed with neither a DrawingContext nor a RenderTargetBitmap. Maybe some sort of WritePixels routine based off of what you've retrieved from the RenderTargetBitmap would work?