Getting a DrawingContext for a wpf WriteableBitmap

前端 未结 5 414
逝去的感伤
逝去的感伤 2020-11-30 05:15

Is there a way to get a DrawingContext (or something similar) for a WriteableBitmap? I.e. something to allow you to call simple DrawLine

相关标签:
5条回答
  • 2020-11-30 05:25

    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));
        });
    
    0 讨论(0)
  • 2020-11-30 05:25

    A different way to solve this problem is to use a RenderTargetBitmap as a backing store, just like in the WriteableBitmap example. Then you can create and issue WPF drawing commands to it whenever you want. For example:

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

    If you want to redraw this RenderTargetBitmap every frame, you can catch the CompositionTarget.Rendering event, like this:

    CompositionTarget.Rendering += MyRenderingHandler;
    
    0 讨论(0)
  • 2020-11-30 05:33

    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?

    0 讨论(0)
  • 2020-11-30 05:34

    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 Graphics
    
    g.DrawLine( ... ); // etc...
    
    // ...and finally:
    g.Dispose(); 
    bmp.Dispose();
    wb.AddDirtyRect( ... );
    wb.Unlock();                    
    
    0 讨论(0)
  • 2020-11-30 05:42

    It appears the word is no.


    For future reference, we plan to use a port of the Writeable Bitmap Extensions for WPF.

    For a solution using purely existing code, any of the other suggestions mentioned below will work.

    0 讨论(0)
提交回复
热议问题