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.

Foi útil?

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;
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top