Esempio n. 1
0
        public Color[] GetNearestColors(Color[] originalColors, ColorMatchMode colorMatchMode, float threshold, ColorEntry[] colorOperations, bool enableColorAdjustments, ColorAdjustments colorAdjustments)
        {
            if (originalColors == null)
            {
                return(null);
            }
            int len = originalColors.Length;

            Color[] newColors = new Color[len];
            match.Clear();
            if (colorOperations != null)
            {
                for (int k = 0; k < colorOperations.Length; k++)
                {
                    int r         = (int)(colorOperations[k].color.r * 255);
                    int g         = (int)(colorOperations[k].color.g * 255);
                    int b         = (int)(colorOperations[k].color.b * 255);
                    int colorHash = (r << 16) + (g << 8) + b;
                    if (colorOperations[k].operation == ColorOperation.Preserve)
                    {
                        match[colorHash] = colorOperations[k].color;
                    }
                    else if (colorOperations[k].operation == ColorOperation.Replace)
                    {
                        match[colorHash] = colorOperations[k].replaceColor;
                    }
                }
            }
            Color[] palette = BuildPaletteColors();

            for (int k = 0; k < MAX_THREADS; k++)
            {
                if (matchPool[k] == null)
                {
                    matchPool[k] = new FastHashSet <Color>();
                }
                matchPool[k].Clear();
            }

            int threadCount = Mathf.Clamp(Mathf.CeilToInt((float)len / MAX_THREADS), 1, MAX_THREADS);

            Parallel.For(0, threadCount, index => {
                int start     = len * index / threadCount;
                int end       = (index == threadCount - 1) ? len : len * (index + 1) / threadCount;
                int lastHash  = -1;
                Color nearest = Color.white;
                FastHashSet <Color> thisMatch = matchPool[index];
                for (int k = start; k < end; k++)
                {
                    int r         = (int)(originalColors[k].r * 255);
                    int g         = (int)(originalColors[k].g * 255);
                    int b         = (int)(originalColors[k].b * 255);
                    int colorHash = (r << 16) + (g << 8) + b;
                    if (colorHash != lastHash)
                    {
                        if (!thisMatch.TryGetValue(colorHash, out nearest))
                        {
                            lastHash = colorHash;
                            nearest  = GetNearestColor(palette, originalColors[k], colorMatchMode, threshold, colorOperations, enableColorAdjustments, colorAdjustments);
                            thisMatch.Add(colorHash, nearest);
                        }
                    }
                    nearest.a    = originalColors[k].a;
                    newColors[k] = nearest;
                }
            });

            return(newColors);
        }
Esempio n. 2
0
 public Color[] GetNearestColors(Texture tex, ColorMatchMode colorMatchMode, float threshold, ColorEntry[] colorOperations, bool enableColorAdjustments, ColorAdjustments colorAdjustments)
 {
     if (tex == null || !(tex is Texture2D))
     {
         return(null);
     }
     if (lastTexture == null || tex != lastTexture)
     {
         lastTexture = (Texture2D)tex;
         lastTexture.EnsureTextureIsReadable();
         originalColors = lastTexture.GetPixels();
     }
     return(GetNearestColors(originalColors, colorMatchMode, threshold, colorOperations, enableColorAdjustments, colorAdjustments));
 }
Esempio n. 3
0
 /// <summary>
 /// Returns the nearest color in the palette
 /// </summary>
 public Color GetNearestColor(Color color, ColorMatchMode colorMatchMode, float threshold, ColorEntry[] colorOperations, bool enableColorAdjustments, ColorAdjustments colorAdjustments)
 {
     Color[] palette = BuildPaletteColors();
     return(GetNearestColor(palette, color, colorMatchMode, threshold, colorOperations, enableColorAdjustments, colorAdjustments));
 }
Esempio n. 4
0
        /// <summary>
        /// Returns the nearest color in the palette
        /// </summary>
        public Color GetNearestColor(Color[] palette, Color color, ColorMatchMode colorMatchMode, float threshold, ColorEntry[] colorOperations, bool enableColorAdjustments, ColorAdjustments colorAdjustments)
        {
            if (colorOperations != null && colorOperations.Length > 0)
            {
                HSLColor hsl = ColorConversion.GetHSLFromRGB(color.r, color.g, color.b);

                for (int k = 0; k < colorOperations.Length; k++)
                {
                    switch (colorMatchMode)
                    {
                    case ColorMatchMode.RGB: {
                        float dr = colorOperations[k].color.r < color.r ? color.r - colorOperations[k].color.r : colorOperations[k].color.r - color.r;
                        float dg = colorOperations[k].color.g < color.g ? color.g - colorOperations[k].color.g : colorOperations[k].color.g - color.g;
                        float db = colorOperations[k].color.b < color.b ? color.b - colorOperations[k].color.b : colorOperations[k].color.b - color.b;
                        if (dr <= threshold && dg <= threshold && db <= threshold)
                        {
                            if (colorOperations[k].operation == ColorOperation.Preserve)
                            {
                                return(color);
                            }
                            else if (colorOperations[k].operation == ColorOperation.Replace)
                            {
                                return(colorOperations[k].replaceColor);
                            }
                        }
                    }
                    break;

                    case ColorMatchMode.Red: {
                        float dr = colorOperations[k].color.r < color.r ? color.r - colorOperations[k].color.r : colorOperations[k].color.r - color.r;
                        if (dr <= threshold)
                        {
                            if (colorOperations[k].operation == ColorOperation.Preserve)
                            {
                                return(color);
                            }
                            else if (colorOperations[k].operation == ColorOperation.Replace)
                            {
                                return(colorOperations[k].replaceColor);
                            }
                        }
                    }
                    break;

                    case ColorMatchMode.Green: {
                        float dg = colorOperations[k].color.g < color.g ? color.g - colorOperations[k].color.g : colorOperations[k].color.g - color.g;
                        if (dg <= threshold)
                        {
                            if (colorOperations[k].operation == ColorOperation.Preserve)
                            {
                                return(color);
                            }
                            else if (colorOperations[k].operation == ColorOperation.Replace)
                            {
                                return(colorOperations[k].replaceColor);
                            }
                        }
                    }
                    break;

                    case ColorMatchMode.Blue: {
                        float db = colorOperations[k].color.b < color.b ? color.b - colorOperations[k].color.b : colorOperations[k].color.b - color.b;
                        if (db <= threshold)
                        {
                            if (colorOperations[k].operation == ColorOperation.Preserve)
                            {
                                return(color);
                            }
                            else if (colorOperations[k].operation == ColorOperation.Replace)
                            {
                                return(colorOperations[k].replaceColor);
                            }
                        }
                    }
                    break;

                    case ColorMatchMode.HSL: {
                        HSLColor hslOp = ColorConversion.GetHSLFromRGB(colorOperations[k].color.r, colorOperations[k].color.g, colorOperations[k].color.b);
                        float    dh    = hslOp.h < hsl.h ? hsl.h - hslOp.h : hslOp.h - hsl.h;
                        float    ds    = hslOp.s < hsl.s ? hsl.s - hslOp.s : hslOp.s - hsl.s;
                        float    dl    = hslOp.l < hsl.l ? hsl.l - hslOp.l : hslOp.l - hsl.l;
                        if (dh <= threshold && ds <= threshold && dl <= threshold)
                        {
                            if (colorOperations[k].operation == ColorOperation.Preserve)
                            {
                                return(color);
                            }
                            else if (colorOperations[k].operation == ColorOperation.Replace)
                            {
                                return(colorOperations[k].replaceColor);
                            }
                        }
                    }
                    break;

                    case ColorMatchMode.Hue: {
                        float hue = ColorConversion.GetHue(colorOperations[k].color.r, colorOperations[k].color.g, colorOperations[k].color.b);
                        float dh  = hue < hsl.h ? hsl.h - hue : hue - hsl.h;
                        if (dh <= threshold)
                        {
                            if (colorOperations[k].operation == ColorOperation.Preserve)
                            {
                                return(color);
                            }
                            else if (colorOperations[k].operation == ColorOperation.Replace)
                            {
                                return(colorOperations[k].replaceColor);
                            }
                        }
                    }
                    break;

                    case ColorMatchMode.Saturation: {
                        float sat = ColorConversion.GetSaturation(colorOperations[k].color.r, colorOperations[k].color.g, colorOperations[k].color.b);
                        float ds  = sat < hsl.s ? hsl.s - sat : sat - hsl.s;
                        if (ds <= threshold)
                        {
                            if (colorOperations[k].operation == ColorOperation.Preserve)
                            {
                                return(color);
                            }
                            else if (colorOperations[k].operation == ColorOperation.Replace)
                            {
                                return(colorOperations[k].replaceColor);
                            }
                        }
                    }
                    break;

                    case ColorMatchMode.Lightness: {
                        float l  = ColorConversion.GetLightness(colorOperations[k].color.r, colorOperations[k].color.g, colorOperations[k].color.b);
                        float dl = l < hsl.l ? hsl.l - l : l - hsl.l;
                        if (dl <= threshold)
                        {
                            if (colorOperations[k].operation == ColorOperation.Preserve)
                            {
                                return(color);
                            }
                            else if (colorOperations[k].operation == ColorOperation.Replace)
                            {
                                return(colorOperations[k].replaceColor);
                            }
                        }
                    }
                    break;
                    }
                }
            }

            float md      = float.MaxValue;
            Color nearest = color;

            switch (colorMatchMode)
            {
            case ColorMatchMode.RGB: {
                for (int c = 0; c < palette.Length; c++)
                {
                    float dr = (palette[c].r - color.r) * 0.299f;
                    float dg = (palette[c].g - color.g) * 0.587f;
                    float db = (palette[c].b - color.b) * 0.114f;
                    float d  = dr * dr + dg * dg + db * db;
                    if (d < md)
                    {
                        md      = d;
                        nearest = palette[c];
                    }
                }
            }
            break;

            case ColorMatchMode.Red: {
                for (int c = 0; c < palette.Length; c++)
                {
                    float dr = palette[c].r - color.r;
                    float d  = dr * dr;
                    if (d < md)
                    {
                        md      = d;
                        nearest = palette[c];
                    }
                }
            }
            break;

            case ColorMatchMode.Green: {
                for (int c = 0; c < palette.Length; c++)
                {
                    float dg = palette[c].g - color.g;
                    float d  = dg * dg;
                    if (d < md)
                    {
                        md      = d;
                        nearest = palette[c];
                    }
                }
            }
            break;

            case ColorMatchMode.Blue: {
                for (int c = 0; c < palette.Length; c++)
                {
                    float db = palette[c].b - color.b;
                    float d  = db * db;
                    if (d < md)
                    {
                        md      = d;
                        nearest = palette[c];
                    }
                }
            }
            break;

            case ColorMatchMode.HSL: {
                HSLColor hsl = ColorConversion.GetHSLFromRGB(color.r, color.g, color.b);
                for (int c = 0; c < palette.Length; c++)
                {
                    HSLColor paletteHSL = ColorConversion.GetHSLFromRGB(palette[c].r, palette[c].g, palette[c].b);
                    float    dh         = (paletteHSL.h - hsl.h);
                    float    ds         = (paletteHSL.s - hsl.s);
                    float    dl         = (paletteHSL.l - hsl.l);
                    float    d          = dh * dh + ds * ds + dl * dl;
                    if (d < md)
                    {
                        md      = d;
                        nearest = palette[c];
                    }
                }
            }
            break;

            case ColorMatchMode.Hue: {
                float h = ColorConversion.GetHue(color.r, color.g, color.b);
                for (int c = 0; c < palette.Length; c++)
                {
                    float paletteH = ColorConversion.GetHue(palette[c].r, palette[c].g, palette[c].b);
                    float dh       = (paletteH - h);
                    float d        = dh * dh;
                    if (d < md)
                    {
                        md      = d;
                        nearest = palette[c];
                    }
                }
            }
            break;

            case ColorMatchMode.Saturation: {
                float s = ColorConversion.GetSaturation(color.r, color.g, color.b);
                for (int c = 0; c < palette.Length; c++)
                {
                    float paletteS = ColorConversion.GetSaturation(palette[c].r, palette[c].g, palette[c].b);
                    float dh       = (paletteS - s);
                    float d        = dh * dh;
                    if (d < md)
                    {
                        md      = d;
                        nearest = palette[c];
                    }
                }
            }
            break;

            case ColorMatchMode.Lightness: {
                float l = ColorConversion.GetLightness(color.r, color.g, color.b);
                for (int c = 0; c < palette.Length; c++)
                {
                    float paletteL = ColorConversion.GetLightness(palette[c].r, palette[c].g, palette[c].b);
                    float dh       = (paletteL - l);
                    float d        = dh * dh;
                    if (d < md)
                    {
                        md      = d;
                        nearest = palette[c];
                    }
                }
            }
            break;
            }
            nearest.a = color.a;
            color     = nearest;

            if (enableColorAdjustments)
            {
                if (colorAdjustments.applyLUT && colorAdjustments.LUT != null)
                {
                    color = ApplyLUT(color, colorAdjustments.LUT);
                }
                // vibrance
                float vibrance = colorAdjustments.vibrance;
                if (vibrance > 0)
                {
                    float maxComponent = color.r > color.g ? color.r : color.g;
                    maxComponent = color.b > maxComponent ? color.b : maxComponent;
                    float minComponent = color.r < color.g ? color.r : color.g;
                    minComponent = color.b < minComponent ? color.b : minComponent;
                    float sat = maxComponent - minComponent;
                    if (sat < 0)
                    {
                        sat = 0;
                    }
                    else if (sat > 1f)
                    {
                        sat = 1f;
                    }
                    float luma = color.GetLuma();
                    color.r *= 1f + vibrance * (1f - sat) * (color.r - luma);
                    color.g *= 1f + vibrance * (1f - sat) * (color.g - luma);
                    color.b *= 1f + vibrance * (1f - sat) * (color.b - luma);
                }
                // tinting
                float tintAmount = colorAdjustments.tintAmount;
                if (tintAmount > 0)
                {
                    Color tintedColor = new Color(color.r * colorAdjustments.tintColor.r, color.g * colorAdjustments.tintColor.g, color.b * colorAdjustments.tintColor.b);
                    color = Color.Lerp(color, tintedColor, tintAmount);
                }
                // contrast
                float contrast = colorAdjustments.contrast + 1f;
                if (contrast != 1f)
                {
                    color.r = (color.r - 0.5f) * contrast + 0.5f;
                    color.g = (color.g - 0.5f) * contrast + 0.5f;
                    color.b = (color.b - 0.5f) * contrast + 0.5f;
                }
                // brightness
                float brightness = colorAdjustments.brightness + 1f;
                if (brightness != 1f)
                {
                    color.r *= brightness;
                    color.g *= brightness;
                    color.b *= brightness;
                }
            }

            return(color);
        }
Esempio n. 5
0
        /// <summary>
        /// Returns a texture with colors that match the current palette
        /// </summary>
        public Texture2D GetNearestTexture(Texture tex, ColorMatchMode colorMatchMode, float threshold, ColorEntry[] colorOperations, bool enableColorAdjustments, ColorAdjustments colorAdjustments)
        {
            Color[] newColors = GetNearestColors(tex, colorMatchMode, threshold, colorOperations, enableColorAdjustments, colorAdjustments);
            if (newColors == null)
            {
                return(null);
            }
            Texture2D texture = (Texture2D)tex;
            Texture2D t       = new Texture2D(texture.width, texture.height, TextureFormat.ARGB32, false);

            t.name       = texture.name + "_ColorStudio";
            t.filterMode = tex.filterMode;
            t.wrapMode   = tex.wrapMode;
#if UNITY_EDITOR
            t.alphaIsTransparency = texture.alphaIsTransparency;
#endif
            t.SetPixels(newColors);
            t.Apply();
            return(t);
        }