uwp 用win2d获取图片主调颜色

win10在设置颜色里有个从“背景图片中选取一种主题颜色”的选项,还有在很多内容展示软件中都使用了这样的功能。

      现在我们需要在 nuget 引用 win2d.uwp 和 Toolkit.uwp 两个库。

     首先将一个图片流转换成 win2d 的 CanvasBitmap 对象,然后通过 CanvasBitmap 的 GetPixelColors 方法获取到图片的全部颜色数组。

1
2
3
4
5
6
7
8
9
10
11
12
13
/// <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
    }
}
复制代码

 

posted @   吃饭/睡觉  阅读(478)  评论(8编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
点击右上角即可分享
微信分享提示