Zyklisches Zeichnen belastet die CPU

  • VB.NET

Es gibt 5 Antworten in diesem Thema. Der letzte Beitrag () ist von eugen_v.

    Zyklisches Zeichnen belastet die CPU

    Hallo alle zusammen!!!
    Habe folgendes Probelm:
    Und zwar möchte ich ein zyklisch alle 100ms ein paar Linien zeichen. Im Hintergrund dieser Linien ist ein Foto.
    Mein Vorgehen:
    1. picFoto ist eine PictureBox, da lade ich das Foto rein.

    VB.NET-Quellcode

    1. picFoto = Image.FromFile(...)

    2. erzeuge eine zweite Picturebox, picLine, wo die linien gezeichnet werden und füge diese der picFoto hinzu.

    VB.NET-Quellcode

    1. picLine = New PictureBox
    2. picLine.BackColor = Color.Transparent
    3. picFoto.Controls.Add(picLine)

    3. zeichne linien

    VB.NET-Quellcode

    1. Dim bmp As New Bitmap(picFoto.Width, picFoto.Height)
    2. Using g As Graphics = Graphics.FromImage(bmp)
    3. Draw Lines(g)
    4. End Using
    5. picLine.Image = bmp

    4. Schritt 3 wird alle 100ms aufgerufen.

    Mein Problem besteht jetzt darin, dass das Foto immer wieder neu gezeichnet. Da die Bilddatein größer ist, beansprucht es den Prozessor sehr stark. gibt es eine Lösung, dieses zu vermeiden?
    Ich würde nicht mit so vielen PB arbeiten.
    Image aus Datei in bitmap laden. Bitmap auf PB zeichnen. Resultierende Bitmap zwischenspeichen. Beim Zeichnen der Linien dann erst die Bitmap reinkopieren und danach dann einfach die Linien drüber malen.
    eat this:

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private bkimage As Bitmap
    3. Private WithEvents tm As New Windows.Forms.Timer With {.Interval = 100, .Enabled = False}
    4. Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    5. bkimage = LoadImageAndResize("Desert.jpg", PictureBox1.ClientRectangle)
    6. PictureBox1.Image = bkimage.Clone
    7. tm.Enabled = True
    8. End Sub
    9. Private Function LoadImageAndResize(ByVal f As String, ByVal rec As Rectangle) As Bitmap
    10. Dim s As New System.IO.FileStream(f, System.IO.FileMode.Open)
    11. Dim bm As Bitmap = Bitmap.FromStream(s)
    12. s.Dispose()
    13. Dim dst As New Bitmap(rec.Width, rec.Height)
    14. Dim g As Graphics = Graphics.FromImage(dst)
    15. g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic
    16. g.DrawImage(bm, rec)
    17. bm.Dispose()
    18. Return dst
    19. End Function
    20. Private Sub tm_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles tm.Tick
    21. PictureBox1.SuspendLayout()
    22. PictureBox1.Image.Dispose()
    23. Dim newbk As Bitmap = bkimage.Clone
    24. Dim g As Graphics = Graphics.FromImage(newbk)
    25. Dim r As New Random
    26. For i = 1 To 10
    27. g.DrawLine(Pens.AntiqueWhite, 0, 0, r.Next(newbk.Width), r.Next(newbk.Height))
    28. Next
    29. PictureBox1.Image = newbk
    30. PictureBox1.ResumeLayout()
    31. End Sub
    32. End Class


    quick and dirty aber so sollte es gehen. Bei mir zuckt jedenfalls nix und die CPU Last liegt auf Leerlauf-Level

    EDIT: A little benchmarked:
    Der Code im Timer_Tick benötigt rund 1000-1500 TICKS (1 Tick = 100 ns), also rund 150 Mikrosekunden, also deutlich weniger als 1 Millisekunde

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

    So, möchte mich für die Antwort nochmals bedanken.

    Habe deinen Lösungsansatz ausprobiert.
    Dabei wird durch die anpassung der Bildauflösung des Fotos, die Bitmap sozusagen kompriemiert.
    Die CPU-Auslastung ist bei dieser Lösung von der PicturBox-Größe abhänging, so dass wenn die Picturebox die Größe des Bildschirms hat (sozusagen Vollbild) die CPU (bei mir) noch mit 10% ausgelastet wird. Perfekt ist das nicht aber auf jeden Fall besser als das was ich hatte.

    Kann man den irgendwie vermeiden, dass das Foto immer wieder aktualisiert (neugezeichnet) wird?
    Meine Idee ist ja mit den zwei PictureBoxen die übereinanderliegen. So wird in die untere das Foto reingeladen und in die obere reingezeichnet.
    ich denke der fehler liegt hierbei in

    VB.NET-Quellcode

    1. picFoto.Controls.Add(picLine)

    Die pictureboxen "verbinden" sich dabei. aber anders kriege ich das obere nicht transparent :(

    Also wenn einer noch Ideen hat...