为什么要做HSL转RGB的原因,设计不想多谈,仁者见仁智者见智。本文的价值,是希望能帮助需要的朋友少走弯路,仅此而已。
Microsoft Office支持的色彩模式有两种:RGB和HSL。HSL由于其直观性,是设计最为常用的色彩模式。在单一形状的颜色调整中,HSL可以直接在Office中操作,虽然比RGB多了一步切换,但也不是什么大事,习惯就无所谓。不过如果要进行批量改色,那么选择形状→填充→其他填充→自定义→修改RGB或HSL值,就显得繁琐无比。而目前支持批量修改颜色的插件几乎没有或者功能不全,无法达到设计的目的,于是设计萌生了自己做一个伪插件的念头。
图1 PPT中每次操作,让批量改色无比繁琐
首先,RGB和HSL都是计算机成熟的色彩模式,那么网上肯定有相关的实现方式。于是在维基百科上,看到了这条百科:http://zh.wikipedia.org/wiki/HSL和HSV色彩空间
【从HSL到RGB的转换】(转换公式来自维基百科)
给定HSL空间中的(h,s,l)值定义的一个颜色,带有h在指示色相角度的值域[0,360)中,分别表示饱和度和亮度的s和l在值域[0,1]中,相应在RGB空间中的(r,g,b)三原色,带有分别对应于红色、绿色和蓝色的r,g和b也在值域[0,1]中,它们可计算为:
首先,如果s=0,则结果的颜色是非彩色的、或灰色的。在这个特殊情况,r,g和b都等于l。注意h的值在这种情况下是未定义的。
当s≠0的时候,可以使用下列过程:
刚开始看这段,设计这个编程和EXCEL菜鸟也着实头疼,但既然都是计算,EXCEL肯定是能做的,于是设计硬着头皮在EXCEL中开始弄数据。
图2 单元格填入文字和初始数字
开始分析公式,“给定HSL空间中的(h,s,l)值定义的一个颜色,带有h在指示色相角度的值域[0,360)中,分别表示饱和度和亮度的s和l在值域[0,1]中,相应在RGB空间中的(r,g,b)三原色,带有分别对应于红色、绿色和蓝色的r,g和b也在值域[0,1]中”。要注意的是,公式里的h/s/l都是转换后的,h值域是[0,360],s和l的值域是[0,1]。这句话很重要,设计刚开始也是犯了不少错误,就是没搞清这里的值域。那怎么转换值域呢,H要除以360(这里有坑,最后谈),S和L要分别除以255。如图2中,HSL(0,255,128)转换值域后是(0,1,0.5)。这也是为什么维基上的公式,要判断L跟1/2的关系的问题所在。
继续分析:“首先,如果s=0,则结果的颜色是非彩色的、或灰色的。在这个特殊情况,r,g和b都等于l”。用EXCEL理解的话来说是这样的:如果代表饱和度S的单元格C3=0,那么F3(R)、G3(G)、H3(B)都等于D3,否则继续判断。由于最后还要给G3、H3复制公式,所以锁定D3。因此F3(R)单元格的第一步公式是:if($C$3=0,$D$3,)。这个条件判断先留着。
然后继续分析饱和度s≠0的情况。
注意,这里的l是转换过值域的亮度,所以我们需要先把D3除以255,再来跟0.5相比较。在K3输入q的公式:=IF(D3/255<0.5,D3/255*(1+C3/255),D3/255+C3/255-D3/255*C3/255)
图3 在K3输入q的公式
接下来看p
在K4输入p的公式:=2*D3/255-K3
图4 在K4输入p的公式
继续看
在K5输入hk的公式:=B3/360
在K6输入tR的公式:=K5+1/3
在K7输入tG的公式:=K5
在K8输入tB的公式:=K5-1/3
图5 在K5-K8分别输入hk、tR、tG、tB的公式
继续,难点来了,这里tC的含义
这里的tc是指tR、tG、tB的任意一个,三者都满足这个条件公式。
K9单元格输入公式:=IF(K6<0,K6+1,IF(K6>1,K6-1,K6))
K10单元格输入公式:=IF(K7<0,K7+1,IF(K7>1,K7-1,K7))
K11单元格输入公式:=IF(K8<0,K8+1,IF(K8>1,K8-1,K8))
图5 这样我们就得到了分别对应tR、tG、tB的三个tC值
接下来看公式的最后一步
这一步分别把三种tC代入进去,就分别得到了R、G、B的值。所以这一步的公式,我们先做R的。此时再加三个单元格nR、nG、nB作为过渡,方便后续引用。
根据上面的公式,nR(即K12单元格)在S≠0时,EXCEL的公式应该是这样的
=IF(K9<1/6,K4+(K3-K4)*6*K9,IF(AND(K9<1/2,K9>=1/6),K3,IF(AND(K9<2/3,K9>=1/2),K4+(K3-K4)*6*(2/3-K9),K4)))
因K12对应的nR在给nG、nB复制公式的时候,K9要分别变为K10、K11,而其他不变。所以公式应该给q、p也就是K3、K4加锁定单元格。
=IF(K9<1/6,$K$4+($K$3-$K$4)*6*K9,IF(AND(K9<1/2,K9>=1/6),$K$3,IF(AND(K9<2/3,K9>=1/2),$K$4+($K$3-$K$4)*6*(2/3-K9),$K$4)))
图6 把公式复制到nR后面的单元格里
此时得到的nR的值域为[0,1],所以在需要转换回[0,255]的值域。
所以nR的公式最后再乘以255。
=IF(K9<1/6,$K$4+($K$3-$K$4)*6*K9,IF(AND(K9<1/2,K9>=1/6),$K$3,IF(AND(K9<2/3,K9>=1/2),$K$4+($K$3-$K$4)*6*(2/3-K9),$K$4)))*255
图7 公式乘255转换回[0,255]的值域
把nR的公式复制给nG、nB单元格,这应该都会,按住控制柄的小黑点,拖动。
图8 把公式复制给nG、nB
然后,因R单元格里的数值之前已经有一个当s=0的判断:=if($C3=0,$D$3,)
因此,R的新公式需要把这个判断加上。此时公式变为:
F3(R)单元格的公式是:=if($C3=0,$D$3,K12)
G3(G)单元格的公式是:=if($C3=0,$D$3,K13)
H3(B)单元格的公式是:=if($C3=0,$D$3,K14)
图9 公式填入F3、G3、H3单元格
至此,从维基百科获取的公式就转换为EXCEL里了。但这里有一个问题。HSL:0,255,128是标准的红色,它的RG