// 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)); }
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)); }
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? } }