这两天稍微研究了一下颜色的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. MySQL数据类型概念

    关系型数据库的特点 1,数据以表格的形式出现 2,每行为各种记录的名称 3,每列为数据名称所对应的数据域 4许多的行和列组成一张table 5若干的表单组成databases 术语 数据库:关联表的集 ...

  2. docker cs50 ide 安装

    ECS上搭建Docker(CentOS7): https://help.aliyun.com/document_detail/51853.html docker官方文档: https://docs.d ...

  3. CentOS安装JDK 8

    准备工作 首先,更新包: yum update 检查服务器上是否已安装旧版本的Java: java -version 如果有旧版本的Java则移除: yum remove java-1.6.0-ope ...

  4. Linux 安装配置 FTP 服务 (vsftpd)

    1. 安装 vsftpd yum install vsftpd -y 2. 创建用户 record adduser -s /bin/nologin -d /var/RecordFile/ record ...

  5. 【echarts3】--1 简单入门

    echarts3 相信大家都了解吧,是百度研发的 ECharts 特性介绍 ECharts,一个纯 Javascript 的图表库,可以流畅的运行在 PC 和移动设备上,兼容当前绝大部分浏览器(IE8 ...

  6. Kubernetes 概念整理

    注:以下大部分内容来自网上摘录,以便后期查阅. Kubernetes (通常称为 K8s) 是用于自动部署.扩展和管理容器化(containerized)应用程序的开源系统,是 Google 内部工具 ...

  7. python入门学习笔记(三)

    10.函数 求绝对值的函数 abs(x) 也可以在交互式命令行通过 help(abs) 查看abs函数的帮助信息.调用 abs 函数:>>> abs(100)100>>& ...

  8. CSS布局(四) float详解

    一.float设计初衷 因为float被设计出来的初衷是用于--文字环绕效果.即,一个图片一段文字,图片float:left之后,文字会环绕图片. <div style="width: ...

  9. eclipse设置git忽略文件

    使用eclipse开发的程序员们经常会接触版本控制软件,这里只要说下eclipse使用egit的情况下设置忽略文件. 特此说明在这里使用window->team->ignored对于git ...

  10. 对于任意大于1的自然数n,若n为奇数,则将n变为3n+1,否则变为n的一半。 经过若干次这样的变换,一定会使n变为1

    对于任意大于1的自然数n,若n为奇数,则将n变为3n+1,否则变为n的一半.经过若干次这样的变换,一定会使n变为1.例如,3→10→5→16→8→4→2→1.输入n,输出变换的次数.n≤10 9 .样 ...