none
Dessin d'axes dans une pictureBox

    Discussion générale

  • Bonjour à tous,

    J'aimerai afficher les axes X et Y dans une pictureBox. J'ai donc le code pour dessiner ces deux axes dans ma pictureBox.
    Dans un petit programme, les deux axes s'affichent très bien mais lorsque j'ai ajouté le code à mon projet l'exception suivante s'est affichée :

    " Une exception non gérée du type 'System.ArgumentException' s'est produite dans PylonLiveView.exe

    Informations supplémentaires : Le paramètre n'est pas valide. "

    Dans le programme de mon projet, je récupère l'image qui est capturée par une caméra. Donc je n'initialise pas une image depuis un répertoire, mais je récupère celle de la pictureBox. Le problème vient peut-être de ça ?

    Petite précision, je programme en C# sous Visual Studio Express 2015.

    J'aimerai avoir quelques avis et quelques conseils donc c'est pour cela que j'ai ouvert un nouveau sujet :)

    Merci d'avance,

    Sebbur

    lundi 4 juillet 2016 08:43

Toutes les réponses

  • Bonjour Sebbur,

    Pouvez-vous montrer le code en question, il se peut que l'image appelle Dispose avant que vous la fournissiez à votre PictureBox, étant donné qu'elle provient d'un WebCam.

    Pour vous guider sur ce que je pense, je vous renvoie ici : Exception: Parameter is not valid (on passing new image to pictureBox)

    Cordialement,

    lundi 4 juillet 2016 09:48
  • Je vous remercie tout d'abord pour votre réponse.

    Voici le code en question : 

    private Rectangle rectImage = Rectangle.Empty;
            private Image bmpAxis = null;
    
            private void DessineSurBmpAxis()
            {
                bmpAxis = new Bitmap(bmpAxis, rectImage.Size);
                using (Graphics grAxis = Graphics.FromImage(bmpAxis))
                {
                    using (Pen penAxe = new Pen(Color.Red, 4.0f))
                    {
                        grAxis.DrawLine(penAxe, 0, bmpAxis.Height - 1024,
                            bmpAxis.Width, bmpAxis.Height - 1024);
                        grAxis.DrawLine(penAxe, 0 + 1024, 0, 0 + 1024, bmpAxis.Height);
                    }
                }
            }
    
            private Image monImage = null;
            private void MainForm_Load(object sender, EventArgs e)
            {
                monImage = pictureBox.Image;
                bmpAxis = new Bitmap(pictureBox.Width, pictureBox.Height);
                rectImage = new Rectangle(0, 0, monImage.Width, monImage.Height);
    
                pictureBox.Invalidate();
            }
    
    private void checkBox3_CheckedChanged(object sender, EventArgs e)
            {
                DessineSurBmpAxis();
                pictureBox.Invalidate();
            }

    Je vais jeter un œil au lien que vous m'avez envoyé.

    Encore merci,

    Sebbur


    • Modifié Sebbur lundi 4 juillet 2016 09:56
    lundi 4 juillet 2016 09:53
  • Bonjour,
    Il me semble que l'erreur est ici, à ce stade bmpAxis n'existe pas encore!

    bmpAxis = new Bitmap(bmpAxis, rectImage.Size);

    bmpAxis = new Bitmap(100,100);

    Cordialement

    Gérard



    lundi 4 juillet 2016 12:01
  • Bonjour,

    Tout d'abord je vous remercie de votre aide et d'avoir pris le temps de répondre.

    J'ai essayé ce que vous m'avez dit, mais l'exception survient à nouveau.
    Elle dit toujours et encore que le paramètre n'est pas valide.

    Merci encore,

    Sebbur 

    lundi 4 juillet 2016 12:07
  • Voici mon exemple

    private void button1_Click(object sender, EventArgs e)
    {
     Graphics l_Grph = pictureBox1.CreateGraphics();
     l_Grph.DrawLine(new Pen(Color.Red), 10, 10, pictureBox1.Width / 2, 10);
     l_Grph.DrawLine(new Pen(Color.Green), 10, 10, 10, pictureBox1.Height/ 2);
    }

    A mon avis, vous n'avez pas besoin d'enregistrer une variable Rectangle,
    Vous devez créer un objet graphics directement depuis le picturebox pour pouvoir dessiner sur l'image.

    Par contre, au chargement vous devez définir l'image de picturebox
    picturebox.Image = new BitMap(imageOriginale, picturebox.size);

    Cordialement
    Gérard

    lundi 4 juillet 2016 12:42
  • J'ai testé tout ça et les axes s'affichent bien comme je le souhaite. En revanche, j'ai deux petits soucis. Tout d'abord quand je décoche la checkBox, les axes ne disparaissent pas et ils restent affichés. J'ai ajouté " if (checkBox3.Checked) " mais le problème persiste. Ensuite lorsque je bouge mon image avec les " ascenseurs ", les axes disparaissent de la pictureBox.

    Merci pour votre aide,

    Sebbur

    lundi 4 juillet 2016 12:51
  • Il faut faire différement, en fait, il faut surcharger la fonction Paint de picturebox1

     private void pictureBox1_Paint(object sender, PaintEventArgs e)
    {            
      if (checkBox1.Checked)
      {
      Graphics l_Grph = pictureBox1.CreateGraphics();
       l_Grph.DrawLine(new Pen(Color.Red), 10, 10, pictureBox1.Width / 2, 10);
       l_Grph.DrawLine(new Pen(Color.Green), 10, 10, 10, pictureBox1.Height / 2);
      }
    }

    private void checkBox1_CheckedChanged(object sender, EventArgs e)
    {
      pictureBox1.Refresh();
    }

    Parfois, il y a des problèmes de rafraichisssement ancrez l'image de chaque coté.

    this.pictureBox1.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;


    • Modifié GP79 lundi 4 juillet 2016 15:11
    lundi 4 juillet 2016 15:10
  • Ca marche très bien merci beaucoup !

    En revanche, sur mon image j'applique un zoom pour faire une remise à l'échelle mais les axes ne suivent pas le zoom.

    private Size Multiplier;
            private Color color = Color.Black;
    
            public void ZoomIn()
            {
                Multiplier = new Size(2, 2);
    
                Image MyImage = pictureBox.Image;
    
                Bitmap MyBitMap = new Bitmap(MyImage, Convert.ToInt32(MyImage.Width * Multiplier.Width),
                Convert.ToInt32(MyImage.Height * Multiplier.Height));
    
                Graphics Graphic = Graphics.FromImage(MyBitMap);
    
                Graphic.InterpolationMode = InterpolationMode.High;
    
                pictureBox.Image = MyBitMap;
    
            }
    
            public void ZoomOut()
            {
                Multiplier = new Size(2, 2);
    
                Image MyImage = pictureBox.Image;
    
                Bitmap MyBitMap = new Bitmap(MyImage, Convert.ToInt32(MyImage.Width / Multiplier.Width),
                Convert.ToInt32(MyImage.Height / Multiplier.Height));
    
                Graphics Graphic = Graphics.FromImage(MyBitMap);
    
                Graphic.InterpolationMode = InterpolationMode.High;
    
                pictureBox.Image = MyBitMap;
            }
    
    
            private void button1_Click(object sender, EventArgs e)
            {
                ZoomIn();
            }
    
            private void button2_Click(object sender, EventArgs e)
            {
                ZoomOut();
            }

    Voici ci-dessus mon code de zoom. Avec ce zoom la photo devient pixélisée si on l'applique trop de fois. Mais lorsque je l'applique les axes ne suivent pas.
    Il faut les redessiner à chaque ZoomIn ou ZoomOut c'est ça ?

    Merci pour votre aide,

    Sebbur

    mardi 5 juillet 2016 06:55
  • Oui tout à fait, après

     pictureBox.Image = MyBitMap;

    normalement il suffit de faire

    pictureBox.refresh();

    qui déclenche l'évènement Paint.

    Pour la pixelisation, en fait, il faudrait repartir à chaque fois de l'original.


    • Modifié GP79 mardi 5 juillet 2016 08:01
    mardi 5 juillet 2016 07:59
  • J'ai essayé en ajoutant " pictureBox.Refresh(); " mais ça a été sans succès. Les deux axes ne suivent pas le zoom.

    Sebbur

    mardi 5 juillet 2016 08:21
  • Oui c'est exact.

    Mais en fait moi je dézoom très souvent étant donné que l'image que je capture est grande et qu'il faut utiliser les " ascenseurs " pour visualiser les autres parties de mon image. Le capteur de ma caméra à une résolution de 2048 px * 2048 px donc je dézoom pour que l'image soit visible entièrement.
    Voici donc mon code ci-dessous.

    if (checkBox3.Checked)
                {
                    Graphics I_Grph = pictureBox.CreateGraphics();
                    I_Grph.DrawLine(new Pen(Color.Red), 1024, 2048, 1024, 0);
                    I_Grph.DrawLine(new Pen(Color.Red), 2048, 1024, 0, 1024);
                }

    Lorsque je dézoom les axes disparaissent et ne suivent pas le zoom que j'effectue sur ma pictureBox.

    Merci de votre aide,

    Sebbur

    mardi 5 juillet 2016 08:58
  • Graphics permet de tracer dans une partie non visible à l'écran.

    Par exemple, tracer l_Grph.DrawLine(new Pen(Color.Red), -10,-10,1000,-10);
    (une ligne horizontale à 10 pixel au dessus du pictureBox)
    ne provoquera pas d'erreur et aucun affichage.

    sur votre formulaire, le pictureBox fait (par exemple) 500 x 400 vous devez toujours tracer les axes

    l_Grph.DrawLine(new Pen(Color.Red), 10,10, pictureBox.Width / 2, 10);

    l_Grph.DrawLine(new Pen(Color.Green), 10,10, 10, pictureBox.Height / 2 );

    Ce sont les coordonnées par rapport au coin haut gauche du picturebox.

    si vous tracer

    l_Grph.DrawLine(new Pen(Color.Red), 1024,2048,1024,0);

    en fait vous tracer en dehors du pictureBox.

    Cordialement

    Gérard

    mardi 5 juillet 2016 09:15
  • Oui c'est ça. Mais dans ma première capture (qui fait donc 2048*2048), on voit bien les axes tracés mais j'aimerai savoir comment je peux faire pour que le dessin des deux axes suivent cette mise à l'échelle lorsque je zoom ou que je dézoom.

    Sebbur

    mardi 5 juillet 2016 09:19
  • En fait c'est ce que vous disiez. Il faut mettre la hauteur et la largeur de la pictureBox divisée par deux pour que les axes soient toujours placés au milieu de la capture.

    Mais le calcul se fera à chaque fois que j'appuie sur les boutons zoom in/out ?

    Merci d'avance,

    Sebbur


    • Modifié Sebbur mardi 5 juillet 2016 09:40
    mardi 5 juillet 2016 09:33
  • Au départ

    image originale 2048 x 2048

    affichage 1000x850

    facteur d'échelle

    int l_Fact =  Convert.ToInt32(850.0 / 2048.0);

    //Tracer des axes

    l_Grph.DrawLine(new Pen(Color.Red), 10,10, 2048 * l_Fact, 10);

    Modification du zoom

    l_Fact *= 2;

    l_Grph.DrawLine(new Pen(Color.Red), 10,10, 2048 * l_Fact, 10);

    Modification du zoom

    l_Fact /= 2;

    l_Grph.DrawLine(new Pen(Color.Red), 10,10, 2048 * l_Fact, 10);

    etc.

    Faut essayer et voir...

    mardi 5 juillet 2016 09:50
  • Mon facteur de zoom est de 2 dans mon code actuel. Donc lorsque je dézoom, la taille de la pictureBox est divisée par deux.
    Voici donc le code de mon zoom :

            private Size Multiplier;
            private Color color = Color.Black;
    
            public void ZoomIn()
            {
                Multiplier = new Size(2, 2);
    
                Image MyImage = pictureBox.Image;
    
                Bitmap MyBitMap = new Bitmap(MyImage, Convert.ToInt32(MyImage.Width * Multiplier.Width),
                Convert.ToInt32(MyImage.Height * Multiplier.Height));
    
                Graphics Graphic = Graphics.FromImage(MyBitMap);
    
                Graphic.InterpolationMode = InterpolationMode.High;
    
                pictureBox.Image = MyBitMap;
    
            }
    
            public void ZoomOut()
            {
                Multiplier = new Size(2, 2);
    
                Image MyImage = pictureBox.Image;
    
                Bitmap MyBitMap = new Bitmap(MyImage, Convert.ToInt32(MyImage.Width / Multiplier.Width),
                Convert.ToInt32(MyImage.Height / Multiplier.Height));
    
                Graphics Graphic = Graphics.FromImage(MyBitMap);
    
                Graphic.InterpolationMode = InterpolationMode.High;
    
                pictureBox.Image = MyBitMap;
                pictureBox.Refresh();
            }
    
    
            private void button1_Click(object sender, EventArgs e)
            {
                ZoomIn(); // permet de zoomer
                pictureBox.Refresh();
            }
    
            private void button2_Click(object sender, EventArgs e)
            {
                ZoomOut(); // permet de dézoomer
                pictureBox.Refresh();
            }

    Et voici le code pour tracer mes axes :

    if (checkBox3.Checked)
                {
                    Graphics I_Grph = pictureBox.CreateGraphics();
                    I_Grph.DrawLine(new Pen(Color.Red), pictureBox.Width/2, 2048, pictureBox.Width /2, 0);
                    I_Grph.DrawLine(new Pen(Color.Red), 2048, pictureBox.Height /2, 0, pictureBox.Height /2);
                }
    Avec ces deux codes, lors de la première capture les axes s'affichent bien, mais lorsque je dézoom, les axes s'affichent mais ils buguent. Quand je clique dans la pictureBox, ils s'affichent momentanément et ils disparaissent.

    Comment je peux faire pour que les axes restent tout le temps affichés ?

    Sebbur

    mardi 5 juillet 2016 10:05
  • 1 - Ils buguent, Ok, mais faut préciser

    2 - Il ne s'affichent qu'une fois. Avez vous le traçage des axes dans l'évènement Paint de la pictureBox?

    Dans mon programme test, moi aussi, les axes ne s'affichent pas lorsque je clique sur la case à cocher.
    J'ai essayer invalidate, pareil.
    Apparement, ni pictureBox.invalidate(), ni pictureBox.Refresh() ne déclenchent l'évènement pictureBox.Paint.

    si j''agrandis ou réduis la fenêtre, ils s'affichent. L'évènement paint est déclenché.

    mardi 5 juillet 2016 10:22
  • En fait ils apparaissent de manière aléatoire lorsque je clique dans la pictureBox. (j'ai également le code pour tracer une ligne dans ma pictureBox et lorsque je la trace les axes apparaissent rapidement mais ils ne restent pas affichés).

    Oui le traçage des axes est dans l'évènement Paint de la pictureBox.

    Quelle est alors la solution qui me permettrait d'afficher les axes lorsque je dézoom ?

    Merci d'avance,

    Sebbur 

    mardi 5 juillet 2016 11:18