IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

VB.NET Discussion :

Rapidité graphique, DrawImage ou DrawString ?


Sujet :

VB.NET

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 12
    Par défaut Rapidité graphique, DrawImage ou DrawString ?
    Bonjour, je suis en train de réaliser une application graphique en VB.NET sur PDA (WM5) qui doit tourner rapidement (25hz pour le rafraichissement). Je dois afficher quelques cercles et quelques traits, ainsi que du texte dans une police spécifique.
    Mon problème est que lorsque je me contente d'afficher des traits et des cercles, je respecte largement la fréquence de rafraichissement à 25hz, mais dès que je fait du drawstring, je tombe à 15hz ...
    Ma question est la suivante : si je crée une image pour chaque caractère de la police (principalement des chiffres), serait il plus rapide d'afficher ces images via drawimage plutot que d'utiliser drawstring ? Ou existe t'il une autre solution plus rapide ?
    D'avance merci de votre aide !

  2. #2
    Membre Expert
    Avatar de olsimare
    Inscrit en
    Décembre 2006
    Messages
    1 184
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 1 184
    Par défaut
    Bonjour.

    Essayes d'abord de passer par un buffer --> tu créés une bitmap, tu créés un graphics à partir de cette image et tu dessines dans le graphics.
    Ensuite, dans le graphics correspondant à ton composant, tu fais un drawimage du bitmap.

    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     
    Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
     
            Dim ibufferImage As Bitmap = New Bitmap(Me.Bounds.Width, Me.Bounds.Height)
            Dim gd As Graphics = Graphics.FromImage(ibufferImage)
            gd.SmoothingMode = Drawing2D.SmoothingMode.HighQuality
            gd.TextRenderingHint = Drawing.Text.TextRenderingHint.AntiAliasGridFit '.AntiAlias '.ClearTypeGridFit '.AntiAlias
            '
            ' Background du parent
            '
            MyBase.OnPaintBackground(New PaintEventArgs(gd, Me.Bounds))
     
            gd.DrawString(Text, Font, Brushes.White, New Point(0, 0))
     
            e.Graphics.DrawImage(ibufferImage, 0, 0)
     
            gd.Dispose()
     
        End Sub
     
        Protected Overrides Sub OnPaintBackground(ByVal pevent As System.Windows.Forms.PaintEventArgs)
            'MyBase.OnPaintBackground(pevent)
        End Sub
    Aprés en jouant sur la qualité du rendu SmoothingMode et TextRenderingHint, il y moyen de grapiller un peu...

    PS : le code ci-dessus n'est pas optimisé, dans l'idéal il ne faudrait pas reconstituer la bitmap à chaque fois...

    Cdt.

  3. #3
    Membre habitué
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 12
    Par défaut
    Merci de ta réponse olsimare.
    Comme je travaille avec compact framework, le "SmoothingMode" et le "TextRenderingHint" ne sont pas compris ... Et je n'ai pas d'évènement "onpaint" ...
    Par contre, pour ce qui est de l'optimisation, je ne recrée pas le bitmap à chaque fois.
    Voici un bout de mon code, ce sera plus clair :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     
    Public Class Form1
        Dim objBitMap
     
        Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
            objBitMap = New Bitmap(Pic_Temp.Image) 'je crée un bitmap une seule fois au démarrage à partir d'une image contenue dans un picturebox
        End Sub
     
        Private Sub Tmr_General_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Tmr_General.Tick
            Dim objGraphics As Graphics
            Dim MaFont As Font
            Dim MaBrush As Brush
            objGraphics = Graphics.FromImage(objBitMap)
            objGraphics.Clear(Color.Black)
            objGraphics.DrawImage(Pic_Temp.Image, 0, 0) 'pic_temp est une picturebox contenant une image utilisée pour le fond
            MaFont = New Font("DS-Digital", 75, FontStyle.Italic)
            MaBrush = New SolidBrush(Color.LimeGreen)
            objGraphics.DrawString("toto", MaFont, MaBrush, 0, 0)
            Me.Pic_Tdb.Image = objBitMap 'je met objbitmap comme image dans ma picturebox de destination
            objGraphics.Dispose()
            objGraphics = Nothing
        End Sub
    End Class
    C'est très schématisé, j'affiche un tas de données en réalité.
    Peut être je m'y prend mal ?
    Une autre piste pourrait etre Direct Draw (les fonctions DirectX sont prise en compte dans le compact framework), mais ça devient nettement plus complexe.
    Qu'en pensez vous ?

  4. #4
    Membre Expert
    Avatar de olsimare
    Inscrit en
    Décembre 2006
    Messages
    1 184
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 1 184
    Par défaut
    Re.

    Quand je disais qu'il ne fallait pas recréer le bitmap, je me suis mal exprimé, je sous-entendais de ne pas refaire également le dessin dans la bitmap, c'est à dire de ne redessiner la bitmap qu'en cas de changement de l'une des composantes du dessin.

    Donc dans ce cas, personnellement, je ne passerai pas par une picturebox, c'est inutile. Une class héritée de controls devrait suffire pour du simple affichage.

    Un exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
     
    Public Class ccExempleProto111
        Inherits Control
     
        Private WithEvents t As New Timer
        Private bBuffer As Bitmap = Nothing
        Private r As Rectangle = Rectangle.Empty
        Private dtStarted As Date = Now
        Public Sub New()
            t.Interval = 1
            If Not System.ComponentModel.LicenseManager.UsageMode = System.ComponentModel.LicenseUsageMode.Designtime Then
                t.Start()
                dtStarted = Now
            End If
        End Sub
        Private ReadOnly Property Buffer() As Bitmap
            Get
                If bBuffer Is Nothing Then
                    ResetBuffer()
                End If
                Return bBuffer
            End Get
        End Property
        Private Sub ResetBuffer()
            If r = Rectangle.Empty Then
                r = New Rectangle(0, 0, Me.ClientRectangle.Width, Me.ClientRectangle.Height)
            End If
            bBuffer = New Bitmap(Me.ClientRectangle.Width, Me.ClientRectangle.Height)
            Dim gd As Graphics = Graphics.FromImage(bBuffer)
     
            Dim MaFont As Font
            Dim MaBrush As Brush
            MaFont = New Font("DS-Digital", 15, FontStyle.Italic)
            MaBrush = New SolidBrush(Color.LimeGreen)
     
            gd.FillRectangle(New SolidBrush(Me.BackColor), Me.ClientRectangle)
     
            gd.DrawString(intTickCount.ToString, MaFont, MaBrush, New Point(0, 0))
     
            gd.DrawString(dtStarted.ToString, MaFont, MaBrush, New Point(0, 50))
     
            gd.DrawString(Now.ToString, MaFont, MaBrush, New Point(0, 100))
     
            gd.DrawRectangle(Pens.Red, r)
            gd.Dispose()
            Me.Refresh()
        End Sub
        Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
            e.Graphics.DrawImage(Me.Buffer, 0, 0)
        End Sub
        Protected Overrides Sub OnPaintBackground(ByVal pevent As System.Windows.Forms.PaintEventArgs)
            'MyBase.OnPaintBackground(pevent)
        End Sub
        Private intStep As Integer = 1
        Private intTickCount As Integer = 0
        Private Sub t_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles t.Tick
            r.Width -= intStep
            r.Height -= intStep
            intTickCount += 1
            ResetBuffer()
            If r.Width = 1 Or r.Height = 1 _
            Or r.Width = Me.Bounds.Width Or r.Height = Me.Bounds.Width Then
                intStep = -intStep
            End If
        End Sub
    End Class
    Et tu le mets sur une form.

    Conclusion :
    sur un Dual Core à 1,8GoHz de base à 3% de CPU, ça me fait monter à 12% pour 60 Hertz (à peu prés)... (j'ai m'y un interval à 1ms sachant trés bien que le rafraichissement en une ms, fallait pas réver).
    Donc pas génial pour dessiner un rectangle et 3 textes !

    C'est à essayer, mais il ne faut de toute façon pas s'attendre à des performances terrifiantes avec GDI+...

    Cdt.

  5. #5
    Membre habitué
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 12
    Par défaut
    Bonsoir, merci pour ta réponse.
    Au risque de paraître un peu ... débutant, tu le places comment ton code dans la form ?
    Lorsque je crée le projet avec une form form1.vb, le code qui se crée c'est ça :
    Public Class Form1
    End Class

    J'ai essayé de le mettre à la suite, mais ça me génère une erreur : Handle de liaison non valide

    Merci de ton aide !

  6. #6
    Membre habitué
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 12
    Par défaut
    erreur de ma part, c'était un problème de service désactivé nécessaire pour le débogage ... oups
    Par contre je ne sais pas ou mettre ton code. Alors j'ai essayé autre chose :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
     
    Public Class Form1
     
        Private bBuffer As Bitmap = Nothing
        Private r As Rectangle = Rectangle.Empty
        Private dtStarted As Date = Now
        Private intStep As Integer = 1
        Private intTickCount As Integer = 0
     
        Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
            Label1.Text = "toto"
        End Sub
     
        Private ReadOnly Property Buffer() As Bitmap
            Get
                If bBuffer Is Nothing Then
                    ResetBuffer()
                End If
                Return bBuffer
            End Get
        End Property
     
        Private Sub ResetBuffer()
            If r = Rectangle.Empty Then
                r = New Rectangle(0, 0, Me.ClientRectangle.Width, Me.ClientRectangle.Height)
            End If
            bBuffer = New Bitmap(Me.ClientRectangle.Width, Me.ClientRectangle.Height)
            Dim gd As Graphics = Graphics.FromImage(bBuffer)
     
            Dim MaFont As Font
            Dim MaBrush As Brush
            MaFont = New Font("DS-Digital", 15, FontStyle.Italic)
            MaBrush = New SolidBrush(Color.LimeGreen)
     
            gd.FillRectangle(New SolidBrush(Me.BackColor), Me.ClientRectangle)
     
            gd.DrawString(intTickCount.ToString, MaFont, MaBrush, New Point(0, 0))
     
            gd.DrawString(dtStarted.ToString, MaFont, MaBrush, New Point(0, 50))
     
            gd.DrawString(Now.ToString, MaFont, MaBrush, New Point(0, 100))
     
            gd.DrawRectangle(Pens.Red, r)
            gd.Dispose()
            Me.Refresh()
        End Sub
     
        Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
            e.Graphics.DrawImage(Me.Buffer, 0, 0)
        End Sub
     
        Protected Overrides Sub OnPaintBackground(ByVal pevent As System.Windows.Forms.PaintEventArgs)
            'MyBase.OnPaintBackground(pevent)
        End Sub
     
        Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
            r.Width -= intStep
            r.Height -= intStep
            intTickCount += 1
            ResetBuffer()
            If r.Width = 1 Or r.Height = 1 _
            Or r.Width = Me.Bounds.Width Or r.Height = Me.Bounds.Width Then
                intStep = -intStep
            End If
     
        End Sub
    End Class
    De cette façon ça marche, mais je ne sais pas si ça revient au même que ta façon ... ?

Discussions similaires

  1. [Débutant] cumuler e.graphics.drawstring et e.graphics.drawimage
    Par jlp13012 dans le forum VB.NET
    Réponses: 4
    Dernier message: 15/07/2014, 11h33
  2. Formalisation graphique des algorithmes
    Par David R. dans le forum Algorithmes et structures de données
    Réponses: 14
    Dernier message: 08/12/2012, 10h21
  3. De la rapidité du code
    Par jfloviou dans le forum Contribuez
    Réponses: 233
    Dernier message: 29/05/2009, 02h17
  4. Réponses: 2
    Dernier message: 16/04/2007, 14h17
  5. Réponses: 10
    Dernier message: 27/08/2002, 23h24

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo