ivan
ivan

Reputation: 1205

How to Fill a path excluding certain areas(paths) C# Graphics

Right now im developing a Windows forms C# App, it detects your face with dlib (https://github.com/takuya-takeuchi/DlibDotNet)
It gets the 68 face landmarks with Points

Face landmarks with its points: enter image description here

And so withthis i have made a Graphics Path for the lips, nose, eyes, and eyebrows and a path that goes around all the face, my question is, is it possible to substract the eyes, eyebrows, lips and nose paths from the one that covers all the face to paint all the face "excluding" those areas?

I found this to be possible in xaml:

(https://learn.microsoft.com/en-us/visualstudio/designers/draw-shapes-and-paths?view=vs-2017) enter image description here

So is it possible to do the ExcludeOverlap or the Substract with Graphics paths and a bitmap in C#? And if so how?

(I know it's almost an unspoken rule to post some code but what i just basically did is create a graphics path for each part of the face, and then paint them on a bitmap with Graphics.FillPath())

Upvotes: 1

Views: 1459

Answers (1)

TaW
TaW

Reputation: 54453

is it possible to substract the eyes, eyebrows, lips and nose paths from the one that covers all the face to paint all the face "excluding" those areas?

This is not only possible; in fact this is the default for combining GraphicsPaths: You add smaller, inner paths to a larger outer path and when you fiil it they will be holes.

Not however that this will also happen when you overlay further paths over the 'holes' resulting in positve areas within the holes.

To makes all paths combine additively (Or -ing) you would change the FillMode property to Winding. The Default is `Alternative' which will create holes (Xor -ing the araes.)

To get full control you could use Regions. They can be combined at will with the whole set of set operations. But they will not support antialiasing, so the curves and tilted lines will look rugged.

Example:

enter image description here

private void pictureBox2_Paint(object sender, PaintEventArgs e)
{
    GraphicsPath gp0 = new GraphicsPath();
    GraphicsPath gp1 = new GraphicsPath();
    GraphicsPath gp2 = new GraphicsPath();
    GraphicsPath gp3 = new GraphicsPath();
    GraphicsPath gp4 = new GraphicsPath();

    gp0.AddEllipse(11, 11, 333, 333);
    gp1.AddEllipse(55, 55, 55, 55);
    gp2.AddEllipse(222, 55, 66, 66);
    gp3.AddEllipse(55, 222, 99, 222);
    gp4.AddLine(66, 123, 234, 77);

    using (Pen pen = new Pen(Color.Empty, 12f))
    gp4.Widen(pen);

    gp0.AddPath(gp1, true);
    gp0.AddPath(gp2, true);
    gp0.AddPath(gp3, true);
    gp0.AddPath(gp4, true);

    gp0.FillMode = FillMode.Alternate;
    e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
    e.Graphics.FillPath(Brushes.Goldenrod, gp0);
}

Upvotes: 1

Related Questions