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

C# Discussion :

Creation de layers sur image


Sujet :

C#

  1. #21
    Membre expérimenté
    Profil pro
    Mangeur de gauffre
    Inscrit en
    Octobre 2007
    Messages
    4 413
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Mangeur de gauffre

    Informations forums :
    Inscription : Octobre 2007
    Messages : 4 413
    Par défaut
    Merci Sperot

    Bon... j'ai deja repris et compilé l'exemple de MSDN
    Bonne nouvelle ca marche
    Reste maintenant a dériver tout ca dans le contexte qui m'intéresse

    Je résume :

    J'ai un resultat et je vois quelque chose (bonne nouvelle)
    Je sais pas vraiment ou je suis ??
    Je ne sais pas encore vers ou je dois aller ??
    Mais je sais ou je veux arriver (autre bonne nouvelle)

    Donc je dois resoudre une equation a deux bonnes nouvelles et deux inconnues !

    On va y arriver mais si tu a encore une piste je reste preneur !

  2. #22
    Membre expérimenté
    Profil pro
    Mangeur de gauffre
    Inscrit en
    Octobre 2007
    Messages
    4 413
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Mangeur de gauffre

    Informations forums :
    Inscription : Octobre 2007
    Messages : 4 413
    Par défaut
    Bonjour Sperot51

    J'ai un peu analysé l'exemple de BufferedGraphics et franchement, je n'ai rien compris a ce que ca apporte sinon compliquer les choses
    En plus la methode clear ne peut se faire que par remplissage d'une couleur !
    A ce niveau la le clear d'un CreateGraphics sur un PB est beaucoup plus efficace

    Je pense que je vais me contenter de travailler avec une premiere image constituée dont je ferai des clone a chaque fois que je veux redessiner sur un fond original

    Je n'ai pas compris en quoi ni comment la methode the TheMonz31 ou la tienne pouvait me produire le meme mesultat de maniere performante

    Ma solution serait donc

    1- Je cree un bitmap et j'en fais une Image
    2- Je dessine dessus mon fond
    3- J'en fais un clone
    4- Je cree un Graphics sur le clone
    5- J'ajoute les elements "ephemeres"
    6- A chaque clear, je dispose le clone et je repars au step 4

    Est-ce une "mauvaise" solution ?

  3. #23
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 204
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 204
    Par défaut
    non, ta solution est bonne

    avec des bufferedgraphics, la solution serait :

    de déclarer 2 bufferedgraphics, de les allouer à la taille du PB

    ensuite sur le 1er, tu fais ton drawimage qui fait que t'as qu'une partie de ta grosse image
    tu render le 1er sur le 2eme

    quand tu veux ajouter tes elements ephemeres, tu les rajoutes sur le 2eme

    quand tu veux effacer tes elements ephemeres, tu render le 1er sur le 2eme

    render du 2eme sur picturebox.creategraphics affiche soit l'image, soit l'image plus les elements ephemeres selon ce que tu as fait avant

    render est une instruction très rapide (0,1ms environ), surtout par rapport à des drawimage ou drawline

    les drawimage et drawline sont beaucoup plus rapide sur un bufferedgraphics que sur un graphics d'un control

    si ton picturebox n'a pas de transparence, il faut faire .clear(PB.backcolor)

    si ton picturebox est transparent et que ton image l'utilise, ca se complique par contre, il faut soit la gérer manuellement, soit utiliser l'instruction qu'utilise les controles pour recréer la partie qu'on croit transparente (qui est en fait un redessin de la partie d'en dessous sur le control du dessus)
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  4. #24
    Membre expérimenté
    Profil pro
    Mangeur de gauffre
    Inscrit en
    Octobre 2007
    Messages
    4 413
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Mangeur de gauffre

    Informations forums :
    Inscription : Octobre 2007
    Messages : 4 413
    Par défaut
    Merci Sperot1

    avec des bufferedgraphics, la solution serait :
    de déclarer 2 bufferedgraphics, de les allouer à la taille du PB
    En fait non !

    Car l'image et les elements ephemere doivent se dessiner sur des surfaces identiques utilisant un meme TransFormMatrix (actuellement je fais des drawlines et elipses sur une Image)

    Etape 2
    La visualisation ne prends qu'un morceau de cette (ces) image pour les afficher sur une autre image de la taille de mon PB en utilisant drawimage avec un rectangle source et un rectangle destination permettant de gerer les deplacement est les zoom rapides dans l'image originale

    En final je fais PB.Image=Image

    (peut etre que le PB ne sert pas a grand chose mais il offre la facilité de l'assignation Image=Image)

    Je commence a percevoir que je devrais jouer sur l'etape 2 pour construire l'image a afficher a partir de deux images originales distincte le fond +/- statique et et une surface egale contenant les objets ephemeres

    Je ne vois pas encore bien toute la subtilité du bufferedgraphics et comment bien le mettre en place dans ce contexte mais si ca fait gagner de la performance, je suis toujours preneur !

  5. #25
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 204
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 204
    Par défaut
    si tu t'en sors pas avec le bufferedgraphics, passe moi ton codeque je te le modifie (dans le pire des cas en élagant pour qu'il ne reste que le code graphique)
    parce ca reste un peu flou ce que tu fais malgré les multiples descriptions
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  6. #26
    Membre expérimenté
    Profil pro
    Mangeur de gauffre
    Inscrit en
    Octobre 2007
    Messages
    4 413
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Mangeur de gauffre

    Informations forums :
    Inscription : Octobre 2007
    Messages : 4 413
    Par défaut
    Salut Sperot51

    Voici la source complete

    Les fonctions utiles sont

    DrawRoute : construction de l'image de fond (MapImg)
    MoveImage : creation de l'image a afficher sur le PB


    Je devrais pouvoir dessiner des choses par dessus MapImg en utilisant TransformMatrix mais sans alterer MapImg

  7. #27
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 204
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 204
    Par défaut
    à retirer :
    public Graphics cGraphics = null;
    et mettre à la place :
    private System.Drawing.BufferedGraphics bufferImage = null;
    private System.Drawing.BufferedGraphics bufferImageEtDessin = null;


    il faut allouer les buffer, à la taille des picturebox je pense, meme si tu ne dessines pas en entier dessus

    à retirer :
    cGraphics = Graphics.FromImage(MapImg);
    et mettre à la place :
    bufferImage.Graphics.Clear(PB.Backcolor)
    bufferImage.Graphics.DrawImage(MapImg,0,0)


    une fois que tu as fini l'image de base, tu fais
    bufferImage.Render(bufferImageEtDessin.Graphics)


    il faut aussi sur l'évenement paint du PB mettre
    bufferImageEtDessin.Render


    après j'ai pas suivi ou tu traces tes lignes, ni où tu choisis que tu ne veux plus les voir (je fais du vb à l'origine, pas du c#)

    donc quand tu traces les lignes, tu le fais sur bufferImageEtDessin.Graphics
    et quand tu veux les effacer, tu fais
    bufferImage.Render(bufferImageEtDessin.Graphics)


    et tu n'as plus besoin d'assigner PB.Image avec une image que tu créé, tu ne fais plus que dessiner et afficher le dessin via le buffer
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  8. #28
    Membre expérimenté
    Profil pro
    Mangeur de gauffre
    Inscrit en
    Octobre 2007
    Messages
    4 413
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Mangeur de gauffre

    Informations forums :
    Inscription : Octobre 2007
    Messages : 4 413
    Par défaut
    Merci Sperot51

    Je pense que je commence a comprendre
    Mais je ne suis pas sur que tu a bien suivi mon mecanisme actuel

    1- Dans DrawImage je construit une image d'une taille indépendante du PB disons 2048 x 2048

    2- Exemple de tracage ephemere : la Methode DrawDistPnt qui actuellement recoit une liste de point en dessine directement sur l'image mais qui devrait dessiner sur une AUTRE image

    3- Dans MoveImage je cree un image de la taille du PB a partir d'un morceau de l'image de base

    4- Ensuite j'assigne cette image au PB

    Avec ta methode qui doit remplacer 2 et 3 et 4 il me semble que je pourrais me passer du PB et travailler sur un pannel

  9. #29
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 204
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 204
    Par défaut
    ton image indépendant il faut la garder as image oui

    c'est pour le reste qu'on peut remplacer par des buffers

    et le PB n'est plus obligatoire, avec un buffer, le rendu se fait sur n'importe quel controle, même sur le form directement si tu veux ...
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  10. #30
    Membre expérimenté
    Profil pro
    Mangeur de gauffre
    Inscrit en
    Octobre 2007
    Messages
    4 413
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Mangeur de gauffre

    Informations forums :
    Inscription : Octobre 2007
    Messages : 4 413
    Par défaut
    Bonsoir Sperot51 et TheMonz

    J'ai plogé dans les exemples de BufferedGraphics et aussi telecharge cett exemple

    http://www.codeproject.com/KB/directx/dxsurfacemgr.aspx

    Ma conclusion est la suivante

    1- C'est vraiment pas tres souple utiliser : il faut définir un bufferedcontext un bufferedgraphics et tout ca me semble asser complexe pour finalemement faire des choses qui devraient etre simples.

    2- Considérant la maniere dont je travaille il me semble que le bufferdgraphics et tout a fait superflu :
    a) je construit une image en backround et un simple graphics permet de faire ca je pense de maniere plus performante

    b) Pour mon probleme de layer je pense que le plus simple c'est de construire une deuxieme image

    c) QUESTION : la ou je suis encore dans les choux c'est que je pense que le PictureBox est inutile mais que je devrais trouver le moyer de d'afficher le clip des images sources sur un pannel et je n'ai toujours pas bien compris comment faire ca. Avec le picturebox c'est evidemment asser simple

    je definis un rectangle dans mon image source
    je definis un rectangle du size de mon Picture Box
    Je fais un drawimage sur une nouvelle image de la taille de mon PB
    J'assigne ensuite cette image a mon PB



    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
          Bitmap bmp = new Bitmap(frameWidth, frameHeight);
          Rectangle destRect = new Rectangle(0, 0, frameWidth, frameHeight);
          Rectangle srcRect = new Rectangle(frameAnchor.X, frameAnchor.Y, srcWidth, srcHeight);
          GraphicsUnit units = GraphicsUnit.Pixel;
          Graphics frameGraphics = Graphics.FromImage(bmp);
          frameGraphics.DrawImage(MapImg, destRect, srcRect, units);
          PB.Image=bmp;
    Si je veux faire un move, j'appelle cette methode en modifiant frameAnchor.X et frameAnchor.Y

    Si je veux faire un Zoom, j'appelle cette methode en modifiant frameAnchor.X et frameAnchor.Y et aussi srcWidth, srcHeight);


    Comment je devrais adapter ce code pour qu'il soit performant et qu'il fonctionne sur un pannel

    Vraiment merci pour votre aide

  11. #31
    Membre expérimenté
    Profil pro
    Mangeur de gauffre
    Inscrit en
    Octobre 2007
    Messages
    4 413
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Mangeur de gauffre

    Informations forums :
    Inscription : Octobre 2007
    Messages : 4 413
    Par défaut N.B.
    Maintenant, je suis toujours disposé a considerer qu'un bufferedgraphics fera mieux le travail, mais j'aimerais comprendre pourquoi ?

  12. #32
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 204
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 204
    Par défaut
    parce qu'un buffer par définition, c'est un espace mémoire de travail, pendant qu'autre chose est affiché
    donc les calculs sont fait en premier et le rendu est ensuite recopié en une fraction de milliseconde à l'écran
    par contre je vois pas trop ou le bufferedgraphics te bloques
    ce n'est qu'un graphics avec une sub "render" en plus (et une allocation nécessaire certes)
    et y a pas besoin d'instancier un context, y en a un shared qui traine
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  13. #33
    Membre expérimenté
    Profil pro
    Mangeur de gauffre
    Inscrit en
    Octobre 2007
    Messages
    4 413
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Mangeur de gauffre

    Informations forums :
    Inscription : Octobre 2007
    Messages : 4 413
    Par défaut
    Salut Sperot51

    Je comprends ce que tu dis pour surface de travail
    Mais a partir du moment ou je dessine sur une image et non pas directement sur l'ecran, ma surface de travail est déja toute faite non ?

    Ce que je ne comprends pas bien c'est comment transferer cette image (ou une portion sur un pannel et pas un picturebox ?)

    Et si je voulais jouer a l'idiot je dirais que j'ai lu l'exemple de MSDN sur les bufferedgraphics (source jointe) et que j'ai rien compris et que d'autre part le bufferedcontext semble nécessaire dixit exemple.
    Mais de maniere plus pragmatique je n'ai pas l'impression que tout ceux qui fond du graphics emploient cette usine a gaz ?

  14. #34
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 204
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 204
    Par défaut
    vu que tu travailles sur un graphics non lié (qui lui travailles sur l'image) oui ca va plus vite que de travailler sur un graphics lié à un controle

    pour le contexte :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    buffer = BufferedGraphicsManager.Current.Allocate()
    donc pas besoin d'avoir à instancier un contexte

    donc si j'ai bien compris (tu dois te dire que je suis lent à comprendre, mais en fait moi je fais du vb et j'ai toujours un peu de mal à lire du c#)
    tu créé une image via un graphics, et tu mets cette image dans PB.image

    pour un panel, tu pourrais aussi mettre dans panel.backgroundimage

    de toute facon que t'utilises l'un ou l'autre, ca ne change rien niveau perf, tous les controles se ressemblent ...
    tu pourrais meme créer un nouveau controle hérité de control


    voici en vb l'utilisation classique d'un buffer (avec pb as picturebox)


    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
       Private buffer As BufferedGraphics
     
     
     
        Private Sub PB_SizeChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles PB.SizeChanged
            buffer = BufferedGraphicsManager.Current.Allocate(PB.CreateGraphics, PB.ClientRectangle)
            dessine_buffer()
        End Sub
     
        Private Sub dessine_buffer()
            buffer.Graphics.Clear(PB.BackColor)
            buffer.Graphics.DrawImage()
            buffer.Graphics.DrawLine()
            buffer.Render
        End Sub
     
     
        Private Sub PB_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PB.Paint
            buffer.Render(e.Graphics)
        End Sub
    si le controle sur lequel on utilise le buffer est transparent, ce n'est plus du meme acabit
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  15. #35
    Membre expérimenté
    Profil pro
    Mangeur de gauffre
    Inscrit en
    Octobre 2007
    Messages
    4 413
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Mangeur de gauffre

    Informations forums :
    Inscription : Octobre 2007
    Messages : 4 413
    Par défaut
    Merci Sperot

    Excuse moi d'avoir l'air de poser des questions dans tout les sens (et parfois des tres semblables) mais c'est ma maniere de digerer un sujet

    Or j'ai envie de bien assimiler tout ces concepts

    Pour les PB j'ai souvent entendu dire que ce n'etais pas le controle le plus performant pour le dessin

    Pour ce qui est du BackroundImage, j'ai souvent entendu dire que ce n'etais pas conseillé

    Mais je peux comprende que dessiner une image puis l'assigner au backroundimage demande plus de manipulation que de dessiner directement sur le control

    Or je pense avoir compris que je devrais bypasser cette partie la de mon process

    Je recapitule le principe actuel

    1- Je cree une grande image (bitmap)
    2- Je prends en clip de cette grande image dans une plus petite image en utilisant drawimage avec un rectangle source dans ma grande image un rectangle destination dans ma petite image
    3- Enfin j'assigne cette petite image a mon PB

    Je pense avoir compris que je pouvais rassembler 2 et 3 en dessinant directement sur le fond de mon pannel et en utilisant DoubleBuffer pour eviter le flicker

    Mais je vais compliquer un peu car pour gerer les layers, je pense construire DEUX grandes images et les superposer lors de l'affichage dans le panel

    J'espere bientot pouvoir vraiment maitriser ce sujet et connaitre les avantages et inconvénients de toutes les méthodes possible.

  16. #36
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 204
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 204
    Par défaut
    je ne sais pas si tu connais reflector, ca permet de décompiler du .net
    et le framework est composé en grande partie avec le framework (plus des appels de dll)

    donc on peut voir comment ca se passe derrière tout ca ...
    donc tous les controles héritent de la control, qui gère l'affichage de base (texte, backcolor, backgroundimage, fausse transparence etc...) ensuite les controles hérités rajoutent par dessus leur spécificité

    pour dessiner en .net, il n'y a que graphics, donc le famework aussi utilise ca
    les controles au moment de l'évenemtn paint, font du drawimage, drawstring, et autre

    donc pour le backgroundimage ou image, dans les 2 cas c'est drawimage qui est utilisé, mais pour backgroundimage, il y a possibilité de modifié le rendu (étiré, zoomé, mosaique ...) et c'est des surcharges de drawimage qui font ca
    donc l'un ou l'autre ca change rien


    la propriété doublebuffer des controles est utile dans certains cas, mais seulement si on ne gère pas soi meme l'affichage avec des bufferedgraphics


    si ta méthode fonctionne et que les perfs sont ok, pas besoin de s'embeter plus
    mais il faut savoir que dès qu'on veut pousser un peu les graphisme en .net, il faut utiliser des bufferedgraphics


    avec des buffers, ton traitement serait
    ton image géante tu la gardes dans un System.Drainwg.Image tout le temps
    il te faut un bufferMorceauImage et un bufferTotal (qui aura les traits en plus)

    quand tu veux changere de morceau d'image (ou au début donc)
    tu fais bufferMorceauImage .graphics.clear
    bufferMorceauImage .graphics.drawimage(imageGeante,....) avec la surcharge qui sert à dire que tu veux tel morceau seulement
    bufferMorceauImage.render(bufferTotal.graphics) => le buffer morceau se dessine sur le buffertotal, donc ils sont identiques niveau visuel
    et pour finir buffertotal.render pourqu'on voit à l'écran le dessin

    et quand tu veux dessiner des lignes dessus, tu fais buffertotal.graphics.drawlines et buffertotal.render

    et ne pas oublier sur l'évenement paint du control utilisé (pb panel ou form) de faire buffertotal.render(e.graphics)

    car quand windows dit à la fenetre de se rafraichir, elle appelle les evenements paint sur tous les controles, et affiche le contenu de e.graphics, donc tout ce que tu avait dessiné disparait, en disant au buffer de se peindre sur e.graphics (instantanné aussi), ca fait le rendu que tu veux


    si y reste des questions n'hésite pas ...
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

Discussions similaires

  1. [HTML][débutante] Map ou Onclick sur image ? Différent ?
    Par khany dans le forum Balisage (X)HTML et validation W3C
    Réponses: 4
    Dernier message: 08/12/2004, 15h05
  2. [allegro]passage de pointeur sur image
    Par Gonath dans le forum Autres éditeurs
    Réponses: 3
    Dernier message: 13/12/2003, 19h47
  3. zoom sur image de formulaire
    Par bourvil dans le forum VBA Access
    Réponses: 2
    Dernier message: 01/10/2003, 10h25
  4. Réponses: 17
    Dernier message: 25/03/2003, 14h45
  5. [c++ builder] creation de surface sur TPanel
    Par JEG dans le forum DirectX
    Réponses: 7
    Dernier message: 23/09/2002, 23h41

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