这两天稍微研究了一下颜色的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. memcached 与 redis 的区别和具体应用场景

    1. Memcached简介 Memcached是以LiveJurnal旗下Danga Interactive公司的Bard Fitzpatric为首开发的高性能分布式内存缓存服务器.其本质上就是一个 ...

  2. Netty基础点滴

    编写一个应答服务器 编写一个应答服务器 写一个Netty服务器主要由两部分组成: 配置服务器功能,如线程.端口 实现服务器处理程序,它包含业务逻辑,决定当有一个请求连接或接收数据时该做什么 启动服务器 ...

  3. windows FileZilla Server 开启FTP over TLS

    FileZilla Server官方下载地址: https://filezilla-project.org/download.php?type=server FileZilla Server 开启FT ...

  4. angular2^ typescript 将 文件和Json数据 合并发送到服务器(2.服务端)

    nodejs 中使用框架 express web框架 multer 文件接受 直接贴代码了,我就不解释了 "use strict"; exports.__esModule = tr ...

  5. Python基础总结

      刚学习Python时,边学边总结的,采用思维导图的形式, 适合回顾使用.内容参考<Python:从入门到实践>一书.   再给出一张Datacamp网站上的一张关于Python基础的总 ...

  6. hibernate学习(六) flush()和clean()区别和使用

    session.flush()是强制和数据库同步 session.clean()是清除session中的缓存 对于批量数据插入的时候优化:减少cpu和内存(缓存)占用量 @Test public vo ...

  7. python调用百度语音(语音识别-斗地主语音记牌器)

    一.概述 本篇简要介绍百度语音语音识别的基本使用(其实是斗地主时想弄个记牌器又没money,抓包什么的又不会,只好搞语音识别的了) 二.创建应用 打开百度语音官网,产品与使用->语音识别-> ...

  8. Android浏览器访问java web的方法

    以前自己也做过Android程序,可以和服务器通信,通过json来存取数据,当时是在APP中直接存取数据的,而这次我打算在手机浏览器中获得服务器传过来的Json参数,后来才发现其实很简单的,首先需要手 ...

  9. 危化品速查APP--Android Project

    开发环境 Android studio 2.3.1 功能描述 集成多种查询方式,查看本地数据库中危险化学品的信息: 按照中文拼音和英文首字母,对化学品进行查询: 按照UN号或者CAS号查询相应的化学品 ...

  10. python 爬取糗事百科 gui小程序

    前言:有时候无聊看一些搞笑的段子,糗事百科还是个不错的网站,所以就想用Python来玩一下.也比较简单,就写出来分享一下.嘿嘿 环境:Python 2.7 + win7 现在开始,打开糗事百科网站,先 ...