tutorials.de Buch-Aktion 02/2012
Like Tree1Danke
  • 1 Beitrag von Spyke
ERLEDIGT
JA
ANTWORTEN
7
ZUGRIFFE
432
EMPFEHLEN
  • An Twitter übertragen
  • An Facebook übertragen
AUF DIESES THEMA
ANTWORTEN
  1. #1
    Tim Bureck Tim Bureck ist offline Mitglied Brokat
    Registriert seit
    Apr 2009
    Ort
    Düsseldorf (NRW)
    Beiträge
    498
    Hallo zusammen,

    ich habe das Problem, dass bei einem eigenen Usercontrol das Zeichnen ab einer gewissen Größe immer länger dauert (ja, irgendwie logisch ). Zugegeben, der Zeichenalgorithmus ist sehr einfach gehalten. Wie könnte ich das optimieren?

    Code csharp:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    
            protected override void OnPaint(PaintEventArgs pe) {
                base.OnPaint(pe);
                Graphics g = pe.Graphics;
     
                if (this.CarView != null) {
                    Color c = NFZColor32.TRANSPARENT.Color;
                    Color transparentMarker = Color.FromArgb(0, 140, 0);
     
                    for (int y = 0; y < this.RealHeight; y++) {
                        for (int x = 0; x < this.RealWidth; x++) {
                            c = ((NFZColor32)this.CarView.Pixels[x / this.ZoomGraphic, y / this.ZoomGraphic]).Color;
     
                            g.FillRectangle(new SolidBrush(c), x * this.OpticalZoom, y * this.OpticalZoom, this.OpticalZoom, this.OpticalZoom);
     
                            if (c == NFZColor32.TRANSPARENT.Color && this.OpticalZoom >= 3) {
                                g.DrawRectangle(
                                    new Pen(transparentMarker),
                                    x * this.OpticalZoom + (this.OpticalZoom / 2 - 1),
                                    y * this.OpticalZoom + (this.OpticalZoom / 2 - 1),
                                    this.OpticalZoom % 2 == 0 ? 2 : 1,
                                    this.OpticalZoom % 2 == 0 ? 2 : 1
                                );
                            }
                        }
                    }
                }
            }

    Bereits bei OpticalZoom 1 und ZoomGraphics 4 (RealHeight = 40; RealWidth = 128) kann man dem Control schön beim Zeichnen zusehen. Was beim OpticalZoom 16 passiert könnt ihr euch dann ausmalen.

    Best regards
    Geändert von Tim Bureck (09.09.10 um 13:17 Uhr) Grund: Titel angepasst
     

  2. #2
    Tim Bureck Tim Bureck ist offline Mitglied Brokat
    Registriert seit
    Apr 2009
    Ort
    Düsseldorf (NRW)
    Beiträge
    498
    Gibt es vielleicht eine alternative Grafikschnittstelle, die ich hier einbauen könnte ohne die ganze GUI neu zu machen? Habe gelesen, dass die Geschwindigkeit von der CPU-Lastigkeit von GDI+ abhängt... aber keinen wirklichen Plan, wie ich das alternativ gestalten könnte.
     

  3. #3
    napstermania napstermania ist offline Mitglied Silber
    Registriert seit
    Jul 2004
    Ort
    Deutschland
    Beiträge
    95
    Hallo,

    mit der GDI+ wird man nie große Zeichnungen und kurzer Zeit erledigen können. Wie du schon gesagt hast berechnet die GDI+ so ziemlich alles über den Prozessor und nicht über die Grafikkarte. Und da der Prozessor idR genug andere Sachen zu tun hat wird das Zeichnen sehr langsam. Ich empfehle dir XNA.
    Das ist ein 3D Grafik Framework, welches auch direkt die Grafikkarte (btw Direct X) zum Zeichnen benutzt. Damit bekommt man sehr schnelle Zeichenroutinen hin.

    Grüsse
     

  4. #4
    Tim Bureck Tim Bureck ist offline Mitglied Brokat
    Registriert seit
    Apr 2009
    Ort
    Düsseldorf (NRW)
    Beiträge
    498
    Das klingt erstmal interessant... Allerdings noch ein Paar Fragen:

    1. Muss der Endbenutzer dieses Framework ebenfalls installieren, wenn ich das in meiner Software verwende?
    2. Könnte ich damit überhaupt mein Windows Forms User Control zeichnen (z.B. jetzt in meiner OnPaint-Methode)?
     

  5. #5
    Avatar von Spyke
    Spyke Spyke ist offline Capoeirista
    Registriert seit
    Oct 2002
    Beiträge
    931
    1. Pen und SolidBrush sind beide IDisposable und sollten dem entsprechend auch wieder freigegeben werden.
    2. Dann würde ich wirklich nur denn sichtbaren Bereich zeichnen lassen (gibt es eine Eigenschaft im Graphics Object, VisibleRectangle glaube)
    3. Du könntest noch versuchen das ganze mit DrawPath zu zeichnen.
    Tim Bureck bedankt sich. 
    www.iv-interactive.de - Projektewebsite
    WikiParser - aktuelles Projekt

  6. #6
    Tim Bureck Tim Bureck ist offline Mitglied Brokat
    Registriert seit
    Apr 2009
    Ort
    Düsseldorf (NRW)
    Beiträge
    498
    So, ich habe meinen Algorithmus noch ein mal ein bisschen überdacht und mir die Tipps hier zu Herzen genommen. Der Teilbereich wurde anscheinend bereits gezeichnet (sieht jedenfalls so aus, wenn man scrollt), dahingehend hab ich also nichts geändert. Allerdings hat etwas ganz banales schon einiges geholfen, hier der Algorithmus:

    Code csharp:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    
            protected override void OnPaint(PaintEventArgs pe) {
                base.OnPaint(pe);
                Graphics g = pe.Graphics;
     
                g.CompositingMode = CompositingMode.SourceCopy;
                g.CompositingQuality = CompositingQuality.HighSpeed;
                g.InterpolationMode = InterpolationMode.NearestNeighbor;
                g.SmoothingMode = SmoothingMode.None;
                g.PixelOffsetMode = PixelOffsetMode.None;
     
                if (this.CarView != null) {
                    Color c = NFZColor32.TRANSPARENT.Color;
                    Color transparentMarker = Color.FromArgb(0, 140, 0);
                    SolidBrush brush = new SolidBrush(c);
                    Pen pen = new Pen(transparentMarker);
                    INFZColor[,] pixels = this.CarView.Pixels;
     
                    g.Clear(c);
     
                    for (int y = 0; y < this.RealHeight; y++) {
                        for (int x = 0; x < this.RealWidth; x++) {
                            c = ((NFZColor32) pixels[x / this.ZoomGraphic, y / this.ZoomGraphic]).Color;
                            brush.Color = c;
     
                            if (c == NFZColor32.TRANSPARENT.Color && this.OpticalZoom >= 3) {
                                g.DrawRectangle(
                                    pen,
                                    x * this.OpticalZoom + 1,
                                    y * this.OpticalZoom + 1,
                                    this.OpticalZoom - 2,
                                    this.OpticalZoom - 2
                                );
                            } else {
                                g.FillRectangle(brush, x * this.OpticalZoom, y * this.OpticalZoom, this.OpticalZoom, this.OpticalZoom);
                            }
                        }
                    }
     
                    brush.Dispose();
                    pen.Dispose();
                }
            }

    Ich habe aus den Schleifen ein paar Dinge rausgezogen, was die Sache schon sehr viel schneller macht. Desweiteren ist die Darstellung von dem hellgrünen Quadrat vereinfacht worden. Vor allem das rausziehen des Array (CarView.Pixels) hat einen enormen Geschwindigkeitsschub gebracht. Mit der jetzigen Lösung kann ich erstmal leben, bis ich mir fortgeschritteneres Wissen (DirectX etc.) angeeignet hab.
     

  7. #7
    Avatar von colblake
    colblake colblake ist offline Mitglied Gold
    Registriert seit
    Jan 2004
    Ort
    dresden
    Beiträge
    214
    Einen Tip noch:

    So wie du das programmiert hast, wird das Bild jedemal neu berechnet, wenn die OnPaint-Methode aufgerufen wird.
    Wenn das nicht willst, zeichne doch auf ein Image (in einer separaten Methode) und stelle dann nur das Image dann in der OnPaint-Methode dar.

    So kannst du die Erstellung des Bildes und den Zeitpunkt der Darstellung trennen.
    Geändert von colblake (29.09.10 um 10:30 Uhr)
     
    Über so viele Sachen wächst Gras , man kann keiner Wiese mehr trauen.

  8. #8
    Tim Bureck Tim Bureck ist offline Mitglied Brokat
    Registriert seit
    Apr 2009
    Ort
    Düsseldorf (NRW)
    Beiträge
    498
    Mittlerweile gibts keinerlei Flackern mehr beim Zeichnen. Die Lösung des Problems war, das Propertiy DoubleBuffered auf true zu setzen. Läuft wie am Schnürchen!

    Code csharp:
    1
    2
    3
    4
    5
    
    public NFZDrawPanel {
      ...
      this.DoubleBuffered = true;
      ...
    }
     

Ähnliche Themen

  1. Geschwindigkeit
    Von bauchinj im Forum PHP
    Antworten: 4
    Letzter Beitrag: 10.02.10, 13:45
  2. Geschwindigkeit
    Von Banditxxy im Forum Flash Plattform
    Antworten: 4
    Letzter Beitrag: 22.12.04, 01:32
  3. Dsl-geschwindigkeit-
    Von MasterLutz im Forum Internet, DSL & Flatrate
    Antworten: 6
    Letzter Beitrag: 17.11.04, 21:35
  4. Geschwindigkeit
    Von UULF im Forum 3D Studio Max
    Antworten: 3
    Letzter Beitrag: 24.09.04, 07:17
  5. geschwindigkeit
    Von koma666 im Forum Relationale Datenbanksysteme
    Antworten: 6
    Letzter Beitrag: 11.07.02, 10:56