2011-06-08 82 views
12

我试图绘制一个完整的RGB色彩地图,最终将允许用户通过点击该视觉地图在任何点上选择一种颜色。我目前的代码如下:如何绘制一个好的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。

Screenshot of the resulting color map

你有任何建议如何改善这种地图,它代表了RGB色彩空间的全谱?

感谢您的所有意见!

UPDATE:

至于建议由乔什 - 卡斯威尔我用过的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)); 
     } 
    } 
} 

这导致下面的输出很适合我需要。

Result using HSB color space

感谢所有输入!

+1

感谢分享代码;那真的很棒! – 2011-06-08 22:48:17

+2

最终的结果确实很美。我希望没有人需要灰色;你可能想沿着右边做一系列的灰色。 – 2011-06-09 17:08:37

+0

这是一个很好的补充。谢谢。 – 2011-06-09 19:26:40

回答

7

那么,你正试图将一个三维物体压平到一个平面上。 RGB颜色基本上代表了立方体内的一个点。将RGB固体映射到表面上可能在数学上是可能的,但对于此颜色选择目的可能不会特别直观。

使用HSB可能会有更好的运气,HSB更像是一个圆柱体,其周围的角度为角度。您可以“展开”柱面,将色调映射到y坐标,然后沿着x轴改变亮度或饱和度 - 您可以执行一些简单的测试来确定哪个组件对于您的应用更重要。如果您觉得有必要包含它,则可以使用双指轻扫作为第三个组件。

HSB与X轴饱和:
HSB map; S on X axis

随着X轴亮度:
HSB map; B on X axis

随着饱和度和亮度相等并且两个X轴:
HSB map; S=B on X axis

如果需要白色,当S = 0%,B = 100%,则可以任一粘条沿着一侧,或尝试S = 1/B时发生。

+0

滑动手势改变第三部分是一个不错的主意......但我想保持尽可能简单。所以我会坚持一个平面表示,不需要任何用户交互。虽然HSB可能更容易变平......谢谢。 – 2011-06-08 20:25:13

+0

HSB更容易处理。我将亮度从左侧提高到中央,然后从中心向右降低饱和度。结果如下(使用20px的正方形):http://cl.ly/1f0q0m043u3v1O2s1618 - 我将添加我的最终代码。 – 2011-06-08 22:07:12

+0

嘿,那看起来很漂亮!很高兴我能帮上忙。 – 2011-06-08 22:13:36

2

我认为一个方式来导出它是这样的:

水平方向上,对于每个像素,挑RGB的比例,例如“0,0,1”

绘制从顶部像素底部与“亮度”,从0变为1

派生每个像素pixel = brightness * (r,g,b)

当你去水平,迭代RGB为:

000, 001, 010, 011, 100, 101, 110, 111

如果您使用3个正弦计算,则可以使用方程来实现此目的,并同时处理插值。

这解决了你的白色和黑色的问题,并给你很多的色彩空间。如果您绝对需要色彩空间的每个像素,则需要以不同的方式进行水平插值,并且需要2^8而不是8个控制点。

+0

这是一个非常好的想法...使用sin()从0..1插值并尝试水平跨越整个频谱 - 感谢那个输入。我会尽力去适应它。 – 2011-06-08 20:28:17

+1

我现在的结果是这样的:http://cl.ly/3v321G2m0V3o1c3n0n3c - 我给HSB一试... – 2011-06-08 21:37:44

+0

不知道你已经实现了它。我无法相信我的想法出来多么丑陋!感谢分享截图。 – Nektarios 2011-06-15 17:36:38

2

您试图在二维表面上表示三维颜色空间。你不可能找到足够的单一表面。

您需要两部分选择。