【发布时间】:2010-09-10 10:48:17
【问题描述】:
有没有办法为WriteableBitmap 获取DrawingContext(或类似的东西)? IE。可以让你调用简单的DrawLine/DrawRectangle/等方法,而不是直接操作原始像素。
【问题讨论】:
有没有办法为WriteableBitmap 获取DrawingContext(或类似的东西)? IE。可以让你调用简单的DrawLine/DrawRectangle/等方法,而不是直接操作原始像素。
【问题讨论】:
我发现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;
}
这可以很容易地像这样使用:
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));
});
【讨论】:
.Close() 隐含在.Dispose() 中——这是using 语句背后的全部要点。如果您将仅 render(...) 命令留在 using 块中,您会没事的,不需要任何 .Close()。
WriteableBitmap,为什么它是第一位的? :) 这与问题完全无关。
WritaBleBitmap result = new WritableBitmap(image);
如果您不介意使用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();
【讨论】:
我想知道同样的事情,因为目前我正在做类似的事情:
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;
}
我正在尝试使用 WriteableBitmap 来允许对像素缓冲区进行多线程访问,目前无论是 DrawingContext 还是 RenderTargetBitmap 都不允许这样做。也许某种基于您从 RenderTargetBitmap 检索到的内容的 WritePixels 例程会起作用?
【讨论】:
bmp.Freeze()。
【讨论】:
解决此问题的另一种方法是使用RenderTargetBitmap 作为后备存储,就像在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);
如果你想每帧重绘这个RenderTargetBitmap,你可以捕捉CompositionTarget.Rendering事件,像这样:
CompositionTarget.Rendering += MyRenderingHandler;
【讨论】: