为 wpf WriteableBitmap 获取 DrawingContext

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/88488/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 19:37:27  来源:igfitidea点击:

Getting a DrawingContext for a wpf WriteableBitmap

wpfbitmapdrawing

提问by Emperor XLII

Is there a way to get a DrawingContext(or something similar) for a WriteableBitmap? I.e. something to allow you to call simple DrawLine/DrawRectangle/etc kinds of methods, rather than manipulate the raw pixels directly.

有没有办法获得 a DrawingContext(或类似的东西)WriteableBitmap?即允许您调用简单的DrawLine/ DrawRectangle/etc 类型的方法,而不是直接操作原始像素。

采纳答案by Emperor XLII

It appears the word is no.

看来这个词是 no



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

为了将来参考,我们计划使用WPF 的可写位图扩展的一个端口。

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

对于使用纯粹现有代码的解决方案,下面提到的任何其他建议都将起作用。

回答by Daniel Wolf

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:

我发现 Sixlettervariables 的解决方案是最可行的解决方案。但是,缺少“drawingContext.Close()”。根据 MSDN,“必须先关闭 DrawingContext,然后才能呈现其内容”。结果是以下效用函数:

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

回答by Danko Durbi?

If you don't mind using System.Drawingyou could do something like:

如果您不介意使用,System.Drawing您可以执行以下操作:

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

回答by user7116

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?

我正在尝试使用 WriteableBitmap 来允许对像素缓冲区进行多线程访问,目前这在 DrawingContext 和 RenderTargetBitmap 中都是不允许的。也许基于您从 RenderTargetBitmap 检索到的内容的某种 WritePixels 例程会起作用?

回答by David Jeske

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

解决此问题的另一种方法是使用 aRenderTargetBitmap作为后备存储,就像在WriteableBitmap示例中一样。然后,您可以随时创建并向其发出 WPF 绘图命令。例如:

// 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 RenderTargetBitmapevery frame, you can catch the CompositionTarget.Renderingevent, like this:

如果你想RenderTargetBitmap每帧重绘这个,你可以捕捉CompositionTarget.Rendering事件,像这样:

CompositionTarget.Rendering += MyRenderingHandler;