uwp 用win2d获取图片主调颜色

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
    }
}

 

posted @ 2018-08-24 20:49  吃饭/睡觉  阅读(463)  评论(8编辑  收藏  举报