win10在設置顏色裏有個從「背景圖片中選取一種主題顏色」的選項,還有在不少內容展現軟件中都使用了這樣的功能。數組
如今咱們須要在 nuget 引用 win2d.uwp 和 Toolkit.uwp 兩個庫。dom
首先將一個圖片流轉換成 win2d 的 CanvasBitmap 對象,而後經過 CanvasBitmap 的 GetPixelColors 方法獲取到圖片的所有顏色數組。async
/// <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);spa
}
在拿到整個顏色數組後咱們須要計算出 平均亮度,平均飽和度,和平均色相code
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);blog
已經將須要作判斷的值求出來後,咱們將 剔除了白色和黑色的 數據在作一遍計算,符合條件的顏色相加在一塊兒 再 將總和除以符合條件的數量。圖片
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);get
右邊爲圖片的主題顏色,能夠看到這張圖片的大部分顏色爲黑色,而當咱們看到這張圖片的時候咱們的注意力就卻會被藍色吸引住,咱們在計算中並非找到出現最屢次的顏色爲主題顏色,而是亮度和飽和度最爲突出的做爲主題色。
所有代碼:
using Microsoft.Graphics.Canvas; using Microsoft.Toolkit.Uwp; using System; using System.Collections.Generic; using System.Threading.Tasks; using Windows.Storage.Streams; using Windows.UI; namespace uwp_播放器.Data { public class ImageThemeBrush { CanvasDevice device = new CanvasDevice(); /// <summary> /// 經過Uri獲取主題色 /// </summary> /// <param name="uri"></param> /// <returns></returns> public async Task<Color> GetPaletteImage(Uri uri) { //實例化資源 var bimap = await CanvasBitmap.LoadAsync(device, uri); //取色 Color[] colors = bimap.GetPixelColors(); return await GetThemeColor(colors); } /// <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); } #region Methon:方法 private async Task<Color> GetThemeColor(Color[] colors) { Color color = new Color(); await Task.Run(() => { //飽和度 黑色多 double sumS = 0; //明亮度 白色多 double sumV = 0; double sumHue = 0; //顏色中最大亮度 double maxV = 0; //顏色中最大飽和度 double maxS = 0; //顏色中最大色相 double maxH = 0; double count = 0; List<Color> notBlackWhite = new List<Color>(); 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 avgH = sumHue / count; 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); //aveS = aveS ; double R = 0; double G = 0; double B = 0; count = 0; 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); }); colors = null; return color; } #endregion } }