本文介绍了RGB颜色的移位色调的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想写一个函数来移动RGB颜色的色调。具体来说,我在iOS应用中使用它,但数学是通用的。

I'm trying to write a function to shift the hue of an RGB color. Specifically I'm using it in an iOS app, but the math is universal.

下图显示了R,G和B值如何相对于hue。

The graph below shows how the R, G, and B values change with respect to the hue.

看看它似乎应该是一个相对简单的写一个函数来移动色相,而不做任何讨厌的转换到不同的颜色格式,这将导致更多的错误这可能是一个问题,如果继续应用小移位到一种颜色),我怀疑是更加计算昂贵。

Looking at that it seems like it should be a relatively simple to write a function to shift the hue without doing any nasty conversions to a different color format which would introduce more error (which could be an issue if continue applying small shifts to a color), and I suspect would be more computationally expensive.

这里是我到目前为止哪种工作。

Here is what I have so far which sort of works. It works perfectly if you're shifting from pure yellow or cyan or magenta but otherwise it gets a little squiffy in some places.

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做这个, :

I know you can do this with UIColors and shift the hue with something like this:

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,

but I'm not crazy about that as It only works in iOS 5, and between allocating a number of color objects and converting from RGB to HSB and then back it seems pretty overkill.

我可能最终会使用查找表或预先计算我的应用程序中的颜色,但我真的很好奇,如果有一种方法,使我的代码工作。非常感谢!

I might end up using a lookup table or pre-calculate the colors in my application, but I'm really curious if there's a way to make my code work. Thanks!

推荐答案

编辑

编辑2 添加偏移量。

您想要的是

RBG->HSV->Update hue->RGB

由于这些可以通过线性矩阵变换近似(即它们是关联的),所以可以在单个步骤没有任何讨厌的转换或精度的损失。

Since these can be approximated by linear matrix transforms (i.e. they are associative), you can perform it in a single step without any nasty conversion or loss of precision. You just multiple the transform matrices with each other, and use that to transform your colors.

这里有一个快速的步骤

There's a quick step by step here http://beesbuzz.biz/code/hsv_color_transforms.php

这里是C ++代码(删除了饱和度和值变换):

Here's the C++ code (With the saturation and value transforms removed):

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;
}

这篇关于RGB颜色的移位色调的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-18 00:28