Darstellung/Verwendung großer Bitmaps in VB

  • VB.NET
  • .NET (FX) 3.0–3.5

Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    Darstellung/Verwendung großer Bitmaps in VB

    Hallo Allerseits,

    ich versuche mich gerade in einem Progrämmchen in dem ich Bitmaps aus Waveforms von Musiktiteln erzeuge und dann in einer Picturebox, der jeweiligen Position im Song passend, anzeigen lasse. Das sind in der Regel zwei Bitmaps, von zwei Titeln, die ich übereinander anzeigen lasse. Um die Waveform detailliert zu sehen, muss diese natürlich doch recht groß/lang als Bitmap gezeichnet werden, ich bin mit mir übereingekommen, pro 60s Musik,
    2000 Pixel in der Bitmap-Length zu verwenden, damit die Waveforms die selben Proportionen erhalten. Das sind dann aber eben bei 4min 8000 Pixel lang, (8000x100). Der Picturebox Refresh/Invalidate erfolgt über einen Timer
    mit 10ms Interval. Das funktioniert alles zufriedenstellend, aber ich stellte doch fest, dass bei längeren Titeln, wenn zwei Bitmaps in die Picturebox gezeichnet werden, es zu Verlangsamung von anderen grafischen Controls kommt.
    Hier der Code des PB Paint Sub die ich per Timer aufrufe...

    VB.NET-Quellcode

    1. Private Sub PictureBoxMIX_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBoxMIX.Paint
    2. If btnAB = True Then
    3. If Not WaveImg1 Is Nothing Then
    4. e.Graphics.DrawImage(WaveImg1, New Point((akt_position) + (PictureBoxMIX.Width \ 2), 0))
    5. End If
    6. If Not WaveImg Is Nothing Then
    7. e.Graphics.DrawImage(WaveImg, New Point((akt_position) + (PictureBoxMIX.Width \ 2), 0))
    8. End If
    9. ElseIf btnAB = False Then
    10. If Not WaveImg Is Nothing Then
    11. e.Graphics.DrawImage(WaveImg, New Point(akt_position) + (PictureBoxMIX.Width \ 2), 0))
    12. End If
    13. If Not WaveImg1 Is Nothing Then
    14. e.Graphics.DrawImage(WaveImg1, New Point((akt_position) + (PictureBoxMIX.Width \ 2), 0))
    15. End if
    16. End If
    17. e.Graphics.DrawLine(New Pen(Brushes.White, 1), PictureBoxMIX.Width \ 2, 0, PictureBoxMIX.Width \ 2, Me.PictureBoxMIX.Height - 1)
    18. End Sub


    Ich hatte mit im Programm erzeugten Bitmaps noch nie viel zu tun, deshalb die Frage, gäbe es eine Ressourcenschonendere Methode, oder muss man damit leben bei so großen Grafiken?!
    Die Bitmap als JPG abzuspeichern und die Picturebox auf 8000 zu vergrößern und deren Position passend nach links zu verschieben wird wohl auch kein Ansatz sein, da das ja nur Platz auf der Platte spart, zudem kann ich dann nicht zwei Waveforms übereinander anzeigen.
    Für einen Hinweis wäre ich dankbar, falls jemand mit einem ähnlichen Problem Erfahrung hätte!

    Schönes Wochenende

    Ralph
    @Ralph000 Willkommen im Forum. :thumbup:
    Warum willst Du die Kurve als Bitmap malen? Male sie im Paint-Ereignis mit DrawLine() oder so.
    Gugst Du hier.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hi Rod,

    ich male die Kurve ja nicht "händisch", ich erzeuge und übernehme die Waveform aus der Bass.dll und da bleibt fast nur diese als Bitmap zu übernehmen. Ich habe nach deinem Hinweis versucht
    die Waveform.datas auszulesen und mit drawlines eine Kurve zu zeichnen, allerdings dauert das auslesen auch wieder 1-2 sec. somit habe ich auch wieder eine Verzögerung, und wirklich schön sah das nicht aus, liegt aber sicher an meiner Umsetzung.
    @Ralph000 Wenn also die Bitmap da ist, und Du sie in einer PictureBox darstellen willst, kannst Du mal mit der Property SizeMode experimentieren, wie es am besten aussieht.
    Oder Du malst das ganze im Paint-Event der PictureBox selbst, da sind Deinen Gestaltungswünschen keine Grenzen gesetzt.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    So, nochmals Hi Rod,

    ich hatte jetzt etwas Zeit mich deinem Lösungsvorschlag mit dem Direktzeichnen per DRAWLINE in die PictureBox auseinandergesetzt. Ich komme jetzt an die gerenderten Waveformdaten
    ohne die WF zeichnen zu lassen. Das ist pro 0.01 Sekunden ein Linie. Die betreffende PB hat eine Breite von 1200, somit zeichne ich immer 1200 Linien. Ich mache bis jetzt über eine
    For Next Schleife (ich finde es auch etwas dilettantisch, aber zum testen sollte es reichen), und erhöhe den Startpunkt der Schleife im Timer jeweils um Eins. Soweit funktioniert das jetzt auch
    Die WF verschiebt sich somit und durch die PB. Aber mein großes Problem, ich kriegs nicht hin, dass das Ganze synchron zur Musik läuft. Ich kann die Geschwindigkeit ja nur über den Abstand
    der einzelnen Lines steuern, erhöhe ich den X-Koordinatenwert läuft das natürlich schneller, aber es werden auch weniger Linien gezeichnet, zeichne ich mehr als 1200 Linien, verwende ich mehr Koordinaten, aber der Abstand ist kleiner und die WF läuft auch langsamer von Rechts nach Links.
    Womöglich habe ich mich da irgendwo im Wald verlaufen und sehe Ihn vor lauter Drawlines nicht mehr.

    Gruß Ralph

    Edit: Problem beseitigt, falsche Variablendeklaration, Integer anstatt Single !!!!

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Ralph000“ ()

    Ralph000 schrieb:

    Problem beseitigt
    Es geht vielleicht noch schneller, wenn Du die Bitmap lockst und direkt im Speicher hantierst. Gugst Du hier.
    Sorge dafür, dass die Bit-Per-Pixel-Breite der Bitmap durch 4 teilbar ist und das ganze sollte sehr schnell laufen (weil der Speicher immer auf ganze 4 Byte Breite ausgelegt ist).
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ich würde auf die PictureBox verzichten und stattdessen auf ein einfaches Control setzen, welches du wie hier in Zeile 28 und 29 initialisiert: github.com/stefan-baumann/Mult…nderingSurfaceBase.cs#L28 (ggf. kannst du auch einfach die Klasse als Basis übernehmen, welche ich verlinkt habe)
    Um das eigentliche Zeichnen des Bildausschnittes zu beschleunigen, kannst du auch BitBlt benutzen: mobile.devx.com/tips/dot-net/c…es-in-c-160922003027.html

    Ralph000 schrieb:

    ich versuche mich gerade in einem Progrämmchen in dem ich Bitmaps aus Waveforms von Musiktiteln erzeuge und dann in einer Picturebox, der jeweiligen Position im Song passend, anzeigen lasse
    ...Das funktioniert alles zufriedenstellend, aber ich stellte doch fest, dass bei längeren Titeln, wenn zwei Bitmaps in die Picturebox gezeichnet werden, es zu Verlangsamung von anderen grafischen Controls kommt.



    Wenn Du in der PictureBox nur die Position der Wave anzeigen möchtest, reicht es da nicht die Wave direkt kleiner zu zeichnen, also immer den min. und max. Wert aus z.B. 5 Positionen?
    Und beim abspielen könntest Du dann alle 5 Positionen im Song den Fortschrittbalken in der PictureBox um 1 Pixel verschieben.
    In dem Beispiel wären das dann nur noch 400 Pixel bei 60s.
    Schau mal bei soundcloud.com rein, da pressen die Songs, egal ob 2 Minuten oder 2 Stunden, in 600 Pixel rein.

    oder...
    beide Waves komplett zeichnen, die PictureBoxen und z.B. ein Label (1 Pixel breit) das als Fortschrittbalken dient, auf Panel1 setzen. Dann Panel1 auf Panel2 mit einem HScroll setzen und Panel1 mit dem HScroll verschieben.
    Geht Natürlich auch ohne Hscroll. Dann könntest Du z.B. Panel 1 automatisch verschieben sobald der Fortschrittbalken die Mitte erreicht.
    In dem Beispiel würde dann nur noch der sichtbare Bereich von Panel2 neu gezeichnet werden, und nicht mehr die komplette PictureBox.
    Das Chaos beginnt mit komprimierter Ordnung (Steppenpferd 2019)
    @Ralph000 @Steppenpferd Wie wäre es denn, das ganze dynamisch zu machen, gugt mal hier.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!