这两天稍微研究了一下颜色的HSL/HSB值,主要因为写程序想要实现通过一张图片拿到图片中的最突出的颜色值(类似Groove Music中播放栏背景就是从专辑封面中取出主色调,还有Windows 10任务栏也可以从桌面背景获取主色调作为主题颜色)。

网上搜索了一下并没有满意的解决办法,于是自己小小的研究了一下,最后效果还算可以啦。

开始的时候想通过分析ARGB来获取,可以说是一头雾水,因为ARGB的组合实在是多,而且我也不清楚组合以后出来的颜色到底有什么规律,所以没过多久就放弃了。

之后决定用HSL/HSB的方式来获取主色调,之前只是了解有这个模式,并没有具体研究过H、S、B分别表示什么,然后小小的学习了一下,收获很大,RGB的模式对于计算机来说很简单,但是对于人类来说就很不友好了,毕竟我们是感性的动物,而HSL/HSB模式就很好理解了,Hue代表色调,范围0-360°,代表了各种颜色(没有白色和黑色,大家应该都知道白色和黑色并不是颜色~),Saturation代表饱和度,范围0-1,饱和度为0那么颜色就是真了,所有的颜色都将变为灰色,Brightness/Lightness代表亮度,范围0-1,这两个之间是有区别的,Brightness为0的话就是黑色(没有光当然是漆黑一片了),为1的话是某种颜色最亮的状态。而Lightness为0的时候也是黑色,但是为1的时候就是白色了(我觉得可以这样认为,光强超过了物体吸收光波的极限,所有的光都反射了回来,所以你看到的就是一片白色啦,对眼睛伤害很大,所以阳光很足的时候不要老在外面待着哦),Lightness为0.5对应了Brightness为1的状态,所以我认为Lightness是Brightness在数值上的延伸而已。总只Wiki上Copy来两张图就解释一切啦!

至于HSB/HSL与ARGB之间具体的转换关系就没有深入研究了,公式都有,深入研究就算了,毕竟头发宝贵……

看到网上都是再拿Hue来做文章,毕竟Hue代表了色调,开始我也这样认为,觉得拿到图片的所有像素,统计一下Hue在哪个颜色范围最多,然后就取这个色调颜色的均值好了,结果发现如果图片的颜色不多还好,如果颜色复杂的话,并不是很容易就能拿到想要的颜色,而且很容易把图片的背景色错认为图片的主色调,想了很多的方法,都觉得不能满足所有的情况,比如有的时候背景色占的面积很大,有时候很小,或者图片就一种颜色,或者颜色很多,这样的话可能需要分类讨论的情况很多,很复杂,最重要的是自己的数学真的不足以支持那么复杂的运算,高数线代什么的早都还给老师了,还是那句话,头发宝贵啊....

然后又经历了一个晚上的不眠之夜,早上起来班车上突然灵感来了,哈哈,觉得真的是想复杂了,入手点不应该从Hue出发,而是从另外两个值来搞事情,Saturation和Brightness,很简单,怎么样定义主色调?很简单,就是看一张图片我们第一眼就关注到的颜色,这样的颜色只需要满足两个条件,饱和度最大并且亮度最大,也就是最鲜艳的颜色,注意这里其实也是有个小问题的,有一个颜色喜好的问题,就想看红绿灯,虽然红绿黄三种颜色都是纯色,他们的饱和度和亮度都是1,但是最能引起我们注意的还是红色,而对于不同的颜色,我觉得每个人最先分辨的颜色可能也是不一样的……那么这个问题,我就不解决了,大神可以自己研究一下,我的做法相当的简单,拿到一组饱和度+亮度的值最大的颜色(可能还涉及到权重,我也不管这个,直接相加),这组颜色可能是很多色调的组合,那就说明这张图上我们第一眼可能看到的颜色有多种,那么拿到这些颜色,可以随机取一种或者进行某种运算,我的话就直接取均色好了,我觉得这样也不错。然后最终效果就是最上面的两张图,我自己是满意了,而且这样处理直接会去掉白色和黑色,除非图上只有这两种颜色。

以上完全是个人想法,请轻喷……

最后要吐槽一下微软,C#里面获取亮度的方法是GetBrightness,看名字觉得应该是采用HSB的颜色模式,结果写完代码一看傻眼了,所有图片拿到的都是白花花的一片,才意识到可能微软用的是HSL的模式,写了个小程序测试了一下,果然,纯色的Brightness都是0.5,而白色的Brightness为1,NM真的是坑啊,要不你就换成GetLightness好不好???

最后附代码,直接来一发拓展方法(刚刚跟猛哥那学来没多久,当然要多用一用),其实代码不重要,重要的是思路,如果大家有更好的想法,欢迎分享给我啦

(WPF的话还简单点,UWP取图片的像素点还是有点小麻烦的)

 static class ExtensionMethod
{
public static double GetHue(this Color color)
{
return System.Drawing.Color.FromArgb(color.A, color.R, color.G, color.B).GetHue();
} public static double GetSaturation(this Color color)
{
return System.Drawing.Color.FromArgb(color.A, color.R, color.G, color.B).GetSaturation();
} public static double GetBrightness(this Color color)
{
return System.Drawing.Color.FromArgb(color.A, color.R, color.G, color.B).GetBrightness();
} public async static Task<Color> GetMajorColorAsync(this BitmapImage bitmap)
{
var random = RandomAccessStreamReference.CreateFromUri(bitmap.UriSource);
var stream = await random.OpenReadAsync();
var decoder = await BitmapDecoder.CreateAsync(stream);
var data = await decoder.GetPixelDataAsync();
var bytes = data.DetachPixelData();
var colors = new List<Color>();
for (int i = ; i < bytes.Length; i += )
{
colors.Add(Color.FromArgb(bytes[i + ], bytes[i + ], bytes[i + ], bytes[i]));
}
colors = colors.GroupBy(c => - c.GetSaturation() + Math.Abs(0.5 - c.GetBrightness())).OrderBy(g => g.Key).FirstOrDefault().ToList();
var color = Color.FromArgb(Convert.ToByte(colors.Average(c => c.A)), Convert.ToByte(colors.Average(c => c.R)), Convert.ToByte(colors.Average(c => c.G)), Convert.ToByte(colors.Average(c => c.B)));
return color;
}
}

终于写完了,每天进步一点点,Get√

通过分析HSL/HSB获取图片主色调的更多相关文章

  1. iOS UIImage:获取图片主色调

    本文转载至 http://www.wahenzan.com/a/mdev/ios/2015/0325/1677.html -(UIColor*)mostColor{ #if __IPHONE_OS_V ...

  2. UWP取出图片主色调

    一切都要从风车动漫的新详情页说起... 当我最初拿到风车动漫新详情页的UI设计概念图时,新详情页中有两点: 1.图片的高斯模糊 2.取出图片的主色调(主要用于tag和相关动漫的标题背景) 大概就是要这 ...

  3. JS快速获取图片宽高的方法

    快速获取图片的宽高其实是为了预先做好排版样式布局做准备,通过快速获取图片宽高的方法比onload方法要节省很多时间,甚至一分钟以上都有可能,并且这种方法适用主流浏览器包括IE低版本浏览器. 我们一步一 ...

  4. php 获取图片主要颜色的方法

    本文章向码农们介绍php 获取图片主要颜色的方法,主要涉及php针对图片的相关操作技巧,需要的码农可以参考一下. $i = imagecreatefromjpeg("image.jpg&qu ...

  5. 转载:JS快速获取图片宽高的方法

    快速获取图片的宽高其实是为了预先做好排版样式布局做准备,通过快速获取图片宽高的方法比onload方法要节省很多时间,甚至一分钟以上都有可能,并且这种方法适用主流浏览器包括IE低版本浏览器. 我们一步一 ...

  6. Android--从系统Camera和Gallery获取图片优化

    前言 之前有两篇博客讲解了如何从系统内已有的Camera和Gallery应用中获取图片的例子,看到评论里有朋友说有时候会报错,导致程序崩溃的问题.本篇博客主要就这个问题分析讲解一下,最后将以一个简单的 ...

  7. 解决获取图片实际尺寸(宽高)的bug

    需求:获取图片的宽高其实是为了预先做好排版样式布局做准备. 可以利用图片onload事件监听获取图片的宽高属性值.在IE9以下版本只能使用图片的width与height属性,HTMl5中新加入了nat ...

  8. js获取图片信息(一)-----获取图片的原始尺寸

    如何获取图片的原始尺寸大小? 如下,当给 img 设置一个固定的大小时,要怎样获取图片的原始尺寸呢? #oImg{ width: 100px; height: 100px; } <img src ...

  9. 使用AI技术获取图片文字与识别图像内容

    获取图片文字 如何使用python获取图片文字呢? 关注公众号[轻松学编程]了解更多- 1.通过python的第三方库pytesseract获取 通过pip install pytesseract导入 ...

随机推荐

  1. 第三方页面嵌入到web项目的方案 之 使用iframe嵌入

    有些项目中可能会遇到这样的需求, 需要在一个项目中嵌入其他的项目的页面或者功能.并且需要这两个页面之间能够进行交互. 本文主要介绍如何实现这种第三方应用的嵌入, 主要有以下几个方向: 1.iframe ...

  2. 读书共享 Primer Plus C-part 9

    第十二章 存储类.链接和内存管理                                                       针对代码块中的static变量做如下范本 #include ...

  3. Linux下jdk环境配置

    1.下载jdk http://www.oracle.com/technetwork/java/javase/downloads/index.html 我选择64位的版本 jdk-8u121-linux ...

  4. HAProxy+Nginx 负载均衡

    一.什么是HAProxy HAProxy提供高可用性.负载均衡以及基于TCP和HTTP应用的代理,支持虚拟主机,它是免费.快速并且可靠的一种解决方案.HAProxy特别适用于那些负载特大的web站点, ...

  5. 打通MySQL的操作权限

    打通MySQL的操作权限 前面已经总结了<XAMPP的配置与使用>,虽然可以直接通过GUI控制面板去启动MySQL服务,但是有些相关的操作则需要在Windows中的CMD命令窗口中去对My ...

  6. FreeSWITCH 内线拨号 总是使用 dialplan/public 拨号计划,而对 dialplan/default 视而不见

    FreeSWITCH 内线拨号 总是使用 dialplan/public 拨号计划,而对 dialplan/default 视而不见 昨天还是 好好的额,  今天 就这样了, 导致 配置都乱了, 搞了 ...

  7. yml 文件操作方法

    文件读取方法示例: import yaml fr = open('yml_file_address', 'r',encoding='utf-8') data = yaml.load(fr) print ...

  8. Spring-Security 自定义Filter完成验证码校验

    Spring-Security的功能主要是由一堆Filter构成过滤器链来实现,每个Filter都会完成自己的一部分工作.我今天要做的是对UsernamePasswordAuthenticationF ...

  9. MongoDB入门系列(四):权限管理

    一.概述 本篇文章主要介绍如何创建用户和角色相关概念,同时对角色的添加和删除做了相关介绍. 版本:3.6.2 二.角色相关概念 1.数据库用户角色 read:该角色拥有数据的只读权限,系统集合以及sy ...

  10. Java遍历文件目录

    函数介绍 File[] listFiles():返回当前文件的子目录或子文件的文件数组. 遍历目录 调用listFiles()即可得文件的子目录和子文件,如果存在子目录,那么子目录需要再次调用list ...