我想写一个函数来改变RGB colored颜色 的色调.具体来说,我在iOS应用程序中使用它,但数学是通用的.

下图显示了R、G和B值如何随色调变化.

不同色调的RGB值图表

现在看来,编写一个函数来改变色调应该是一件相对简单的事情,而不需要对不同的 colored颜色 格式进行任何令人讨厌的转换,这会带来更多的错误(如果继续对 colored颜色 进行小的改变,这可能是一个问题),我怀疑计算成本会更高.

以下是我到目前为止所做的工作.如果你从纯黄色、青色或洋红转向,它的效果非常好,但在其他地方,它会变得有点蓬松.

Color4f ShiftHue(Color4f c, float d) {
    if (d==0) {
        return c;
    }
    while (d<0) {
        d+=1;
    }

    d *= 3;

    float original[] = {c.red, c.green, c.blue};
    float returned[] = {c.red, c.green, c.blue};

    // big shifts
    for (int i=0; i<3; i++) {
        returned[i] = original[(i+((int) d))%3];
    }
    d -= (float) ((int) d);
    original[0] = returned[0];
    original[1] = returned[1];
    original[2] = returned[2];

    float lower = MIN(MIN(c.red, c.green), c.blue);
    float upper = MAX(MAX(c.red, c.green), c.blue);

    float spread = upper - lower;
    float shift  = spread * d * 2;

    // little shift
    for (int i = 0; i < 3; ++i) {
        // if middle value
        if (original[(i+2)%3]==upper && original[(i+1)%3]==lower) {
            returned[i] -= shift;
            if (returned[i]<lower) {
                returned[(i+1)%3] += lower - returned[i];
                returned[i]=lower;
            } else
                if (returned[i]>upper) {
                    returned[(i+2)%3] -= returned[i] - upper;
                    returned[i]=upper;
                }
            break;
        }
    }

    return Color4fMake(returned[0], returned[1], returned[2], c.alpha);
}

我知道你可以用UIColors来做这件事,然后用这样的东西来改变色调:

CGFloat hue;
CGFloat sat;
CGFloat bri;
[[UIColor colorWithRed:parent.color.red green:parent.color.green blue:parent.color.blue alpha:1] getHue:&hue saturation:&sat brightness:&bri alpha:nil];
hue -= .03;
if (hue<0) {
    hue+=1;
}
UIColor *tempColor = [UIColor colorWithHue:hue saturation:sat brightness:bri alpha:1];
const float* components= CGColorGetComponents(tempColor.CGColor);
color = Color4fMake(components[0], components[1], components[2], 1);

但我对此并不着迷,因为它只在iOS 5中起作用,在分配大量彩色对象和从RGB转换到HSB再转换回来之间,似乎有点过头了.

我可能最终会使用一个查找表或预先计算应用程序中的 colored颜色 ,但我真的很好奇是否有办法让我的代码正常工作.谢谢

推荐答案

Edit per comment changed "are all" to "can be linearly approximated by".
Edit 2 adding offsets.


基本上,你想要的步骤是

RBG->HSV->Update hue->RGB

由于这can be approximated by个线性矩阵变换(即,它们是关联的),您可以在一个步骤中执行它,而不会出现任何令人讨厌的转换或精度损失.您只需将变换矩阵彼此相乘,并使用它来变换 colored颜色 .

这里有一个快速的步骤

这里是C++代码(带饱和度和值转换被删除):

Color TransformH(
    const Color &in,  // color to transform
    float H
)
{
  float U = cos(H*M_PI/180);
  float W = sin(H*M_PI/180);

  Color ret;
  ret.r = (.299+.701*U+.168*W)*in.r
    + (.587-.587*U+.330*W)*in.g
    + (.114-.114*U-.497*W)*in.b;
  ret.g = (.299-.299*U-.328*W)*in.r
    + (.587+.413*U+.035*W)*in.g
    + (.114-.114*U+.292*W)*in.b;
  ret.b = (.299-.3*U+1.25*W)*in.r
    + (.587-.588*U-1.05*W)*in.g
    + (.114+.886*U-.203*W)*in.b;
  return ret;
}

Objective-c相关问答推荐

在哪里可以找到 iPad 示例代码

UIAlertController:supportedInterfaceOrientations 被递归调用

防止同时多个按钮

UISearchDisplayController 没有结果tableView?

自动布局和按下时隐藏底栏

在Objective C中迭代枚举?

反编译 Objective-C 库

lldb 无法打印变量值并显示错误:对 'id' 的引用不明确

在 iPhone 应用程序中使用 RestKit 的最佳方式

如何在 iPhone 上画出讲话泡泡?

从 UIPageViewController 中移除视图控制器

委托如何在 Objective-C 中工作?

Objective-C 实例变量?

如何在 UIImageView 中显示 base64 图像?

如何在 xcode 项目中启用/禁用 ARC?

如何更改标签栏上的非活动图标/文本 colored颜色 ?

iPhone:如何确定线程是否是主线程?

iPhone SDK:如何在视图中播放视频?而不是全屏

目标 C:读取文本文件

@package 指令在 Objective-C 中的作用是什么?