I think I found a bug when trying to compare Color Structs

While trying to change the color of individual pixels from red to blue, I noticed an inconsistency when trying to check if a color was equal to another.

Using some help from these posts:

https://answers.unity.com/questions/1083182/rgb-colors-as-float-values-converter.html

I Managed to get this code working but it has some problems.

     private static readonly Color[] RedFilter = { new Color(0.643f, 0, 0), new Color(0.486f, 0, 0), new Color(0.360f, 0.015f, 0), new Color(0.266f, 0.015f, 0) };

    /// <summary>
    /// Copies a sprite's texture and changes it's color
    /// </summary>
    public static Texture2D CopyTexture2D(Sprite sprite, PlayerColor color)
    {
        Color RGBColor(float r, float g, float b)
        {
            if (r > 255)
                r = 255f;

            if (g > 255)
                g = 255f;

            if (b > 255)
                b = 255f;

            r /= 255f;
            g /= 255f;
            b /= 255f;

            return new Color(r, g, b);
        }

        //Create a new Texture2D, which will be the copy.
        Texture2D copiedTexture = new Texture2D(46, 38);
        copiedTexture.filterMode = FilterMode.Point;
        copiedTexture.wrapMode = TextureWrapMode.Clamp;
        // Get spritesheet texture
        Color[] pixelColors = sprite.texture.GetPixels((int)sprite.textureRect.x, (int)sprite.textureRect.y, 46, 38); 
        for (int i = 0; i < pixelColors.Length; i++)
        {
            if (pixelColors[i] == RGBColor(124, 0, 0))
                Debug.Log("This is always true: " + pixelColors[i] + " == " + RGBColor(124, 0, 0));

            switch (color)
            {
                case PlayerColor.Blue:
                    if (pixelColors[i].Equals(RGBColor(164, 0, 0)))
                        pixelColors[i] = RGBColor(0, 60, 192);
                    // --- Bug From here ---
                    else if (pixelColors[i].Equals(RGBColor(124, 0, 0)))
                        pixelColors[i] = RGBColor(0, 36, 148);
                    else if (pixelColors[i].Equals(new Color(0.486f, 0, 0)))
                        pixelColors[i] = RGBColor(0, 36, 148);
                    else if (pixelColors[i] == (new Color(0.486f, 0, 0)))
                        pixelColors[i] = RGBColor(0, 36, 148);
                    else if (pixelColors[i] == RedFilter[1])
                        pixelColors[i] = RGBColor(0, 36, 148);
                    else if (pixelColors[i].Equals(RedFilter[1]))
                        pixelColors[i] = RGBColor(0, 36, 148);
                    // --- To here ---

                    // This one works but commented out to show the problem.
                    //else if (pixelColors[i] == RGBAColor(124, 0, 0))
                    //pixelColors[i] = RGBAColor(0, 36, 148);
                    else if (pixelColors[i].Equals(RGBColor(92, 4, 0)))
                        pixelColors[i] = RGBColor(0, 20, 108);
                    else if (pixelColors[i].Equals(RGBColor(68, 4, 0)))
                        pixelColors[i] = RGBColor(0, 4, 76);
                    break;
            }
            copiedTexture.SetPixels(pixelColors);
        }

        copiedTexture.SetPixels(pixelColors);

        copiedTexture.Apply();
        
        return copiedTexture;
    }

When trying to condition the color (124, 0, 0) or (0.486f, 0, 0), the condition gets ingnored despite being the same color, giving the result of the attached image.


Also I attached a unity project showing this issue

Honestly I don’t know if I should be posting this or even if the problem is caused by a bad coding practice, but I feel like it should work independently of the way the comparison is being made.

7572787–937933–Color bug.zip (397 KB)

Never compare floating point values for equality. Here’s why:

https://starmanta.gitbooks.io/unitytipsredux/content/floating-point.html

Since Color is (float,float,float,float) and Color32 is (int,int,int,int) and since we know they map between each other with a free cast, we must treat them all as floating point.

2 Likes

If you want to do pixel-wise color comparisons, it is better to use GetPixels32, and use Color32 for all of your colors and comparisons. Then you’re operating with integers on all sides and there’s no need to deal with floating point comparisons.

1 Like

Thank you for your responses. I suspected I was at fault for the error but since the other comparisons were working I kinda got thrown off to think that maybe it was something else happening.

I’ll try to remove the bug tag and add a help tag on this post