win10在设置颜色里有个从“背景图片中选取一种主题颜色”的选项
,还有在很多内容展示软件中都使用了这样的功能。
现在我们需要在 nuget 引用 win2d.uwp 和 Toolkit.uwp 两个库。
首先将一个图片流转换成 win2d 的 CanvasBitmap 对象,然后通过 CanvasBitmap 的 GetPixelColors 方法获取到图片的全部颜色数组。
- /// <summary>
- /// 通过stream获取主题色
- /// </summary>
- /// <param name="uri"></param>
- /// <returns></returns>
- public async Task<Color> GetPaletteImage(IRandomAccessStream stream)
- {
-
-
-
- //实例化资源
- var bimap = await CanvasBitmap.LoadAsync(device , stream);
//取色
Color[] colors = bimap.GetPixelColors();
return await GetThemeColor(colors);
-
- }
在拿到整个颜色数组后我们需要计算出 平均亮度,平均饱和度,和平均色相
- foreach (var item in colors)
- {
- //将 rgb 转换成 hsv 对象
- HsvColor hsv = Microsoft.Toolkit.Uwp.Helpers.ColorHelper.ToHsv(item);
- //先将黑色和白色剔除掉
- if (hsv.V < 0.3 || hsv.S < 0.2)
- {
- continue;
- }
- //找出最大饱和度
- maxS = hsv.S > maxS ? hsv.S : maxS;
- //找出最大亮度度
- maxV = hsv.V > maxV ? hsv.V : maxV;
- //找出最大色相
- maxH = hsv.H > maxH ? hsv.H : maxH;
- //色相总和
- sumHue += hsv.H;
- //亮度总和
- sumS += hsv.S;
- //饱和度总和
- sumV += hsv.V;
- count++;
- notBlackWhite.Add(item);
- }
double avgV = sumV / count;
double avgS = sumS / count;
double maxAvgV = maxV / 2;
double maxAvgS = maxS / 2;
double maxAvgH = maxH / 2;
-
//计算各个值,用来做判断用
double h = Math.Max(maxAvgV, avgV);
double s = Math.Min(maxAvgS, avgS);
double hue = Math.Min(maxAvgH, avgH);
-
已经将需要做判断的值求出来后,我们将 剔除了白色和黑色的 数据在做一遍计算,符合条件的颜色相加在一起 再 将总和除以符合条件的数量。
- foreach (var item in notBlackWhite)
- {
- HsvColor hsv = Microsoft.Toolkit.Uwp.Helpers.ColorHelper.ToHsv(item);
- //颜色大于平均色相 并且 饱和度大于平局饱和度 并且 亮度大于平局亮度 的符合条件 进行相加
- if (hsv.H >= hue + 10 && hsv.V >= h && hsv.S >= s)
- {
- R += item.R;
- G += item.G;
- B += item.B;
- count++;
- }
- }
double r = R / count;
double g = G / count;
double b = B / count;
color = Color.FromArgb(255, (byte)r, (byte)g, (byte)b);
-
右边为图片的主题颜色,可以看到这张图片的大部分颜色为黑色,而当我们看到这张图片的时候我们的注意力就却会被蓝色吸引住,我们在计算中并不是找到出现最多次的颜色为主题颜色,而是亮度和饱和度最为突出的作为主题色。




全部代码: