private static Color Mix(WeightedValue<Color>[] colors) { double weightSum = colors.Select(vv => vv.Weight).Sum(); var normalizedHSLColors = colors.Select(vc => new WeightedValue<HSL>(ColorSpaceHelper.RGBtoHSL(vc.Value.R, vc.Value.G, vc.Value.B), vc.Weight / weightSum)); double h = 0.0; double count = 0.0; double sSum = 0.0; double lSum = 0.0; double x = 0.0; double y = 0.0; foreach (var color in normalizedHSLColors) { count++; sSum += color.Value.Saturation * (color.Weight * 2.0); lSum += color.Value.Luminance * (color.Weight * 2.0); x += Math.Cos(2.0 * Math.PI * (DegreeToPercent(color.Value.Hue) * (color.Weight * 2.0))); y += Math.Sin(2.0 * Math.PI * (DegreeToPercent(color.Value.Hue) * (color.Weight * 2.0))); } double s = sSum / count; double l = lSum / count; if ((x != 0.0) || (y != 0.0)) { h = Math.Atan2(y, x) / (2.0 * Math.PI); } else { s = 0.0; } var result = ColorSpaceHelper.HSLtoRGB(PercentToDegree(h), s, l); double r = result.Red, g = result.Green, b = result.Blue; const double addRatio = 0.0; const double avgRatio = 0.0; const double subRatio = 0.0; const double colorizeRatio = (1.0 - (addRatio + avgRatio + subRatio)); double additiveR = ComputeAdditiveComponent(colors, weightSum, (c) => c.R); double substractiveR = ComputeSubtractiveComponent(colors, weightSum, (c) => c.R); double avgR = ComputeAvgComponent(colors, weightSum, (c) => c.R); double additiveG = ComputeAdditiveComponent(colors, weightSum, (c) => c.G); double substractiveG = ComputeSubtractiveComponent(colors, weightSum, (c) => c.G); double avgG = ComputeAvgComponent(colors, weightSum, (c) => c.G); double additiveB = ComputeAdditiveComponent(colors, weightSum, (c) => c.B); double substractiveB = ComputeSubtractiveComponent(colors, weightSum, (c) => c.B); double avgB = ComputeAvgComponent(colors, weightSum, (c) => c.B); return Color.FromRgb( ToByte(r * colorizeRatio + additiveR * addRatio + substractiveR * subRatio + avgR * avgRatio), ToByte(g * colorizeRatio + additiveG * addRatio + substractiveG * subRatio + avgG * avgRatio), ToByte(b * colorizeRatio + additiveB * addRatio + substractiveB * subRatio + avgB * avgRatio)); }
private static double ComputeAdditiveComponent(WeightedValue<Color>[] colors, double weightSum, Func<Color, byte> selectComponent) { return ToByteRange(Add(colors.Select(c => new WeightedValue<double>(selectComponent(c.Value), c.Weight / weightSum)))); }
private static double ComputeAvgComponent(WeightedValue<Color>[] colors, double weightSum, Func<Color, byte> selectComponent) { return ToByteRange(colors.Select(c => selectComponent(c.Value) * ((c.Weight / weightSum) * 2.0)).Average()); }