如何在HSV色彩空间中插值色调值? [英] How to interpolate hue values in HSV colour space?

查看:258
本文介绍了如何在HSV色彩空间中插值色调值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在HSV颜色空间中的两种颜色之间进行插值,以产生平滑的颜色渐变。

I'm trying to interpolate between two colours in HSV colour space to produce a smooth colour gradient.

我使用线性插值,例如: p>

I'm using a linear interpolation, eg:

h = (1 - p) * h1 + p * h2
s = (1 - p) * s1 + p * s2
v = (1 - p) * v1 + p * v2

百分比,h1,h2,s1,s2,v1,v2是两种颜色的色调,饱和度和值分量)

(where p is the percentage, and h1, h2, s1, s2, v1, v2 are the hue, saturation and value components of the two colours)

和v,但不是h。由于色相分量是一个角度,因此计算需要计算出h1和h2之间的最短距离,然后在右方向(顺时针或逆时针)插值。

This produces a good result for s and v but not for h. As the hue component is an angle, the calculation needs to work out the shortest distance between h1 and h2 and then do the interpolation in the right direction (either clockwise or anti-clockwise).

我应该使用什么公式或算法?

What formula or algorithm should I use?

编辑:通过跟踪Jack的建议,我修改了我的JavaScript梯度函数,它工作得很好。对任何感兴趣的人,这是我结束了:

By following Jack's suggestions I modified my JavaScript gradient function and it works well. For anyone interested, here's what I ended up with:

// create gradient from yellow to red to black with 100 steps
var gradient = hsbGradient(100, [{h:0.14, s:0.5, b:1}, {h:0, s:1, b:1}, {h:0, s:1, b:0}]); 

function hsbGradient(steps, colours) {
  var parts = colours.length - 1;
  var gradient = new Array(steps);
  var gradientIndex = 0;
  var partSteps = Math.floor(steps / parts);
  var remainder = steps - (partSteps * parts);
  for (var col = 0; col < parts; col++) {
    // get colours
    var c1 = colours[col], 
        c2 = colours[col + 1];
    // determine clockwise and counter-clockwise distance between hues
    var distCCW = (c1.h >= c2.h) ? c1.h - c2.h : 1 + c1.h - c2.h;
        distCW = (c1.h >= c2.h) ? 1 + c2.h - c1.h : c2.h - c1.h;
     // ensure we get the right number of steps by adding remainder to final part
    if (col == parts - 1) partSteps += remainder; 
    // make gradient for this part
    for (var step = 0; step < partSteps; step ++) {
      var p = step / partSteps;
      // interpolate h, s, b
      var h = (distCW <= distCCW) ? c1.h + (distCW * p) : c1.h - (distCCW * p);
      if (h < 0) h = 1 + h;
      if (h > 1) h = h - 1;
      var s = (1 - p) * c1.s + p * c2.s;
      var b = (1 - p) * c1.b + p * c2.b;
      // add to gradient array
      gradient[gradientIndex] = {h:h, s:s, b:b};
      gradientIndex ++;
    }
  }
  return gradient;
}


推荐答案

out是从开始色调到结束色调的最短路径。这可以很容易地完成,因为色相值范围从0到255.

You should just need to find out which is the shortest path from starting hue to ending hue. This can be done easily since hue values range from 0 to 255.

您可以先从较高的色调中减去较低的色调,然后添加256到较低的色调,再次与交换操作数的差异。

You can first subtract the lower hue from the higher one, then add 256 to the lower one to check again the difference with swapped operands.

int maxCCW = higherHue - lowerHue;
int maxCW = (lowerHue+256) - higherHue;

所以你会得到两个值,大的一个决定你是顺时针还是逆时针。那么你必须找到一种方法使插值对色调的模256运算,所以如果你从 246 插入到 20 如果系数> = 0.5f ,您应该将hue重置为0(因为它达到256和 hue = hue%

So you'll obtain two values, the greater one decides if you should go clockwise or counterclockwise. Then you'll have to find a way to make the interpolation operate on modulo 256 of the hue, so if you are interpolating from 246 to 20 if the coefficient is >= 0.5f you should reset hue to 0 (since it reaches 256 and hue = hue%256 in any case).

实际上如果你不关心色调,而内插在0,但只是应用模运算符计算新的色调它应该工作。

Actually if you don't care about hue while interpolating over the 0 but just apply modulo operator after calculating the new hue it should work anyway.

这篇关于如何在HSV色彩空间中插值色调值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆