6 votes

Comment puis-je remplir une partie de l'image avec de la couleur ?

J'ai une image que j'ajoute dans mon formulaire, comment puis-je remplir une partie de l'image ?

J'ai ceci

I have this

Ce que j'essaie d'obtenir :

What i want have

9voto

TaW Points 5477

A décharge d'inondation une zone où vous avez besoin d'une routine de décharge alimentaire et de très peu d'autres choses.

Voir cet exemple :

enter image description here

Il utilise deux boîtes à images, ainsi qu'une étiquette pour afficher la couleur choisie.

Et deux événements de clic de souris, un pour choisir la couleur :

private void pictureBoxPalette_MouseClick(object sender, MouseEventArgs e)
{
    Point sPt = scaledPoint(pictureBoxPalette, e.Location);
    lbl_color.BackColor = ((Bitmap)pictureBoxPalette.Image).GetPixel(sPt.X, sPt.Y);
}

et un pour faire le plein :

private void pictureBoxTgt_MouseClick(object sender, MouseEventArgs e)
{
    Point sPt = scaledPoint(pictureBoxTgt, e.Location);
    Bitmap bmp = (Bitmap)pictureBoxTgt.Image;
    Color c0 = bmp.GetPixel(sPt.X, sPt.Y); 
    Fill4(bmp, sPt, c0, lbl_color.BackColor);
    pictureBoxTgt.Image = bmp;
}

La routine Floodfill est tirée de ce poste il s'agit essentiellement d'une mise en œuvre directe d'une wikipedia l'algorithme.. :

static void Fill4(Bitmap bmp, Point pt, Color c0, Color c1)
{
    Color cx = bmp.GetPixel(pt.X, pt.Y);
    if (cx.GetBrightness() < 0.01f) return;  // optional, to prevent filling a black grid
    Rectangle bmpRect = new Rectangle(Point.Empty, bmp.Size);
    Stack<Point> stack = new Stack<Point>();
    int x0 = pt.X;
    int y0 = pt.Y;

    stack.Push(new Point(x0, y0) );
    while (stack.Any() )
    {
        Point p = stack.Pop();
        if (!bmpRect.Contains(p)) continue;
        cx = bmp.GetPixel(p.X, p.Y);
        if (cx == c0)
        {
            bmp.SetPixel(p.X, p.Y, c1);
            stack.Push(new Point(p.X, p.Y + 1));
            stack.Push(new Point(p.X, p.Y - 1));
            stack.Push(new Point(p.X + 1, p.Y));
            stack.Push(new Point(p.X - 1, p.Y));
        }
    }
}

Mise à jour

J'ai mis à jour le code pour inclure une fonction qui mettra à l'échelle l'emplacement d'un clic de souris en un point de pixel d'image ; maintenant cela fonctionnera avec SizeMode=StretchImage ainsi, vous pouvez travailler sur l'image entière

static Point scaledPoint(PictureBox pb, Point pt)
{
    float scaleX = 1f * pb.Image.Width / pb.ClientSize.Width;
    float scaleY = 1f * pb.Image.Height / pb.ClientSize.Height;
    return  new Point((int)(pt.X * scaleX), (int)(pt.Y * scaleY));
}

Bien sûr, vous pouvez ensuite enregistrer l'image.

Notez que votre image originale est de 4bpp et doit être convertie en 24bpp ou mieux avant d'être colorée

Notez également que pour SizeMode=Zoom les calculs sont un peu plus complexes. Voici un exemple qui devrait fonctionner avec n'importe quel SizeMode . :

static Point scaledPoint(PictureBox pbox, Point pt)
{
    Size si = pbox.Image.Size;
    Size sp = pbox.ClientSize;
    int left = 0;
    int top = 0;

    if (pbox.SizeMode == PictureBoxSizeMode.Normal ||
        pbox.SizeMode == PictureBoxSizeMode.AutoSize) return pt;
    if (pbox.SizeMode == PictureBoxSizeMode.CenterImage)
    {
        left = (sp.Width - si.Width) / 2;
        top = (sp.Height - si.Height) / 2;
        return new Point(pt.X - left, pt.Y - top);
    }                   
    if (pbox.SizeMode == PictureBoxSizeMode.Zoom)
    {
        if (1f * si.Width / si.Height < 1f * sp.Width / sp.Height)
            left = (sp.Width - si.Width * sp.Height / si.Height) / 2;
        else
            top = (sp.Height - si.Height * sp.Width / si.Width) / 2;
    }

    pt = new Point(pt.X  - left, pt.Y - top);
    float scaleX = 1f * pbox.Image.Width / (pbox.ClientSize.Width - 2 * left) ;
    float scaleY = 1f * pbox.Image.Height / (pbox.ClientSize.Height - 2 * top);
    return new Point((int)(pt.X * scaleX), (int)(pt.Y * scaleY));
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X