2016-05-18 00:00:00

Adobe Kuler的色盘算法

Adobe Kuler是Adobe提供的著名调色工具,提供强大的色盘拾色,以及近十种分组拾色规则和众多的颜色预设等功能.

Kuler是旧称呼,实际上早在多年前Adobe Kuler已经被改名为Adobe Color,但Kuler仍旧被大多数用户所沿用

Kuler官网提供的是网页版Kuler,另外,在AE,AI,PS等软件中,Adobe提供了名为CEP的HTML5环境来提供一些Adobe本身无法提供的功能,CEP的一个重要作用就是提供内置Kuler,以AE为例,下图即为内置Kuler

这里略微提一点,内置Kuler其实就是网页版Kuler,CEP访问网页版Kuler时带上了软件的标志,当这些标志被识别为PS,AI,AE等等时,便会返回类似移动网页的Kuler,这便是内置Kuler的实质.

但是,因为众所周知的网络原因,国内是不能流畅访问Kuler这个强大工具

为什么要手动实现色盘?

手动实现色盘,是为了提供能够快速启动的调色工具

Adobe提供的开发者环境有巨大的问题,其中一个不可忽视的就是:它根本没有根据点获取对应坐标的图片像素这一方法.

除非愿意忍受将图片的所有坐标与对应RGB值直接保存到产品中(最后存出来体积有1M),否则必须手动将Kuler的色盘实现出来,这样我们可以直接从点击的坐标算出对应的RGB值.

Kuler色盘的分析

Kuler官网中的图片是经过缩小了的,原图为1500*1500

对设计敏感的人可以敏锐地发觉,Kuler色轮实际上只是一个360*100矩形的极坐标映射,以长(360)为角度,以宽(100)为长度画出的一个圆形.因此,应当查询一些参数有角度的基础色彩转换算法,最终查到了HSV HSL 和 CMYK

HSV

这篇博文详细地介绍了HSV的算法.注意,原文中HSL的说法是错误的,HSV与HSB是同种色彩空间的不同称呼,HSL则和它们有所不同,原文中使用的是HSV而不是HSL的.

但是,HSV画出来的只是一个以红(Red),绿(Green)和蓝(Blue)三种颜色为主色的色盘

上图为Mac中系统拾色器中的色盘,使用的就是HSV色彩空间,很明显与Kuler色盘相差极大.(吐槽,不止两三位玩后期的朋友对我说这俩没差别)

HSL

HSL目前市面上没有现成的圆盘,因此先利用Canvas画一个看看

最终结果仍然不好

CMYK

最后想到了CMYK色彩空间, 因为某度的贴吧压图压绿的问题,我记住了CMYK这个东西,同样画一下CMYK圆盘

最终效果比较类似于Kuler,但是中心点是黑色的--没错,CMYK转RGB的算法描述中,确实是半径越小,RGB值越趋近[0,0,0]

分析

三种色彩空间全部失败, 我另外还查询了例如色谱,七色谱等关键字,仍然没有找到与Kuler类似的.因此可以下个结论,Kuler的色盘完全是Adobe自己独有的,完全没有其他任何工具使用了Kuler

与三种色彩空间做了对比,加上那名国外MotionDesigner的无心之语, 我发现,似乎Kuler色盘只是将HSV色盘的多种颜色重新分配了不同的角度.

这个发现过程可以说是十分巧合的,但是,没有之前几个小时的研究色彩空间以及canvas手动绘图, 我肯定无法发现这一点.

因此,最后的工作便是重新映射色彩的角度范围

重映射

最终实现的算法如下:

//h为角度,s为长度
colorPicker.prototype.CoreGetColorFromPoint = function(h,s){
    var i;

    var f, p, q, t;
    var r=1,g=1,b=1;
    var v = 1;
    if( s == 0 ) {
        v = Math.floor(v*255);
        return [v,v,v];
        }
    var condition;
    var tempI

    if(h<45 && h>=0){
        i = 0;      
        f = h/90; 
    }else if(h<120 && h>=45){ 
        i = 1 
        f = (h-45)/(120-45); 
    }else if(h<180 && h>=120){ 
        i = 2 
        f = (h-120)/(180-120); 
    }else if(h<220 && h>=180){ 
        i = 3 
        f = (h-180)/(220-180); 
    }else if(h<275 && h>=220){ 
        i = 4  
        f = (h-220)/(275-220); 
    }else if(h<320 && h>=275){ 
        i = 5  
        f = (h-275)/(320-275);
    }else if(h<360 && h>=320){ 
        i = 6
        f = (h-320)/(360-320)
    }

    p =  1 - s ;
    q =  1 - s * f ;
    t =  1 - s * ( 1 - f );

    switch( i ) {
        case 0:r = v;g = t;b = p;break;        
        case 1:r = v;g = 0.5+t/2;b = p;break;   
        case 2:r = q;g = v;b = p;break;     
        case 3:r = p;g = v;b = t;break;      
        case 4:r = p;g = q;b = v;break;        
        case 5:r = t;g = p;b = v;break;         
        case 6:r = v;g = p;b = q;break;         

    }
    return [r,g,b];
}

上面switch语句中分出了7种角度范围,每种范围对应的rgb计算方式都不一样,我通过二十多组输入和输出数据,最终确定下来所有的rgb计算方式.其中,橙色是最有意思的,它的RGB为(255,127,0),rgb计算方式与其他的完全不一样

当成功实现了Kuler的色盘算法后,可以认为它是一个HSV转RGB算法的变种

这个算法的实现过程是十分有趣的,有趣既在发现了Canvas中直接对imageData赋值时开始的角度竟然不是0而是-30度,也在于发现了Kuler色盘的一个小BUG: 有大约10度左右的像素,全部为相同的绿色

此BUG十分像青色转绿色时没有颜色过渡而直接变成绿色,然后Adobe为了掩盖这个错误而使用了模糊.作为一个著名调色产品,Adobe竟然从未尝试修复此问题,难道过去十几年没有一个人发现这个BUG?

引申

上面的算法实际上是根据点获得颜色, 作为一款拾色器,实际还有根据颜色获得点的这样的需求.作为色盘算法的逆过程,具体的算法在此就不赘述了

最终利用色盘算法实现的拾色器开源在我的Github上,名为AdobeColorPicker

另外,在搜索色盘资料的时候,无意间发现了无依赖地更改纯色PNG图片的颜色的办法,实在是意外之喜

本文链接:https://smallpath.me/post/Adobe Kuler的色盘算法

-- EOF --