Bild scrollen

  • VB.NET

Es gibt 22 Antworten in diesem Thema. Der letzte Beitrag () ist von Otti.

    Bild scrollen

    Hey, zusammen.

    Es geht wie bereits im Thema zu erkennen, um ein Bild welches nicht dreht, sondern scrollen soll.
    Sofern das Bild an ende angekommen ist , soll es wieder neu gezeichnet werden.

    Habe da leider nix passendes finden können und einen Ansatz habe ich auch nicht.

    Hatte mal ein Bild drehen lassen, dies hatte ich so gelöst.
    Vielleicht kann man den Code ja etwas abändern, jemand eine Idee?

    Bild drehen:

    VB.NET-Quellcode

    1. Public Function RotateImage(ByVal Image As Image, ByVal Angle As Integer) As Image
    2. Dim bmp As New Bitmap(Image.Width, Image.Height)
    3. Dim m As New Drawing2D.Matrix
    4. m.RotateAt(Angle, New PointF(Image.Width / 2, Image.Height / 2))
    5. With Graphics.FromImage(bmp)
    6. .Transform = m
    7. .DrawImage(Image, 0, 0)
    8. End With
    9. Return CType(bmp, Image)
    10. End Function
    11. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    12. PictureBox1.Hide()
    13. Me.DoubleBuffered = True
    14. Timer1.Start()
    15. Timer1.Interval = 20
    16. End Sub
    17. Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    18. img = PictureBox1.Image
    19. Static Angle As Integer
    20. Angle += 1
    21. Dim bmp As New Bitmap(Me.Width, Me.Height)
    22. Dim Graph As Graphics = Graphics.FromImage(bmp)
    23. Graph.DrawImage(RotateImage(img, Angle), PictureBox1.Location.X, PictureBox1.Location.Y)
    24. Graph.Dispose()
    25. Me.Ba


    In Anhang mal ein Beispiel Bild um es etwas verständlicher zu machen.
    Wie gesagt sollte das Bild Vertikal in einer Endlosschleife scrollen.
    Bilder
    • Bild1.png

      3,69 kB, 236×836, 161 mal angesehen
    @Otti Aus wie vielen Hauptbestandteilen (hier: 8) besteht denn Dein Bild?
    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!
    @Otti Ich hab mal Frau Google nach c# ScrollBitmap befragt.
    Die Antwort 3 scheint vielversprechend:
    docs.microsoft.com/en-us/windo…l-a-bitmap-in-scroll-bars
    Achtung, das ist C++, da kannstr Du Dir vielleicht ne Idee abgucken.
    Ich werd mal was probieren.
    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

    Ich würde ein neues Bitmap in gleicher Größe wie das Original erstellen. Vom neuen Bitmap ein Graphics und das Originalbild mit passender DrawImage Methode 2 mal reinzeichnen. Da kann man ja angeben welcher Bereich vom Original wohin im Graphics gezeichnet werden soll.
    Mfg -Franky-
    @Otti Form mit Button, PictureBox und Timer und ein Bild auf der Festplatte:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.Drawing.Imaging
    2. Imports System.Runtime.InteropServices
    3. Public Class Form1
    4. ReadOnly MyBmp As New Bitmap("C:\Temp\EinBild.jpg")
    5. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    6. Me.PictureBox1.Image = Me.MyBmp
    7. Me.Timer1.Interval = 10
    8. End Sub
    9. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    10. Me.Timer1.Enabled = Not Me.Timer1.Enabled
    11. End Sub
    12. Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    13. Me.PictureBox1.Image = Form1.ScrollUp(Me.MyBmp)
    14. End Sub
    15. ''' <summary>
    16. ''' Scrollt die Bitmap un eine Zeile nach oben
    17. ''' </summary>
    18. ''' <param name="bmp">die Bitmap</param>
    19. ''' <returns>die gescrollte Bitmap</returns>
    20. Private Shared Function ScrollUp(bmp As Bitmap) As Image
    21. ' Bitmap locken
    22. Dim bmpData = bmp.LockBits(New Rectangle(Point.Empty, bmp.Size), ImageLockMode.ReadWrite, bmp.PixelFormat)
    23. ' Declare an array to hold the bytes of the bitmap.
    24. Dim bytes = Math.Abs(bmpData.Stride) * bmp.Height
    25. Dim rgbValues = New Byte(bytes) {}
    26. ' Speicher für eine Zeile
    27. Dim line = New Byte(bmpData.Stride) {}
    28. ' die erste Zeile wegspeichern
    29. Marshal.Copy(bmpData.Scan0, line, 0, bmpData.Stride)
    30. ' Pointer auf die zweite Zeile
    31. Dim Second As IntPtr = bmpData.Scan0 + bmpData.Stride
    32. ' Bitmap zeilenverschoben rauskopieren
    33. Marshal.Copy(Second, rgbValues, 0, bytes - bmpData.Stride)
    34. ' erste Zeile hinten dran kopieren
    35. Array.Copy(line, 0, rgbValues, bytes - bmpData.Stride, bmpData.Stride)
    36. ' Array in die Bitmap zurückkopieren
    37. Marshal.Copy(rgbValues, 0, bmpData.Scan0, bytes)
    38. bmp.UnlockBits(bmpData)
    39. Return bmp
    40. End Function
    41. End Class
    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!
    @Otti
    RodFromGermany hat ja schon eine sehr interessante Lösung gepostet. Ich möchte Dir dennoch den Weg zeigen, den ich ja weiter oben beschrieben hatte. Dann hast gleich zwei Möglichkeiten die Du ausprobieren kannst.
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Option Strict On
    2. Option Explicit On
    3. Public Class Form1
    4. ReadOnly MyBmp As New Bitmap("D:\Programming\VBC\GDI+\City001.jpg")
    5. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    6. Me.PictureBox1.Image = Me.MyBmp
    7. Me.Timer1.Interval = 10
    8. End Sub
    9. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    10. Me.Timer1.Enabled = Not Me.Timer1.Enabled
    11. End Sub
    12. Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    13. ' pixel > 0 = Scroll down
    14. ' pixel < 0 = Scroll up
    15. Me.PictureBox1.Image = Form1.ScrollUpOrDown(Me.MyBmp, 1)
    16. End Sub
    17. Private Shared Function ScrollUpOrDown(bmp As Bitmap, Optional pixel As Integer = 1) As Image
    18. If pixel <> 0 Then
    19. Dim stepping As Integer = Math.Abs(pixel)
    20. Using bmpOut As New Bitmap(bmp.Width, bmp.Height)
    21. Using gra As Graphics = Graphics.FromImage(bmpOut)
    22. If pixel > 0 Then
    23. gra.DrawImage(bmp, New Rectangle(0, 0, bmpOut.Width, stepping),
    24. New Rectangle(0, bmp.Height - stepping, bmp.Width, stepping),
    25. GraphicsUnit.Pixel)
    26. ElseIf pixel < 0 Then
    27. gra.DrawImage(bmp, New Rectangle(0, bmpOut.Height - stepping, bmpOut.Width, stepping),
    28. New Rectangle(0, 0, bmp.Width, stepping), GraphicsUnit.Pixel)
    29. End If
    30. gra.DrawImage(bmp, New Rectangle(0, pixel, bmpOut.Width, bmpOut.Height - pixel),
    31. New Rectangle(0, 0, bmp.Width, bmp.Height - pixel), GraphicsUnit.Pixel)
    32. End Using
    33. Using gra As Graphics = Graphics.FromImage(bmp)
    34. gra.DrawImage(bmpOut, 0, 0, bmp.Width, bmp.Height)
    35. End Using
    36. End Using
    37. End If
    38. Return bmp
    39. End Function
    40. End Class

    Mfg -Franky-
    @Otti Und mach gleich einen Benchmark-Test.
    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!
    @RodFromGermany
    @-Franky-

    Hey Ihr beiden... Vielen Lieben Dank dafür, es ist so ungefähr was ich mich vorgestellt habe.
    Habe dazu jedoch noch zwei Fragen.
    Die erste wäre, ob das scrollen auch schneller geht?
    Die zweite wäre, da ich ja unterschiedliche Felder (In dem Beispiel Bild wäre es Feld 1-8) , diese auch nach Timer Stopp an
    einen bestimmten Feld stehen bleiben kann?

    Die Schnelligkeit habe ich heraus gefunden wie ich diese beschleunige, verstehe allerdings nicht wie???
    Me.PictureBox1.Image = Form1.ScrollUpOrDown(Me.MyBmp, 1)
    was sagt denn die 1 aus?
    Sind das die Pixel?

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Otti“ ()

    Otti schrieb:

    Habe dazu jedoch noch zwei Fragen.
    Poste eine vollständige und belastbare Aufgabenstellung / Problembeschreibung.

    Otti schrieb:

    was sagt denn die 1 aus?
    Den Code ansehen, überlegen und wissen.



    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!
    ok war ein bisschen unverständlich...
    - Ja die 1, sind meine Pixel, daher scrollt das Bild schnell. Soweit klar.

    Aufgabenstellung / Problem Beschreibung wäre wie folgt:
    - Ich würde gerne die Bilder im ganzen angezeigt bekommen sofern der Timer gestoppt wird, um das voll Bild zu erkenne.
    Ein Beispiel im Anhang.
    Bilder
    • so nicht.PNG

      2,43 kB, 240×334, 151 mal angesehen
    • so.PNG

      2,06 kB, 235×316, 151 mal angesehen

    Otti schrieb:

    im ganzen angezeigt bekommen
    Warum fängt Dein Bild nicht bei [1] an?
    Zähle die Schritte und wisse, wo Du bist
    oder
    holr Dir das Ur-Bild zurück.
    ====
    Hast Du Dir mal die Geschwindigkeiten beider Codes angesehen :?:
    Danach erst solltest Du weitermachen.
    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!

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

    @Otti

    Jetzt zu Deinen Fragen: Der Parameter pixel gibt an um wieviel Pixel pro Timer_Tick das Bild gescrollt werden soll. Wenn Du eine Beschleunigung erreichen möchtest, dann musst Du pro Timer_Tick den Wert für den Parameter pixel vergrößern bzw dann wieder verkleinern um so etwas wie ein Bremsen zu erreichen. Da nimmst am besten einen Single für und addierst oder subtrahierst einen kleinen Wert damit nicht zu schnell Beschleunigt oder abbremst. Den Single per CInt an pixel übergeben.

    Zum stoppen bei einem bestimmten Feld: Dir ist ja die Höhe eines Feldes bekannt. Sagen wir als Bsp 50 Pixel. Wenn der Timer also 50 mal das Event feuert und Du pixel = 1 verwendest, dann ist das ganze um 1 Feld gescrollt. Ist eigentlich eine einfache Rechenaufgabe. Sofern der Timer Interval gleich bleibt, brauchst also nur zählen um wieviel Pixel das Bild gescrollt wurde und kannst entsprechend den Timer stoppen.

    Speedtest: Trommelwirbel und Fanfare, der Pokal geht an RodFromGermany. Sein Code ist natürlich schneller. Auf meinem PC ca. 2ms bei einem 500x375 großem Bild. :) Aber darum geht es gar nicht.
    Mfg -Franky-
    Hey...

    Habe leider immer noch das Problem das ich nicht klar komme bzgl der aktuellen abfrage der Position des Bildes.
    Nutze aktuell den Code von -Franky-.
    Hatte mir parallel zum vorhanden Timer einen Zähle eingebaut, allerdings läuft dieser unabhängig vom eigentlichen Code.
    Folge ist das, sofern das Bild nicht huntertprozentig ist, sich nach mehrfachem scrollen das Bild trotzdessen verschiebt.
    Nun zu meiner Frage: Wie kann ich aus dem Code von -Franky- die Position ermitteln?

    Ich denke nicht das dies so funktioniert.

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

    @Otti

    Vllt hilft Dir das hier weiter. Bei meinem Bild ist jedes Feld genau 50 Pixel hoch. Mit einer kleinen Änderung im Originalcode, kannst Du das testen ob sich das Bild nach mehrfachem scrollen verschiebt. Achso, die Const pixel sollte einen bestimmten Wert haben. 50 * 6 = 300 / pixel = ganze Zahl.

    VB.NET-Quellcode

    1. Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    2. Static counter As Integer
    3. Const pixel As Integer = 15
    4. Me.PictureBox1.Image = Form1.ScrollUpOrDown(Me.MyBmp, pixel)
    5. counter += pixel
    6. ' jedes Feld ist 50 Pixel hoch
    7. ' es soll um 6 Felder gescrollt werden
    8. If counter >= 50 * 6 Then
    9. Timer1.Enabled = False
    10. counter = 0
    11. End If
    12. End Sub
    Bilder
    • test.png

      2,79 kB, 150×400, 149 mal angesehen
    Mfg -Franky-

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „-Franky-“ ()

    @-Franky-
    Guten morgen...

    Ja danke dafür, hatte es nicht ganz genau so wie du mit dem Code.
    Habe allerdings meinen Fehler gefunden.
    Beim zusammen setzen meiner Bilder in Folge, waren zwei Bilder nicht ganz etwas höher, daher kam der Versatz.

    Habe allerdings noch eine Frage.
    Da dies ein Spiel für unsere Kleingarten Anlage werden, welches über mehrere Bildschirme läuft, wollte ich nochmal fragen ob ich dies auch mit meherern Pictureboxen machen kann,
    ohne den Code mehrfach zu kopieren....
    @Otti

    Otti schrieb:

    welches über mehrere Bildschirme läuft, wollte ich nochmal fragen ob ich dies auch mit meherern Pictureboxen machen kann, ohne den Code mehrfach zu kopieren....

    Werden die Bildschirme gespiegelt oder erweitert? Ansonsten brauchst doch nur im Timer_Tick weitere Pictureboxen mit jeweils einem anderen Bild ansprechen.

    VB.NET-Quellcode

    1. Me.PictureBox1.Image = Form1.ScrollUpOrDown(Bild1, pixel)
    2. Me.PictureBox2.Image = Form1.ScrollUpOrDown(Bild2, pixel)
    3. Me.PictureBox3.Image = Form1.ScrollUpOrDown(Bild3, pixel)
    4. ' usw
    Mfg -Franky-