static public List <CIELab[]> SplitOnParts(CIELab[] inputArray, int PartsCount) { List <CIELab[]> outputList = new List <CIELab[]>(); int[,] Sizes = new int[PartsCount, 3]; int PartSize = inputArray.Length / PartsCount; Sizes[0, 0] = 0; Sizes[0, 1] = (inputArray.Length - PartSize * (PartsCount - 1)) - 1; Sizes[0, 2] = Sizes[0, 1] - Sizes[0, 0] + 1; for (int i = 1; i < PartsCount; i++) { Sizes[i, 0] = Sizes[i - 1, 1] + 1; Sizes[i, 1] = Sizes[i, 0] + PartSize - 1; Sizes[i, 2] = Sizes[i, 1] - Sizes[i, 0] + 1; } for (int i = 0; i < PartsCount; i++) { outputList.Add(new CIELab[Sizes[i, 2]]); for (int j = 0; j < Sizes[i, 2]; j++) { outputList[i][j] = new CIELab(inputArray[j + Sizes[i, 0]]); } } return(outputList); }
static public Color CIELab_to_RGB(CIELab LAB) { double[] XYZ = new double[3]; XYZ = CIELab_to_XYZ(LAB); return(XYZ_to_RGB(XYZ)); }
static public CIELab[] Array_RGBtoCIELab(Color[] inputList) { CIELab[] outputList = new CIELab[inputList.Length]; for (int i = 0; i < inputList.Length; i++) { outputList[i] = CIELab.RGB_to_CIELab(inputList[i]); } return(outputList); }
static public double deltaE76(CIELab first, CIELab second) { double var_L, var_a, var_b; var_L = first.L - second.L; var_a = first.a - second.a; var_b = first.b - second.b; var_L = var_L * var_L; var_a = var_a * var_a; var_b = var_b * var_b; return(var_L + var_a + var_b); }
public void GetColorInfo(Color color) { ChangeNeeded = false; TargetRGB = color; TargetHSV.H = color.GetHue(); TargetHSV.S = color.GetSaturation(); TargetHSV.V = color.GetBrightness(); TargetXYZ = CIELab.RGB_to_XYZ(color); TargetCIELab = CIELab.XYZ_to_CIELab(TargetXYZ); SetRGB(); SetHSV(); SetXYZ(); SetCIELab(); ChangeNeeded = true; }
static public List <List <Color> > GroupList_CIELabtoRBG(List <List <CIELab> > inputList) { List <List <Color> > outputList = new List <List <Color> >(); List <Color> temp = new List <Color>(); foreach (List <CIELab> list in inputList) { foreach (CIELab color in list) { temp.Add(CIELab.CIELab_to_RGB(color)); } outputList.Add(temp.GetRange(0, temp.Count)); temp.Clear(); } return(outputList); }
static public double[] CIELab_to_XYZ(CIELab LAB) { double[] XYZ = new double[3]; double var_Y = (LAB.L + 16d) / 116d; double var_X = LAB.a / 500d + var_Y; double var_Z = var_Y - LAB.b / 200d; if (Math.Pow(var_Y, 3d) > 0.008856d) { var_Y = Math.Pow(var_Y, 3); } else { var_Y = (var_Y - 16d / 116d) / 7.787d; } if (Math.Pow(var_X, 3d) > 0.008856d) { var_X = Math.Pow(var_X, 3); } else { var_X = (var_X - 16d / 116d) / 7.787d; } if (Math.Pow(var_Z, 3d) > 0.008856) { var_Z = Math.Pow(var_Z, 3); } else { var_Z = (var_Z - 16d / 116d) / 7.787d; } XYZ[0] = var_X * ref_x; XYZ[1] = var_Y * ref_y; XYZ[2] = var_Z * ref_z; return(XYZ); }
static public Color HSV_to_RGB(HSV hsv) { double H = hsv.H; double S = hsv.S; double V = hsv.V; while (H < 0) { H += 360; } ; while (H >= 360) { H -= 360; } ; double R, G, B; if (V <= 0) { R = G = B = 0; } else if (S <= 0) { R = G = B = V; } else { double hf = H / 60.0; int i = (int)Math.Floor(hf); double f = hf - i; double pv = V * (1 - S); double qv = V * (1 - S * f); double tv = V * (1 - S * (1 - f)); switch (i) { case 0: R = V; G = tv; B = pv; break; case 1: R = qv; G = V; B = pv; break; case 2: R = pv; G = V; B = tv; break; case 3: R = pv; G = qv; B = V; break; case 4: R = tv; G = pv; B = V; break; case 5: R = V; G = pv; B = qv; break; case 6: R = V; G = tv; B = pv; break; case -1: R = V; G = pv; B = qv; break; default: R = G = B = V; break; } } int r = CIELab.FixOutOfRangeVaue((int)(R * 255.0)); int g = CIELab.FixOutOfRangeVaue((int)(G * 255.0)); int b = CIELab.FixOutOfRangeVaue((int)(B * 255.0)); return(Color.FromArgb(r, g, b)); }
public CIELab(CIELab get) { L = get.L; a = get.a; b = get.b; }
public bool Equal(CIELab first) { return(L == first.L && a == first.a && b == first.b); }
static public Color[] V5(Color[] llist, int ColorsCount) { List <RGB> RGB_AllColors = new List <RGB>(); foreach (Color item in llist) { RGB_AllColors.Add(new RGB(item)); } List <List <Color> > Result = new List <List <Color> >(); List <RGB> Part = new List <RGB>(); int maxLength = 0; int emptyListCount = 0; RGB_AllColors.Sort(delegate(RGB left, RGB right) { return(right.Hue.CompareTo(left.Hue)); }); for (int i = 0; i < ColorsCount; i++) { if (i < 3) { foreach (RGB item in RGB_AllColors) { if ((float)item.Hue >= (float)(120f * (float)i) && (float)item.Hue <= (float)(120f * (float)(i + 1))) { Part.Add(item); } } } if (Part.Count >= 2) { Part = ColorPalette.DistrictByHue(Part, true); Part.Sort(delegate(RGB left, RGB right) { return(left.Hue.CompareTo(right.Hue)); }); } if (maxLength < Part.Count) { maxLength = Part.Count; } if (Part.Count == 0) { emptyListCount += 1; } List <Color> temp = new List <Color>(); foreach (RGB item in Part) { temp.Add(item.Color); } Result.Add(temp.GetRange(0, temp.Count)); Part.Clear(); } if (emptyListCount != 0 && maxLength > 1) { double E_value = 0d; double E_valueMax = 0d; int GroupIndex = 0; while (emptyListCount != 0) { Result.Sort(delegate(List <Color> left, List <Color> right) { return(right.Count.CompareTo(left.Count)); }); E_value = 0d; E_valueMax = 0d; GroupIndex = 0; for (int i = 0; i < ColorsCount; i++) { if (Result[i].Count > 1) { Color left = ColorPalette.GetAverageColor(Result[i].GetRange(0, Result[i].Count / 2)); Color right = ColorPalette.GetAverageColor(Result[i].GetRange(Result[i].Count / 2, Result[i].Count / 2)); CIELab CIE_left = CIELab.RGB_to_CIELab(left); CIELab CIE_right = CIELab.RGB_to_CIELab(right); E_value = CIELab.deltaE76(CIE_left, CIE_right); if (E_value > E_valueMax) { GroupIndex = i; E_valueMax = E_value; } } } maxLength = Result[GroupIndex].Count; if (maxLength == 1) { break; } Result[ColorsCount - 1].AddRange(Result[GroupIndex].GetRange(0, maxLength / 2)); Result[GroupIndex].RemoveRange(0, maxLength / 2); emptyListCount--; } } int index = Result.FindIndex(group => group.Count != 0); for (int i = 0; i < Result.Count; i++) { if (Result[i].Count == 0) { Result[i] = Result[index]; } } return(ColorPalette.GetAverageColors(Result).ToArray()); }
static public List <List <Color> > RunSingleThread(Color[] RGB_AllColors, int ClasterCount, int InitVersion) { int IterationCount = 0; int ColorsCount; int weight; double var_L, var_a, var_b, count, minE, E; List <List <CIELab> > ResultClasters = new List <List <CIELab> >(); CIELab[] PreviousCentroids = new CIELab[ClasterCount]; CIELab[] CIELab_AllColors = Converter.Array_RGBtoCIELab(RGB_AllColors); AllWeights = ColorPalette.GetColorsWeights(RGB_AllColors); Color[] RGB_AllColorsDistr = ColorPalette.DistrictByRGB(RGB_AllColors); CIELab[] CIELab_AllColorsDistr = Converter.Array_RGBtoCIELab(RGB_AllColorsDistr); ColorsCount = RGB_AllColorsDistr.Length; for (int i = 0; i < ClasterCount; i++) { PreviousCentroids[i] = CIELab_AllColors[0]; ResultClasters.Add(new List <CIELab>()); } switch (InitVersion) { case 1: CurrentCentroids = Converter.Array_RGBtoCIELab(InitializeCentroids.V1(RGB_AllColors, ClasterCount)); break; case 2: CurrentCentroids = Converter.Array_RGBtoCIELab(InitializeCentroids.V2(RGB_AllColors, ClasterCount)); break; case 3: CurrentCentroids = Converter.Array_RGBtoCIELab(InitializeCentroids.V3(RGB_AllColors, ClasterCount)); break; case 4: CurrentCentroids = Converter.Array_RGBtoCIELab(InitializeCentroids.V4(RGB_AllColors, ClasterCount)); break; case 5: CurrentCentroids = Converter.Array_RGBtoCIELab(InitializeCentroids.V5(RGB_AllColors, ClasterCount)); break; default: CurrentCentroids = Converter.Array_RGBtoCIELab(InitializeCentroids.V4(RGB_AllColors, ClasterCount)); break; } while (true) { IterationCount++; double[,] accum = new double[ClasterCount, 4]; CIELab CurrentColor; int NumOfNearestClaster = 0; for (int f = 0; f < ColorsCount; f++) { minE = 1000000d; CurrentColor = CIELab_AllColorsDistr[f]; weight = AllWeights[f]; for (int i = 0; i < ClasterCount; i++) { var_L = CurrentColor.L - CurrentCentroids[i].L; var_a = CurrentColor.a - CurrentCentroids[i].a; var_b = CurrentColor.b - CurrentCentroids[i].b; var_L = var_L * var_L; var_a = var_a * var_a; var_b = var_b * var_b; E = var_L + var_a + var_b; if (E < minE) { minE = E; NumOfNearestClaster = i; } } accum[NumOfNearestClaster, 0] += CurrentColor.L * weight; accum[NumOfNearestClaster, 1] += CurrentColor.a * weight; accum[NumOfNearestClaster, 2] += CurrentColor.b * weight; accum[NumOfNearestClaster, 3] += weight; } CurrentCentroids.CopyTo(PreviousCentroids, 0); for (int f = 0; f < ClasterCount; f++) { count = var_L = var_a = var_b = 0; count += accum[f, 3]; var_L += accum[f, 0]; var_a += accum[f, 1]; var_b += accum[f, 2]; var_L = var_L / count; var_a = var_a / count; var_b = var_b / count; CurrentCentroids[f] = new CIELab(var_L, var_a, var_b); } bool equal = CompareClasters(CurrentCentroids, PreviousCentroids); if (equal || IterationCount >= 500) { Group(CIELab_AllColorsDistr, ResultClasters, ClasterCount); FillEmptyClasters(ResultClasters, ClasterCount); break; } } if (ClasterCount == 20) { ColorPalette.s = IterationCount.ToString() + "\t count"; } return(Converter.GroupList_CIELabtoRBG(ResultClasters)); }
static public List <List <Color> > RunMultiThread(Color[] RGB_AllColors, int ClasterCount, int InitVersion) { int IterationCount = 0; int ThreadCount = 3; int ColorsCount = RGB_AllColors.Length; double var_L, var_a, var_b, count; List <List <CIELab> > ResultClasters = new List <List <CIELab> >(); CIELab[] PreviousCentroids = new CIELab[ClasterCount]; CIELab[] CIELab_AllColors; AccumParts = new List <double[, ]>(); switch (InitVersion) { case 1: CurrentCentroids = Converter.Array_RGBtoCIELab(InitializeCentroids.V1(RGB_AllColors, ClasterCount)); break; case 2: CurrentCentroids = Converter.Array_RGBtoCIELab(InitializeCentroids.V2(RGB_AllColors, ClasterCount)); break; case 3: CurrentCentroids = Converter.Array_RGBtoCIELab(InitializeCentroids.V3(RGB_AllColors, ClasterCount)); break; case 4: CurrentCentroids = Converter.Array_RGBtoCIELab(InitializeCentroids.V4(RGB_AllColors, ClasterCount)); break; case 5: CurrentCentroids = Converter.Array_RGBtoCIELab(InitializeCentroids.V5(RGB_AllColors, ClasterCount)); break; default: CurrentCentroids = Converter.Array_RGBtoCIELab(InitializeCentroids.V4(RGB_AllColors, ClasterCount)); break; } AllWeights = ColorPalette.GetColorsWeights(RGB_AllColors); RGB_AllColors = ColorPalette.DistrictByRGB(RGB_AllColors); CIELab_AllColors = Converter.Array_RGBtoCIELab(RGB_AllColors); WeightsParts = Converter.SplitOnParts(AllWeights, ThreadCount); CIELab_Parts = Converter.SplitOnParts(CIELab_AllColors, ThreadCount); for (int j = 0; j < ThreadCount; j++) { AccumParts.Add(new double[ClasterCount, 4]); for (int i = 0; i < ClasterCount; i++) { PreviousCentroids[i] = CIELab_Parts[0][0]; } } for (int i = 0; i < ClasterCount; i++) { ResultClasters.Add(new List <CIELab>()); } var watch = System.Diagnostics.Stopwatch.StartNew(); while (true) { IterationCount++; using (CountdownEvent complete = new CountdownEvent(ThreadCount)) { ThreadPool.QueueUserWorkItem(delegate { MainAlgorithm(CIELab_Parts[0], ClasterCount, 0); complete.Signal(); }); ThreadPool.QueueUserWorkItem(delegate { MainAlgorithm(CIELab_Parts[1], ClasterCount, 1); complete.Signal(); }); ThreadPool.QueueUserWorkItem(delegate { MainAlgorithm(CIELab_Parts[2], ClasterCount, 2); complete.Signal(); }); complete.Wait(); } CurrentCentroids.CopyTo(PreviousCentroids, 0); for (int f = 0; f < ClasterCount; f++) { count = var_L = var_a = var_b = 0; for (int j = 0; j < ThreadCount; j++) { count += AccumParts[j][f, 3]; var_L += AccumParts[j][f, 0]; var_a += AccumParts[j][f, 1]; var_b += AccumParts[j][f, 2]; } var_L = var_L / count; var_a = var_a / count; var_b = var_b / count; CurrentCentroids[f] = new CIELab(var_L, var_a, var_b); } bool equal = CompareClasters(CurrentCentroids, PreviousCentroids); if (equal || IterationCount >= 500) { Group(CIELab_AllColors, ResultClasters, ClasterCount); FillEmptyClasters(ResultClasters, ClasterCount); break; } } watch.Stop(); var elapsedMs = watch.ElapsedMilliseconds; if (ClasterCount == 20) { ColorPalette.s += IterationCount.ToString() + "\t count\n"; ColorPalette.s += ((float)elapsedMs / 1000).ToString() + "\t mainAlgo"; } return(Converter.GroupList_CIELabtoRBG(ResultClasters)); }
public void ConvertColor() { ChangeNeeded = false; switch (ConvertType) { case "RGB": TargetRGB = Color.FromArgb(Int32.Parse(RGB_R.Text), Int32.Parse(RGB_G.Text), Int32.Parse(RGB_B.Text)); TargetXYZ = CIELab.RGB_to_XYZ(TargetRGB); TargetCIELab = CIELab.RGB_to_CIELab(TargetRGB); TargetHSV = HSV.RGB_to_HSV(TargetRGB); SetHSV(); SetXYZ(); SetCIELab(); break; case "HSV": TargetHSV.H = Double.Parse(HSV_H.Text); TargetHSV.S = Double.Parse(HSV_S.Text); TargetHSV.V = Double.Parse(HSV_V.Text); TargetRGB = HSV.HSV_to_RGB(TargetHSV); TargetXYZ = CIELab.RGB_to_XYZ(TargetRGB); TargetCIELab = CIELab.RGB_to_CIELab(TargetRGB); SetRGB(); SetXYZ(); SetCIELab(); break; case "XYZ": TargetXYZ[0] = Double.Parse(XYZ_X.Text) * 100d; TargetXYZ[1] = Double.Parse(XYZ_Y.Text) * 100d; TargetXYZ[2] = Double.Parse(XYZ_Z.Text) * 100d; TargetRGB = CIELab.XYZ_to_RGB(TargetXYZ); TargetCIELab = CIELab.XYZ_to_CIELab(TargetXYZ); TargetHSV = HSV.RGB_to_HSV(TargetRGB); SetRGB(); SetHSV(); SetCIELab(); break; case "Lab": TargetCIELab.L = Double.Parse(Lab_L.Text); TargetCIELab.a = Double.Parse(Lab_a.Text); TargetCIELab.b = Double.Parse(Lab_b.Text); TargetRGB = CIELab.CIELab_to_RGB(TargetCIELab); TargetXYZ = CIELab.CIELab_to_XYZ(TargetCIELab); TargetHSV = HSV.RGB_to_HSV(TargetRGB); SetRGB(); SetHSV(); SetXYZ(); break; } targetColor.BackColor = TargetRGB; ConvertType = ""; ChangeNeeded = true; }