win10在設置顏色里有個從“背景圖片中選取一種主題顏色”的選項,還有在很多內容展示軟體中都使用了這樣的功能。 現在我們需要在 nuget 引用 win2d.uwp 和 Toolkit.uwp 兩個庫。 首先將一個圖片流轉換成 win2d 的 CanvasBitmap 對象,然後通過 CanvasB ...
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);
右邊為圖片的主題顏色,可以看到這張圖片的大部分顏色為黑色,而當我們看到這張圖片的時候我們的註意力就卻會被藍色吸引住,我們在計算中並不是找到出現最多次的顏色為主題顏色,而是亮度和飽和度最為突出的作為主題色。
全部代碼:
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 } }