2

我想知道如何将 RGB 值映射到 xy 坐标。例如,在某些应用程序中,我看到在该圆圈内移动光标会均匀地改变 rgb 值的圆圈。

就我而言,我有一个正方形区域,我想将该区域内的 xy 坐标映射到 rgb 值。我只希望 RGB 值在 [0, 255] 范围内,因为 xy 区域可以说 x 和 y 的值在 [0, 100] 范围内。还期望颜色逐渐变化,例如 (1,1) 可能是 (255, 0, 0) 并且 xy 到 (1,2) 的变化将导致类似的 rgb (254, 1, 0) 而不是完全不同的颜色(129、244、65)

有人可以告诉我这背后的数学吗?更好的是,一些c代码?

4

2 回答 2

2

我会从矩形转换为极坐标并使用HSL 或 HSV 颜色而不是 RGB 颜色。

它会自然平滑,您可以在 URL 处查看 HSL/HSV 图形(圆形图形)(请参阅平滑过渡)。一旦您转换了那些您应该能够通过搜索自行计算出的 x/y 值,结果值应该能够很容易地索引到色调颜色中,以获得平滑的过渡效果。

至于 C 代码,只是基本的数学运算是直截了当的,但颜色的实际设置取决于您编写 C 代码的平台,您尚未披露,或者更好的是,使用适当的标签指定,所以此处的相应开发人员可以看到它。

这是 C 中的 HSV -> RGB 转换算法

于 2015-03-26T22:11:29.143 回答
1

RGB 值可以按分量线性组合以创建渐变效果。假设您想从一种颜色传递(r1, g1, b1)到另一种颜色(r2, g2, b2)。RGB 渐变中的所有中间颜色都是((1-a)*r1 + a*r2, (1-a)*g1 + a*g2, (1-a)*b1 + a*b2)a从 0 到 1 不等。

要计算沿从点到点p=(x,y)的线性渐变的每个点的颜色,您将计算 和 的点积,然后将其除以 的范数和 的范数,并将值钳制在区间内。p1=(x1,y1)p2=(x2,y2)p1 pp1 p2p1 p2p1 p[0,1]

对于圆心c和半径为 的圆上的径向渐变rad,您将计算a = distance(p, c) / r并钳制为[0, 1]

出现哪些中间颜色取决于所使用的颜色空间(RGB、HSV、HSL 等)(仍按分量进行插值。)请参阅http://howaboutanorange.com/blog/2011/08/10/color_interpolation/

示例代码(伪代码,未经测试):

struct rgb_color {
    float r, g, b;
};
struct vec {
    float x, y;
};

// Color at point p, for a linear RGB gradient from point a (with color a_col) to b (with color b_col)    
rgb_color linear_gradient(vec p, vec a, rgb_color a_col, vec b, rgb_color b_col) {
    vec ab = { b.x - a.x, b.y - a.y };
    vec ap = { p.x - a.x, p.y - a.y };
    float ab_norm = sqrt(ab.x*ab.x + ab.y*ab.y);
    float ap_norm = sqrt(ap.x*ap.x + ap.y*ap.y);

    float dot = ab.x*ap.x + ab.y*ap.y;
    k = dot / (ab_norm * ap_norm);
    if(k < 0.0) k = 0.0;
    else if(k > 1.0) k = 1.0;

    float r = (1.0-k)*a_col.r + k*b_col.r;
    float g = (1.0-k)*a_col.g + k*b_col.g;
    float b = (1.0-k)*a_col.b + k*b_col.b;
    return { r, g, b };
}

// Color at point p, for a radial RGB gradient from for circle with center c (with color c_col), radius, and color outer_col outside the circle.
rgb_color radial_gradient(vec p, rgb_color c_col, vec c, float radius, rgb_color outer_col) {
    vec pc = { c.x - p.x, c.y - p.y };
    float pc_norm = sqrt(pc.x*pc.x + pc.y*pc.y);

    float k = pc_norm / radius;
    if(k < 0.0) k = 0.0;
    else if(k > 1.0) k = 1.0;

    float r = (1.0-k)*c_col.r + k*outer_col.r;
    float g = (1.0-k)*c_col.g + k*outer_col.g;
    float b = (1.0-k)*c_col.b + k*outer_col.b;
    return { r, g, b };
}
于 2015-03-26T22:14:21.010 回答