2008-09-17 18 views

Antwort

4

Es erscheint the word is no.


Für die Zukunft planen wir, einen Port des Writeable Bitmap Extensions für WPF zu verwenden.

Für eine Lösung, die ausschließlich vorhandenen Code verwendet, funktionieren alle anderen unten aufgeführten Vorschläge.

+0

Das ist kein offizielles Wort. Das ist nur irgendein Typ, der etwas in einem Forum sagt. –

+0

Punkt genommen; Aktualisierter Text. Ich nehme an, du könntest sagen, dass es "offiziell" bedeutet, wie in "in einem Forum gepostet von Beamten überwacht, und nicht von ihnen korrigiert", aber das ist ein bisschen eine Strecke :) –

5

Ich frage mich das Gleiche, wie zur Zeit mache ich so etwas wie:

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

Ich versuche, die Writeablebitmap zu verwenden multithreaded Zugriff auf die Pixelpuffer zu ermöglichen, die derzeit mit nicht erlaubt ist, weder ein DrawingContext oder eine RenderTargetBitmap. Vielleicht würde eine Art WritePixels-Routine, die auf dem basiert, was Sie aus der RenderTargetBitmap abgerufen haben, funktionieren?

+0

Render verbringen zu lange – lindexi

+0

Sie kann nicht die bmp.Render schreiben Sie sich mit der das kann die drawingVisual nicht bekommen. – lindexi

15

Wenn Sie nichts dagegen nicht System.Drawing verwenden könnten Sie so etwas wie:

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

Ich hatte keine Chance, es auszuprobieren gerade noch, aber das scheint eine sehr vernünftige Problemumgehung in WPF zu sein. Vielen Dank! –

+1

Nur für den Fall, dass sich jemand fragt, habe ich die DrawingVisual WPF-Methode getestet, die in diesem Thema und dieser System.Drawing-Methode erwähnt wird, und diese System.Drawing-Methode ist VIEL SCHNELLER. Ich bin sehr enttäuscht von WPF. – Verax

+1

Sie können das gleiche mit WPF tun, mit ähnlicher (oder besser?) Leistung mit RenderTargetBitmap und DrawingVisual/DrawingContext –

19

I sixlettervariables' Lösung der machbaren gefunden. Es fehlt jedoch ein "drawingContext.Close()". Laut MSDN "muss ein DrawingContext geschlossen werden, bevor der Inhalt gerendert werden kann". Das Ergebnis ist die folgende Nutzenfunktion:

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

Dies kann dann so leicht verwendet werden:

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

Die '.Close()' ist implizit in der '.Dispose()' - was ist der ganze Punkt dahinter die 'using'-Anweisung. Wenn Sie * nur * den Befehl 'render (...)' innerhalb des using-Blocks belassen, ist alles in Ordnung und Sie brauchen kein '.Close()'. –

+0

Danke Eamon. Ich habe den Fehler im Code behoben. –

+4

In dieser Antwort gibt es keine 'WriteableBitmap', warum ist sie die beste? :) Es ist völlig unabhängig von der Frage. –

1

Eine andere Möglichkeit, dieses Problem zu lösen, ist ein RenderTargetBitmap als Hintergrundspeicher zu bedienen, einfach wie in dem WriteableBitmap Beispiel. Dann können Sie jederzeit WPF-Zeichenbefehle erstellen und ausgeben. Zum Beispiel:

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

Wenn Sie diese RenderTargetBitmap jeden Frame neu zu zeichnen wollen, können Sie das CompositionTarget.Rendering Ereignis, wie diese fangen:

CompositionTarget.Rendering += MyRenderingHandler; 
Verwandte Themen