Example #1
0
    // K-Means Mode
    public static bool checkColor2(Vector3 lab, afunction checkColor)
    {
        // Check that a color is valid: it must verify our checkColor condition, but also be in the color space
        //input is lab ?acolor = rgb2lab (acolor);
        Vector3 acolor = lab2hcl(lab);

        return(!float.IsNaN(acolor[0]) && acolor[0] >= 0 && acolor[1] >= 0 && acolor[2] >= 0 && acolor[0] < 256 && acolor[1] < 256 && acolor[2] < 256 && checkColor(lab));
    }
Example #2
0
    public static bool checkLab(Vector3 lab, afunction checkColor)
    {
        // It will be necessary to check if a Lab color exists in the rgb space.
        //first convert labtorgb
        Vector3 acolor = lab2rgb(lab);

        //Vector3 acolor = new Vector3(lab[0]*255, lab[1]*255, lab[2]*255);
        return(!float.IsNaN(acolor[0]) && acolor[0] >= 0 && acolor[1] >= 0 && acolor[2] >= 0 && acolor[0] < 256 && acolor[1] < 256 && acolor[2] < 256 && checkColor(lab));
    }
Example #3
0
    public static List <Vector3> generate(int colorsCount, afunction checkColor, bool forceMode, int quality, bool ultra_precision = false)
    {
        // Default
        rnd = new System.Random();
        if (colorsCount == null)
        {
            colorsCount = 8;
        }
        if (checkColor == null)
        {
            checkColor = testfunction;
        }
        if (forceMode == null)
        {
            forceMode = false;
        }
        if (quality == null)
        {
            quality = 50;
        }
        ultra_precision = ultra_precision || false;
        int steps = 0;

        if (forceMode)
        {
            // Force Vector Mode
            List <Vector3> colors = new List <Vector3>();
            // Init
            List <Vector3> vectors = new List <Vector3>();
            for (int i = 0; i < colorsCount; i++)
            {
                // Find a valid Lab color
                Vector3 acolor = new Vector3(Random.value, 2 * Random.value - 1, 2 * Random.value - 1);
                while (!checkLab(acolor, checkColor))
                {
                    acolor = new Vector3(Random.value, 2 * Random.value - 1, 2 * Random.value - 1);
                }
                colors.Add(acolor);
            }

            // Force vector: repulsion
            float repulsion = 0.3f;
            float speed     = 0.05f;
            steps = quality * 20;
            while (steps > 0)
            {
                // Init
                for (int i = 0; i < colors.Count; i++)
                {
                    vectors.Add(new Vector3(0, 0, 0));
                    //vectors[i] = {dl:0, da:0, db:0};
                }
                // Compute Force
                for (int i = 0; i < colors.Count; i++)
                {
                    Vector3 colorA = colors[i];
                    for (int j = 0; j < i; j++)
                    {
                        Vector3 colorB = colors[j];

                        // repulsion force
                        float dl = colorA[0] - colorB[0];
                        float da = colorA[1] - colorB[1];
                        float db = colorA[2] - colorB[2];
                        float d  = Mathf.Sqrt(Mathf.Pow(dl, 2) + Mathf.Pow(da, 2) + Mathf.Pow(db, 2));
                        if (d > 0)
                        {
                            float force = repulsion / Mathf.Pow(d, 2);

                            vectors[i][0] += dl * force / d;
                            vectors[i][1] += da * force / d;
                            vectors[i][2] += db * force / d;

                            vectors[j][0] -= dl * force / d;
                            vectors[j][1] -= da * force / d;
                            vectors[j][2] -= db * force / d;
                        }
                        else
                        {
                            // Jitter
                            vectors[j][0] += 0.02f - 0.04f * Random.value;
                            vectors[j][1] += 0.02f - 0.04f * Random.value;
                            vectors[j][2] += 0.02f - 0.04f * Random.value;
                        }
                    }
                }
                // Apply Force
                for (int i = 0; i < colors.Count; i++)
                {
                    Vector3 acolor       = colors[i];
                    float   displacement = speed * Mathf.Sqrt(Mathf.Pow(vectors[i].x, 2) + Mathf.Pow(vectors[i].y, 2) + Mathf.Pow(vectors[i].z, 2));
                    if (displacement > 0)
                    {
                        float   ratio        = speed * Mathf.Min(0.1f, displacement) / displacement;
                        Vector3 candidateLab = new Vector3(acolor[0] + vectors[i].x * ratio, acolor[1] + vectors[i].y * ratio, acolor[2] + vectors[i].z * ratio);
                        if (checkLab(candidateLab, checkColor))
                        {
                            colors[i] = candidateLab;
                        }
                    }
                }
                steps -= 1;
            }
            IEnumerable <Vector3> crgb = from c in colors select lab2rgb(c);

            return(crgb.ToList());
            //return colors.AsEnumerable.Select(c=>lab2rgb(c));
            //return colors;//colors.map(function(lab){return chroma.lab(lab[0], lab[1], lab[2]);});
        }
        else
        {
            bool init = true;
            if (kMeans == null)
            {
                kMeans = new List <Vector3>();
                init   = false;
            }
            //List<Vector3> kMeans = new List<Vector3>();
            kmeansClusters = new Dictionary <int, List <int> >();
            for (int i = 0; i < colorsCount; i++)
            {
                Vector3 lab = new Vector3(Random.value, 2 * Random.value - 1, 2 * Random.value - 1);
                while (!checkColor2(lab, checkColor))                       //chroma.lab(lab)
                {
                    lab = new Vector3(Random.value, 2 * Random.value - 1, 2 * Random.value - 1);
                }
                if (!init)
                {
                    kMeans.Add(lab);
                }
                kmeansClusters.Add(i, new List <int>());
            }

            colorSamples   = new List <Vector3>();
            samplesClosest = new List <int>();
            if (ultra_precision)
            {
                for (float l = 0; l <= 1; l += 0.01f)
                {
                    for (float a = -1; a <= 1; a += 0.05f)
                    {
                        for (float b = -1; b <= 1; b += 0.05f)
                        {
                            if (checkColor2(new Vector3(l, a, b), checkColor))                           //chroma.lab(l, a, b)
                            {
                                colorSamples.Add(new Vector3(l, a, b));
                                samplesClosest.Add(-1);
                            }
                        }
                    }
                }
            }
            else
            {
                for (float l = 0; l <= 1; l += 0.05f)
                {
                    for (float a = -1; a <= 1; a += 0.1f)
                    {
                        for (float b = -1; b <= 1; b += 0.1f)
                        {
                            if (checkColor2(new Vector3(l, a, b), checkColor))
                            {
                                colorSamples.Add(new Vector3(l, a, b));
                                samplesClosest.Add(-1);
                            }
                        }
                    }
                }
            }


            // Steps
            steps = quality;
            while (steps > 0)
            {
                // kMeans -> Samples Closest
                for (int i = 0; i < colorSamples.Count; i++)
                {
                    Vector3 lab         = colorSamples[i];
                    float   minDistance = 1000000;
                    for (int j = 0; j < kMeans.Count; j++)
                    {
                        Vector3 kMean    = kMeans[j];
                        float   distance = Mathf.Sqrt(Mathf.Pow(lab[0] - kMean[0], 2) + Mathf.Pow(lab[1] - kMean[1], 2) + Mathf.Pow(lab[2] - kMean[2], 2));
                        if (distance < minDistance)
                        {
                            minDistance       = distance;
                            samplesClosest[i] = j;
                        }
                    }
                }

                // Samples -> kMeans
                List <Vector3> freeColorSamples = new List <Vector3>(colorSamples);                      //colorSamples.slice(0);//copy?
                for (int j = 0; j < kMeans.Count; j++)
                {
                    int     count          = 0;
                    Vector3 candidateKMean = new Vector3(0, 0, 0);

                    //Debug.Log ("J "+j.ToString());
                    //Debug.Log ("Dic "+kmeansClusters.ToString());

                    for (int i = 0; i < colorSamples.Count; i++)
                    {
                        if (samplesClosest[i] == j)
                        {
                            count++;
                            candidateKMean[0] += colorSamples[i][0];
                            candidateKMean[1] += colorSamples[i][1];
                            candidateKMean[2] += colorSamples[i][2];
                            kmeansClusters[j].Add(i);
                        }
                    }
                    if (count != 0)
                    {
                        candidateKMean[0] /= count;
                        candidateKMean[1] /= count;
                        candidateKMean[2] /= count;
                    }
                    //chroma.lab ?
                    if (count != 0 && checkColor2(new Vector3(candidateKMean[0], candidateKMean[1], candidateKMean[2]), checkColor) && candidateKMean.magnitude != 0)
                    {
                        kMeans[j] = candidateKMean;
                    }
                    else
                    {
                        // The candidate kMean is out of the boundaries of the color space, or unfound.
                        if (freeColorSamples.Count > 0)
                        {
                            // We just search for the closest FREE color of the candidate kMean
                            float minDistance = 10000000000;
                            int   closest     = -1;
                            for (int i = 0; i < freeColorSamples.Count; i++)
                            {
                                float distance = Mathf.Sqrt(Mathf.Pow(freeColorSamples[i][0] - candidateKMean[0], 2) + Mathf.Pow(freeColorSamples[i][1] - candidateKMean[1], 2) + Mathf.Pow(freeColorSamples[i][2] - candidateKMean[2], 2));
                                if (distance < minDistance)
                                {
                                    minDistance = distance;
                                    closest     = i;
                                }
                            }
                            kMeans[j] = colorSamples[closest];
                        }
                        else
                        {
                            // Then we just search for the closest color of the candidate kMean
                            float minDistance = 10000000000;
                            int   closest     = -1;
                            for (int i = 0; i < colorSamples.Count; i++)
                            {
                                float distance = Mathf.Sqrt(Mathf.Pow(colorSamples[i][0] - candidateKMean[0], 2) + Mathf.Pow(colorSamples[i][1] - candidateKMean[1], 2) + Mathf.Pow(colorSamples[i][2] - candidateKMean[2], 2));
                                if (distance < minDistance)
                                {
                                    minDistance = distance;
                                    closest     = i;
                                }
                            }
                            kMeans[j] = colorSamples[closest];
                        }
                    }
                    //Array.ForEach<int>(intArray, PrintSquare);
                    IEnumerable <Vector3> freeColorSamples1 =
                        from color in freeColorSamples
                        where color[0] != kMeans[j][0] ||
                        color[1] != kMeans[j][1] ||
                        color[2] != kMeans[j][2]
                        select color;
                    freeColorSamples = freeColorSamples1.ToList();
                    //freeColorSamples = freeColorSamples.filter(function(color){
                    //		return color[0] != kMeans[j][0]
                    //		|| color[1] != kMeans[j][1]
                    //		|| color[2] != kMeans[j][2];
                    //	});
                }
                steps -= 1;
            }
            IEnumerable <Vector3> krgb = from c in kMeans select lab2rgb(c) / 255.0f;

            return(krgb.ToList());           // kMeans.map(function(lab){return chroma.lab(lab[0], lab[1], lab[2]);});lab->torgb?
        }
    }