Есть ли способ получить DrawingContext
(или что-то подобное) для WriteableBitmap
? То есть что позволит вам называть простые методы DrawLine
/DrawRectangle
/etc, а не напрямую манипулировать исходными пикселями.
Получение DrawingContext для wpf WriteableBitmap
Ответ 1
Появляется слово не равно.
В будущем мы планируем использовать порт Записываемые расширения Bitmap для WPF.
Для решения, использующего только существующий код, любые другие рекомендации, упомянутые ниже, будут работать.
Ответ 2
Я нашел решение sixlettervariables наиболее работоспособным. Однако отсутствует "drawContext.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));
});
Ответ 3
Если вы не против использования 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();
Ответ 4
Мне интересно то же самое, что и в настоящее время я делаю что-то вроде:
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. Может быть, какая-то рутина WritePixels, основанная на том, что вы извлекли из RenderTargetBitmap, будет работать?
Ответ 5
Другой способ решить эту проблему - использовать 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;