HSV是个好东西,比RGB来的直观一点,也适合人们调色。可惜对机器来说不够简单,尤其是网上大多数HSV与RGB互转的麻烦公式(被人为了性能简化过)让人摸不着头脑,现在着重介绍两个方面:
- HSV中的hue到底是什么,为什么这么漂亮,有没有更好的方案
- HSV转RGB公式的真面目。
HSV里的H
HSV里的H是hue,意为色相,在HSV三维中起到了改变颜色的作用。
看这很漂亮,但它怎么来的呢,先驱们是怎么想到这种能把所有颜色都表示出来的方法?
我一开始以为很复杂,后来一番研究后才发现其实异常简单,先人们为了把各种颜色都表示出来,采用了一种极其弱智的办法(误),将红,黄,绿,青,蓝,品红6种颜色均匀放在一条轴上(红在头和末尾都有出现,故一共七个点)。
红———-黄————绿————-青————蓝———–品红————-红
然后极其简单的采用线性插值的办法画出了色相!!!就是这么简单!
下面这张图能直白的表示:
至此hue应该被介绍的很清楚了。
但作为有创造力的年轻人我怎么会就此收手!(误
在我看来先驱们创造的hue还有点缺陷,就是黄青还有品红似乎比红黄蓝看起来要窄一点,有的时候看起来不那么均匀。
那么有没有更好的解决方案呢???
我企图用了两种方法来产生hue:
- 红黄蓝三个点线性插值
- 红黄蓝三个点用正弦插值
然后用shadertoy画出来了,然而实际上的效果奇丑(真的奇丑)。。。。。。。
红黄蓝三个点线性插值:
红黄蓝三个点用正弦插值
为什么这么丑呢?后来分析是因为用RGB插值的缘故,所以肯定没有RGB中两维全满的情况,因此也就不可能出现消减三原色黄青品红中的任意一个。(逃
HSV转RGB公式的真面目
说完了hue的基本组成原理,我们看HSV转RGB公式就很轻松了。
HSV中的SV:
S是饱和度,S越高颜色掺杂的白越少。
V是明亮度,与S一样也是控制白色多少的。但!它的优先权比S更大,它控制着S能掺杂的白的灰度。
说了这些大家可能也是没懂,一张图表示一下:
重点看左边轴,之所以说V的优先级更大,就是因为当V是0的时候,S再怎么蹦跶也都是黑色。
V绝对的影响了上界,S影响了下界。
这样一看,HSV转RGB应该很简单了,看着图就能写出来。
我也不贴完整代码了,我就贴一个经常用到的,在程序中经常要我们生成多个不一样的颜色值,我们也不可能随机生成,那样容易重复,也不好看。一块现成的js代码:
function hsv(i,total){
//hsv
var rgb = "";
//I set the s and v to the highest and lowest
var hue = (6 * (i / total.toFixed(1)));
var hue_int = Math.floor(hue);
var inc = Math.round((hue - hue_int) * 255);
switch (hue_int) {
case 0:
rgb = "#" + "FF" + zero_fill(inc) + "00";
break;
case 1:
rgb = "#" + zero_fill(255 - inc) + "FF" + "00";
break;
case 2:
rgb = "#" + "00" + "FF" + zero_fill(inc);
break;
case 3:
rgb = "#" + "00" + zero_fill(255 - inc) + "FF";
break;
case 4:
rgb = "#" + zero_fill(inc) + "00" + "FF";
break;
case 5:
rgb = "#" + "FF" + "00" + zero_fill(255 - inc);
break;
default:
console.log(hue + ',' + hue_int);
}
return rgb;
}
function zero_fill(num){
var result= Math.round(num).toString(16);
if (result.length < 2)
result="0"+result;
return result;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
给定一个目前值,一个最大值就能生成一个在hue’轴上对应的RGB值,我在我期末大作业和自己无聊做的小游戏(knocker.xyz)中都用到了这种方法(屡试不爽,真香)
<script>
(function(){
function setArticleH(btnReadmore,posi){
var winH = $(window).height();
var articleBox = $("div.article_content");
var artH = articleBox.height();
if(artH > winH*posi){
articleBox.css({
'height':winH*posi+'px',
'overflow':'hidden'
})
btnReadmore.click(function(){
articleBox.removeAttr("style");
$(this).parent().remove();
})
}else{
btnReadmore.parent().remove();
}
}
var btnReadmore = $("#btn-readmore");
if(btnReadmore.length>0){
if(currentUserName){
setArticleH(btnReadmore,3);
}else{
setArticleH(btnReadmore,1.2);
}
}
})()
</script>
</article>