Frage

Ich habe eine WPF-Anwendung auf einem Ultraschallgerät bekommt, die in C ++ mit einer Geschwindigkeit nach oben erzeugten Ultraschallbilder zeigen von 30 Bildern pro Sekunde.

Von dem, was ich verstehe, für die normalen Prozessbilder in WPF Anzeige sind eine Bitmapsource für Ihr Bild zu schaffen und die Quelle für Ihr Bild gesetzt, die dann bewirkt, dass es ungültig zu machen und anzuzeigen.

Da BitmapSources nicht IDisposable implementieren, mit dieser Methode hat mich gezwungen, 30 BitmapSources eine zweite zu erstellen. Für ein 640x480-Bild mit 32bppArgb Format dieses herum 30MB ist / sec der Speicher einen zweiten und dann garbage zugeordnet ist angeordnet, alle 10 Sekunden, so dass sichtbare Verzögerung. Offensichtlich keine akzeptable Lösung.

Meine momentan Lösung ist:

In C ++: erstelle ich ein System.Drawing.Bitmap (WinForms Bitmap) in Managed C ++, führen Sie eine Memcpy von einem Zeiger auf das Bild zu füllen, die Graphics-Objekt verwendet, einige zusätzliche Zeichnung zu tun I müssen, und übergeben diese in die C # / WPF während eines ImageReceived Ereignis.

In C # Image.Source zu einer von BitmapBuffer erzeugt Quelle eingestellt ist, das ist eine Hack-Art und Weise, die Rohdaten der Bitmap-Quelle für den Zugriff: Siehe Link. ich ein P / Invoke von Copymemory kopieren die Daten aus den in den Bitmap.Scan0 BitmapBuffer. Ich habe dann das Bild ungültig macht den Bildschirm zu aktualisieren, und zu Entsorgen (), um das Objekt Drawing.Bitmap den Speicher freizugeben.

Während dieses Verfahren für eine Weile gearbeitet hat, scheint es sehr hacky und ich finde es schwer zu glauben, dass es kein anderer „angemessen“ Weg, dies zu tun, als durch Reflexion.

Frage: Gibt es eine bessere Art und Weise

War es hilfreich?

Lösung

Hier ist ein Code, den ich schrieb * für Aliasing (gemeinsame Nutzung von Speichern) zwischen einer WPF Bitmapsource und einem GDI-Bitmap (für mein eigenes Projekt)

Natürlich müssen Sie es zwicken für Ihre eigenen Bedürfnisse, wird es wahrscheinlich mit einem weniger „Hacky“ Gefühl am Ende landen.

class AliasedBitmapSource : BitmapSource {
    private Bitmap source;
    public AliasedBitmapSource(Bitmap source) {
        this.source = source;
        this.pixelHeight = source.Height;
        this.pixelWidth = source.Width;
        this.dpiX = source.HorizontalResolution;
        this.dpiY = source.VerticalResolution;
    }

    public override event EventHandler DownloadCompleted;
    public override event EventHandler<ExceptionEventArgs> DownloadFailed;
    public override event EventHandler<ExceptionEventArgs> DecodeFailed;

    protected override Freezable CreateInstanceCore() {
        throw new NotImplementedException();
    }

    private readonly double dpiX;
    public override double DpiX {
        get {
            return dpiX;
        }
    }

    private readonly double dpiY;
    public override double DpiY {
        get {
            return dpiY;
        }
    }

    private readonly int pixelHeight;
    public override int PixelHeight {
        get {
            return pixelHeight;
        }
    }

    private readonly int pixelWidth;
    public override int PixelWidth {
        get {
            return pixelWidth;
        }
    }

    public override System.Windows.Media.PixelFormat Format {
        get {
            return PixelFormats.Bgra32;
        }
    }

    public override BitmapPalette Palette {
        get {
            return null;
        }
    }

    public unsafe override void CopyPixels(Int32Rect sourceRect, Array pixels, int stride, int offset) {
        BitmapData sourceData = source.LockBits(
        sourceRect.ToRectangle(),
        ImageLockMode.ReadWrite,
        System.Drawing.Imaging.PixelFormat.Format32bppArgb);

        fixed (byte* _ptr = &((byte[])pixels)[0]) {
            byte* dstptr = _ptr;
            byte* srcptr = (byte*)sourceData.Scan0;

            for (int i = 0; i < pixels.Length; ++i) {
                *dstptr = *srcptr;
                ++dstptr;
                ++srcptr;
            }
        }

        source.UnlockBits(sourceData);
    }
}

public static class Extensions {
    public static Rectangle ToRectangle(this Int32Rect me) {
        return new Rectangle(
        me.X,
        me.Y,
        me.Width,
        me.Height);
    }

    public static Int32Rect ToInt32Rect(this Rectangle me) {
        return new Int32Rect(
        me.X,
        me.Y,
        me.Width,
        me.Height);
    }
}

* von "schrieb" ich meine "warf zusammen in 10 Minuten"

Andere Tipps

Wenn Sie die neuesten WPF Bits überprüfen verwenden

scroll top