如何绘制一个好的RGB颜色地图?

12

我正在尝试绘制一个完整的RGB颜色映射,最终允许用户通过在视觉映射的任何点进行点击来选择颜色。我的当前代码如下:

- (void)drawRect:(CGRect)rect
{
    CGContextRef c = UIGraphicsGetCurrentContext();

    for (float x=0; x<320; x++) {
        for (float y=0; y<416; y++) {

            float r = x / 320;
            float g = y / 416;
            float b = (y < 208) ? y / 208 : (416 - y) / 208;

            CGContextSetRGBFillColor(c, r, g, b, 1.0);
            CGContextFillRect(c, CGRectMake(x, y, 1, 1));

        }
    }
}
结果还不错,但我还不满意。 光谱缺少亮色,包括白色。 原因很明显:红色,绿色和蓝色永远不会同时达到1.0。 结果颜色映射的屏幕截图 你有什么建议来改进这幅地图,使它能代表RGB颜色空间的完整光谱吗?
感谢您提供的所有输入!
更新:
根据Josh Caswell的建议,我使用了HSB颜色空间和以下代码:
- (void)drawRect:(CGRect)rect
{
    CGContextRef c = UIGraphicsGetCurrentContext();

    int size = 20;

    for (float x=0; x<320; x+=size) {

        float s = x < 160 ? 1       : (320 - x) / 160;
        float b = x < 160 ? x / 160 : 1;

        for (float y=0; y<416; y+=size) {

            float h = y / 416;

            [[UIColor colorWithHue:h saturation:s brightness:b alpha:1.0] setFill];
            CGContextFillRect(c, CGRectMake(x, y, size, size));
        }
    }
}

这导致了以下输出,非常适合我的需要。

使用HSB颜色空间的结果

感谢所有的输入!


1
感谢分享代码,做得非常好! - jscs
2
最终结果确实很美。我希望没有人需要灰色;你可能想在右侧做一系列灰度。 - Mark Ransom
那是一个很好的补充。谢谢。 - Daniel Bleisteiner
3个回答

7
您正在尝试将三维对象展平到一个平面上。RGB颜色基本上代表了立方体内的一个点。将RGB立方体映射到表面上在数学上可能是可行的,但对于这种颜色选择目的可能不是特别直观的。
您可以尝试使用HSB,它更像是一个带有色调角度的圆柱体。您可以“展开”圆柱体,将色调映射到y坐标,然后沿x轴变化亮度或饱和度 - 您可以进行一些简单的测试来决定哪个组件对您的应用程序更重要。如果您觉得需要包括第三个组件,则可以使用双指滑动。
饱和度在X轴上的HSB:
HSB map; S on X axis 亮度在X轴上的HSB:
HSB map; B on X axis 饱和度和亮度相等且都在X轴上:
HSB map; S=B on X axis 如果您需要白色,当S = 0%,B = 100%时发生,您可以将其粘贴在一侧,或尝试S = 1 / B。

将滑动手势用于更改第三个组件是一个不错的想法...但我希望尽可能保持简单。因此,我将坚持使用平面表示,不需要任何用户交互。虽然HSB可能更容易被压平...谢谢。 - Daniel Bleisteiner
HSB更容易处理。我已经从左到中提高了亮度,然后从中到右降低了饱和度。这导致了以下结果(方块大小为20px):http://cl.ly/1f0q0m043u3v1O2s1618 - 我会添加我的最终代码。 - Daniel Bleisteiner

2
我认为一种推导方法是这样的:
横向地,对于每个像素,选择一个 r g b 的比例,例如“0, 0, 1”。
从上到下绘制亮度从0到1的像素。
将每个像素推导为 pixel = brightness * (r,g,b)
在横向移动时,按如下方式迭代 R G B: 000,001,010,011,100,101,110,111 如果使用3个正弦计算,您可以使用方程实现此操作并同时处理插值。
这解决了白色和黑色问题,并为您提供了大量的颜色空间。如果您需要颜色空间中每个像素,您需要以不同的水平插值方式进行插值,并且需要8个控制点而不是2 ^ 8。

这是一个非常好的想法...使用sin()函数从0到1进行插值,并尝试水平地跨越整个光谱 - 感谢您的建议。我会尝试去适应它。 - Daniel Bleisteiner
1
我的当前结果看起来像这样:http://cl.ly/3v321G2m0V3o1c3n0n3c - 我会尝试使用HSB... - Daniel Bleisteiner
没意识到你已经实现了它。我简直不敢相信我的想法变得如此丑陋!感谢分享截图。 - Nektarios
这个想法并不差,但 HSB 只是做得更好 :) - Daniel Bleisteiner

2

您正在尝试在二维表面上表示三维颜色空间。很难找到一个单一的表面是足够的。

您需要进行两部分选择。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接