schnellere Graphik

  • VB.NET

Es gibt 9 Antworten in diesem Thema. Der letzte Beitrag () ist von johannes.hagel.

    schnellere Graphik

    Einen schönen guten Abend,

    Ich habe folgendes kleine Problem. Ich schreibe gerade ein Programm zur Darstellung beliebiger Fraktale (z.B. Mandelbrotmenge). Es funktioniert eigentlich sehr gut bis auf einen kleinen Schönheitsfehler. Die Berechnung der Farbwerte eines Integer - Arrays von 500 mal 500 (immerhin 250000 Bildpunkte) geht WESENTLICH schneller als deren graphische Darstellung nachher. Und das finde ich schade. Bei einer Iterationstiefe von 30 braucht mein PC 3s zur Erstellung und gut 20s zur Darstellung. Ich verwende folgende Routine zur Darstellung:

    public a(500,500) as integer

    .
    .
    .

    for i=1 to 500
    for j=1 to 500
    gr.rectangle(new solidbrush(farbe(a(i,j)),i,j,1,1))
    next j
    next i

    Läuft tadellos aber ist schneckenlangsam, wie gesagt gut 20s pro Bild.

    Somit meine Frage. Gibt es in VB2010 eine Möglichkeit zweidimensionale Arrays blitzschnell auf den Bildschirm zu bekommen? Wenn ich mir ansehe, wie schnell manche Spielegraphik ist, müsste es ja eigentlich gehen. Vielleicht kennt ja jemand eine (einfach zu programmierende!) Methode?

    Mit bestem Dank im Voraus,

    Johannes
    yousrs, nimm lockbits und setpixel...

    Das macht sinn. Zwei Verfahren, die sich komplett ausschließen;) Einfach lockbits, und fertig.
    Hi
    da LockBits etwas unhandlich ist, hier mal ein kleines Beispiel:

    VB.NET-Quellcode

    1. Private bmpBitmap As Bitmap
    2. Private Sub CreateBitmap()
    3. 'Bitmap erzeugen (32-Bit-RGB-Bitmap, da diese einfacher per 32-Bit Integer bearbeitet werden koennen)
    4. Dim bmp As New Bitmap(500, 500, Imaging.PixelFormat.Format32bppRgb)
    5. 'Den Inhalt der Bitmap ermitteln
    6. Dim bdata As Imaging.BitmapData = bmp.LockBits(New Rectangle(Point.Empty, bmp.Size), Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat)
    7. Dim arr(bdata.Width * bdata.Height - 1) As Integer 'Puffer fuer Farben erzeugen
    8. Dim width As Integer = bdata.Width 'Breite zwischenspeichern
    9. 'Bitmap per (x,y) fuellen
    10. 'da es ein 1-Dimensionales Array ist, verwende ich einfach y * width + x zum berechnen des Array-Indexes
    11. For y As Integer = 0 To bdata.Height - 1
    12. For x As Integer = 0 To bdata.Width - 1
    13. arr(y * width + x) = ComputeFractal(x, y) 'Fraktal berechnen und den rgb-Wert in das Array geben
    14. Next
    15. Next
    16. 'Inhalt des Arrays in die Bitmaprohdaten kopieren
    17. Runtime.InteropServices.Marshal.Copy(arr, 0, bdata.Scan0, arr.Length)
    18. bmp.UnlockBits(bdata) 'Bitmap wieder freigeben
    19. 'Bitmap zwischenspeichern und später im Paint-Ereignis o.Ä. zeichnen lassen
    20. bmpBitmap = bmp
    21. End Sub

    Statt jeden Pixel einzeln zu zeichnen, zeichnest du jetzt einfach die gesamte Bitmap in einem Rutsch per Graphics.DrawImage oder Graphics.DrawImageUnscaled.

    Gruß
    ~blaze~
    Hallo Blaze,

    Vielen Dank für das Beispielprogramm, ich werde es nun mal probieren. Mit welchem Befehl bekomme ich dann zum Schluß die Bitmap in meine erstellte Picturebox1 von 500 mal 500 Pixe?

    Gruß, Johannes
    Guten Morgen alle,

    Entschuldigt, wenn diese Frage hier zu elementar ist. Wie genau kodiert man RGB Werte von Punkten? Sind das einfach Bytes, also Zahlen zwischen 0 und 255? Also wenn ich zum Beispiel auf dem Arraypunkt A(2,3) die Farbe Color.Green malen möchte, wie errechnet sich dann in VB2010 der dazugehörige RGB Wert :?:

    Grüße Johannes

    PS: bin erst seit kurzem hier. Wie macht ihr es, wenn ihr richtigen Code hier reinkopiert, dass es aussieht wie im VB2010 Editor?
    Hallo Johannes,

    VB Quelltext kannst du hier am besten einfügen, in dem zu im Beitragseditor im Modus Quellcode

    VB.NET-Quellcode

    1. Dein Code

    schreibst.

    Color enthält verschiedene Objekte vom Typ Color. Dieser Typ ist eine Struktur.
    Du kannst nun mit Color.FromARGB(zahl) ein Objekt vom Typ Color aus einem ARGB-Wert (32bit dezimal) erstellen ;)

    Ein ARGB Wert ist im grunde nichts anderes, als alle Zahl aneinander: Alpha:0 Rot: 255 Grün: 255 Blau 0

    in Binär:

    Alpha: 00000000
    Rot: 11111111
    Grün: 11111111
    Blau: 00000000

    Daraus machen wir 00000000111111111111111100000000.
    Wenn wir dass nun mal in Dezimal umrechnen: 16776960

    Machen wir also mal BackgroundColor = Color.FromARGB(16776960)
    aha. gelb ;)


    Gruß,
    Manawyrm

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

    Hallo Tobias,

    Vielen herzlichen Dank für die Nachhilfestunde. :rolleyes: Das war schon mal sehr nützlich zu wissen. :) Nun ist es bei mir so, dass ich am liebsten eine Funktion hätte, die aus einer gewünschten Farbe den Alpha RGB Code macht. Also ich weiß, dass ich zum Beispiel gerne die Farbe Color.DarkRed hätte und will dazu die AlphaRGB Zahl in Binär oder Dezimal haben. Gibt es eine solche Funktion oder muss ich die erst schreiben?

    Grüße Johannes

    bmp erstellt - Darstellung in Picturebox?

    ~blaze~ schrieb:

    Hi
    da LockBits etwas unhandlich ist, hier mal ein kleines Beispiel:

    VB.NET-Quellcode

    1. Private bmpBitmap As Bitmap
    2. Private Sub CreateBitmap()
    3. 'Bitmap erzeugen (32-Bit-RGB-Bitmap, da diese einfacher per 32-Bit Integer bearbeitet werden koennen)
    4. Dim bmp As New Bitmap(500, 500, Imaging.PixelFormat.Format32bppRgb)
    5. 'Den Inhalt der Bitmap ermitteln
    6. Dim bdata As Imaging.BitmapData = bmp.LockBits(New Rectangle(Point.Empty, bmp.Size), Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat)
    7. Dim arr(bdata.Width * bdata.Height - 1) As Integer 'Puffer fuer Farben erzeugen
    8. Dim width As Integer = bdata.Width 'Breite zwischenspeichern
    9. 'Bitmap per (x,y) fuellen
    10. 'da es ein 1-Dimensionales Array ist, verwende ich einfach y * width + x zum berechnen des Array-Indexes
    11. For y As Integer = 0 To bdata.Height - 1
    12. For x As Integer = 0 To bdata.Width - 1
    13. arr(y * width + x) = ComputeFractal(x, y) 'Fraktal berechnen und den rgb-Wert in das Array geben
    14. Next
    15. Next
    16. 'Inhalt des Arrays in die Bitmaprohdaten kopieren
    17. Runtime.InteropServices.Marshal.Copy(arr, 0, bdata.Scan0, arr.Length)
    18. bmp.UnlockBits(bdata) 'Bitmap wieder freigeben
    19. 'Bitmap zwischenspeichern und später im Paint-Ereignis o.Ä. zeichnen lassen
    20. bmpBitmap = bmp
    21. End Sub

    Statt jeden Pixel einzeln zu zeichnen, zeichnest du jetzt einfach die gesamte Bitmap in einem Rutsch per Graphics.DrawImage oder Graphics.DrawImageUnscaled.

    Gruß
    ~blaze~

    Hi Blaze,

    Ich habe Deinen Code zur Erstellung einer bmp in mein Programm implementiert und bin begeistert! Vielen Dank für diesen äußert nützlichen Code! Die Darstellung des Fraktals
    erfolgte einfach mit mit

    Picturebox1.Iimage=bmpBitmap

    Nun ist die Geschwindigkeit des Programmes tatsächlich nur noch durch die Rechenleistung des Prozessors bei der Berechnung des Fraktals begrenzt und nicht mehr durch die Graphik. Sehr schön!!

    Vielen Dank nochmals für diese Informationen! :thumbsup: :thumbsup: :thumbsup:

    Gruß Johannes