Conseguir um DrawingContext para uma WriteableBitmap WPF
Pergunta
Existe uma maneira de obter uma DrawingContext
(ou algo similar) para um WriteableBitmap
? Ou seja, algo para que você possa chamar simples DrawLine
/ DrawRectangle
/ etc tipos de métodos, em vez de manipular os pixels matérias diretamente.
Solução 4
Parece a palavra não é .
Para referência futura, pretendemos usar uma porta do Writeable Bitmap extensões para WPF.
Para uma solução usando o código puramente existente, qualquer uma das outras sugestões mencionadas abaixo trabalho vontade.
Outras dicas
Eu encontrei solução sixlettervariables o mais viável. No entanto, há uma "drawingContext.Close ()" faltando. De acordo com MSDN, "Um DrawingContext deve ser fechado antes o seu conteúdo pode ser processado". O resultado é o seguinte função de utilidade:
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;
}
Este pode então ser facilmente usado como este:
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));
});
Se você não se importa com System.Drawing
você poderia fazer algo como:
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();
Eu estou perguntando a mesma coisa, como atualmente eu fizer algo como:
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;
}
Eu estou tentando usar o WriteableBitmap para permitir o acesso de vários segmentos para o buffer de pixel, que atualmente não é permitido com nem um DrawingContext nem uma RenderTargetBitmap. Talvez algum tipo de rotina WritePixels baseado fora do que você recuperados do RenderTargetBitmap iria trabalhar?
Uma maneira diferente de resolver este problema é usar um RenderTargetBitmap
como um armazenamento de backup, tal como no exemplo WriteableBitmap
. Em seguida, você pode criar e emissão WPF comandos de desenho a ele quando quiser. Por exemplo:
// 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);
Se você quiser redesenhar esta RenderTargetBitmap
cada quadro, você pode pegar o evento CompositionTarget.Rendering
, como este:
CompositionTarget.Rendering += MyRenderingHandler;