Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does this color comparison fail?

Tags:

c#

colors

Why does this assertion fail?

Assert.AreEqual( Color.Red, Color.FromArgb( Color.Red.A, Color.Red.R, Color.Red.G, Color.Red.B ) );
like image 848
Anthony Avatar asked Apr 03 '12 13:04

Anthony


People also ask

How do you compare colors?

The most common method would be a visual color comparison by looking at two physical color samples side by side under a light source. Color is very relative, so you can compare colors in terms of the other color across dimensions such as hue, lightness and saturation (brightness).

How can you tell the difference between two colors?

In order to measure the difference between two colors, the difference is assigned to a distance within the color space. In an equidistant-method color space, the color difference ∆E can be determined from the distance between the color places: ΔE = √ (L*₁-L*₂)² + (a*₁-a*₂)² + (b*₁-b*₂)².

Why do colors look different under different light?

Metamerism occurs when two colors match under one type of lighting but not another. This peculiarity has to do with the relationship between light and color. We perceive color based on the way an object reflects light, and that perception is based on the light source.


2 Answers

Here is how Colors comparison implemented:

public override bool Equals(object obj)
{
    if (obj is Color)
    {
        Color color = (Color) obj;
        if ((this.value == color.value)
            && (this.state == color.state)
            && (this.knownColor == color.knownColor))
        {
            return ((this.name == color.name)
                || ((this.name != null)
                   && (color.name != null)
                   && this.name.Equals(color.name)));
        }
    }
    return false;
}

How it works:

  1. Field value compared. It is Argb values of current instance (they are stored in one field of type long). So, if Argb different, we have different colors. You pass this step successfully.
  2. Field state compared. It shows the way how color was created: from Argb, from KnownColor, or by name. Actually your comparison fails on this step.
  3. Field knownColor compared. It has value of KnownColor enum, or zero, if color was not created from known color.
  4. Field name compared. It has null value for all colors except ones created by name.

So, if you want to compare values of colors, you should use value field in comparison (it is returned by ToArgb method):

Assert.AreEqual(color1.ToArgb(), color2.ToArgb());

Edit

To create copy of some color you can use following extension method:

public static class ColorHelper
{
    public static Color Copy(this Color color)
    {
        if (color.IsKnownColor)
            return Color.FromKnownColor(color.ToKnownColor());

        if (color.IsNamedColor)
            return Color.FromName(color.Name);

        // this is better, then pass A,r,g,b separately
        return Color.FromArgb(color.ToArgb()); 
    }

Now assertion passes:

Assert.AreEqual(Color.Red, Color.Red.Copy());

But it makes no sense, because you can use single color instance in every place of your program :)

like image 189
Sergey Berezovskiy Avatar answered Oct 03 '22 07:10

Sergey Berezovskiy


Color.Red is a named color, while Color.FromArgb(...) is not. So they're not considered equal, even though they have the same ARGB values. Note that the string representation is also different:

Color.Red.ToString()           : "Color [Red]"
Color.FromArgb(...).ToString() : "Color [A=255, R=255, G=0, B=0]"
like image 27
Thomas Levesque Avatar answered Oct 03 '22 08:10

Thomas Levesque