0

Given an image, I want to convert its pixels nearby a specified color, like Color.FromArgb(210, 189, 51), to transparent area.

I tried this:

public Bitmap MakeTransparent(Image image,Color clr)
{
    Bitmap b = new Bitmap(image);

    var replacementColour = Color.FromArgb(255, 255, 255);
    var tolerance = 1;

    for (int i = b.Size.Width - 1; i >= 0; i--)
    {
        for (int j = b.Size.Height - 1; j >= 0; j--)
        {
            var col = b.GetPixel(i, j);

            if (clr.R - col.R < tolerance &&
                clr.G - col.G < tolerance &&
                clr.B - col.B < tolerance)
            {
                b.SetPixel(i, j, replacementColour);
            }
        }
    }

    b.MakeTransparent(replacementColour);

    return b;
}

But the result is wrong.

Orace
  • 6,774
  • 25
  • 42
Merbin Joe
  • 592
  • 3
  • 24

1 Answers1

1

You should learn about metrics.

Anyway, if bad colors are converted it's obviously due to your test:

if (clr.R - col.R < tolerance && clr.G - col.G < tolerance && clr.B - col.B < tolerance)

If clr is say (100,100,100) (light gray) any color with RGB less than 99 will pass the test. Like (75,57,37) (dark shitty brown)...

You may use Math.Abs:

if (Math.Abs(clr.R - col.R) < tolerance &&
    Math.Abs(clr.G - col.G) < tolerance &&
    Math.Abs(clr.B - col.B) < tolerance)

As a remark, if tolerance is 1 you check for Math.Abs(d) < 1 which is equivalent to d == 0. So if tolerance is 1, you actually check for color equality.

You may use:

if (Math.Abs(clr.R - col.R) <= tolerance &&
    Math.Abs(clr.G - col.G) <= tolerance &&
    Math.Abs(clr.B - col.B) <= tolerance)

In this case, you check for color equality when tolerance is equal to 0.

Also, you should directly set the matching pixels to transparent instead of set it to white and use your previous function:

var replacementColour = Color.Transparent;

...  // for loops

if (Math.Abs(clr.R - col.R) < tolerance &&
    Math.Abs(clr.G - col.G) < tolerance &&
    Math.Abs(clr.B - col.B) < tolerance)
{
    b.SetPixel(i, j, replacementColour);
}

Doing this may not be the good way, as color distances is a big subject. You should learn about that:

Community
  • 1
  • 1
Orace
  • 6,774
  • 25
  • 42