海报网页背景色的提取

(原样式)

可爱的PM又来提需求了:做一个能自动从海报上提取(好看的)颜色作为网页背景色的功能,我们要让海报类网页向App的体验看齐。

好的……诶!不对啊,我是个FE,配色不是我的擅长阿!?还好我在设计团队耳濡目染的几年,有了一点点审美能力和一丢丢设计类app的使用经验。打开ide、打开ps,搞起!

先捋一下这个需求的解决思路:

  1. 从图片中提取主要颜色信息(让底色和海报产生关联性)
  2. 颜色必须与该图片和网页内文字有鲜明的对比度(视觉舒适)

【第一步:提取颜色】

每一张图片都包含着width * height像素的[red, green, blue, alpha]颜色信息,我们需要依托前端的canvas对象从图片中提取基本颜色数据:

// 读取网页上id为img的图片对象
var image = document.getElementById('img');
// 创建canvas
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
// image:图片对象
var width = canvas.width = image.width;
var height = canvas.height = image.height;
// 在canvas中绘制图片
context.drawImage(image, 0, 0, width, height);
// 提取图片颜色数据
var imageData = context.getImageData(0, 0, width, height);
    // 图片采样像素步进 1:一个像素为单位,10:十个像素为单位
var quality = 10;
var pixelCount = width * height;
var pixelArray = [];
for (var i = 0, offset, r, g, b, a; i < pixelCount; i = i + quality) {
    offset = i * 4;
    r = pixels[offset + 0];
    g = pixels[offset + 1];
    b = pixels[offset + 2];
    a = pixels[offset + 3];
    // 如果像素的透明度过低,则略过
    if (a >= 125) {
        if (!(r > 250 && g > 250 && b > 250)) {
            pixelArray.push([r, g, b]);
        }
    }
}

拿到颜色数据后,我们只需要通过算法去快速统计像素数据,从而得出图片中每个颜色的权重,此处有多种算法推荐(具体代码就不展开了,详情可看参考4):

  • Simple histogramming
  • Median Cut
  • k-means
  • Leptonica

最后我们取出最前面几个的色调信息作为下一步思路的参照色。(到此解决颜色关联的问题)

PS:庆幸我们处在一个开放的年代,github上有个优秀的图片色板提取库,我们只需按照说明引用该库就能快速提取颜色,详情可看参考5

【第二步:颜色对比】

在拿到的交互稿中,文字是#FFF纯白色,我们根据海报图片提取出来的颜色是随图而变,因此产生了2个小问题:

  • 如何避免底色和文字颜色过于接近,造成阅读困难

通过查阅知乎(详情可看参考1),根据作者的实验结果来看:文字和背景对比度在0.6以内,有较好的阅读体验。很好解决了颜色和文字过于接近的问题。

  • 如何避免图片融入底色中,造成视觉混淆

因为颜色就是从图片中提取出来的,所以有很搭概率会和图片的背景融为一体,看起来非常别扭:

(海报和背景主色相融)

大家先感受下RGB和HSV(HSB)色域的颜色调整变化:

  • 调整r、g、b中任意值,会造成颜色的色相变化
  • 调整h色相,会造成颜色的色相变化
  • 调整s饱和度,会造成颜色的灰度变化
  • 调整b(v)亮度,会造成颜色的明暗变化

根据对色域的属性调整试验 & 平时做APP开发的经验,我们发现:

  1. 对S饱和度、B(V)亮度的调整对色彩的影响会比较小;
  2. 为了兼顾到文字和背景色的反差,将原色值的B(V)亮度控制在15%~60%之间,可以确保良好的文字阅读体验;
  3. 为了区分主色调和背景色,通过调整饱和度可以得到良好的层次效果:
区间 表现 处理
<= 60% 颜色比较暗沉 +10%
> 60% < 85% 颜色舒适,但是会有边缘相融风险 + 2%
>= 85% 颜色过于鲜艳 -10%
(优化后,海报和背景主色产生关联层次)

在线体验地址:体验地址


参考:

1.【知乎 – 提高「可读性」,文本、背景色怎么选】

https://zhuanlan.zhihu.com/p/30018110

2.【维基百科 – HSL和HSV色彩空间】

https://zh.wikipedia.org/wiki/HSL%E5%92%8CHSV%E8%89%B2%E5%BD%A9%E7%A9%BA%E9%97%B4

3.【Leptonica – 图像分析算法】

http://www.leptonica.org/

4.【Github – 图像颜色采样算法】

https://github.com/mattnedrich/palette-maker

5.【Github – 图像颜色提取库】

https://github.com/lokesh/color-thief