Изменить оттенок цвета RGB

Я пытаюсь написать функцию для изменения оттенка цвета RGB. В частности, я использую его в приложении для iOS, но математика универсальна.

На графике ниже показано, как значения R, G и B меняются в зависимости от оттенка.

Graph of RGB values across hues

Глядя на это, кажется, что было бы относительно просто написать функцию для сдвига оттенка без каких-либо неприятных преобразований в другой цветовой формат, который привел бы к большему количеству ошибок (что может быть проблемой, если продолжать применять небольшие сдвиги к цвет), и я подозреваю, что это будет более затратным с точки зрения вычислений.

Вот какие работы у меня есть. Он отлично работает, если вы переходите от чистого желтого, голубого или пурпурного, но в остальном он становится немного мягким в некоторых местах.

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, а затем обратно, это кажется излишним.

Я мог бы использовать таблицу поиска или предварительно вычислить цвета в своем приложении, но мне действительно любопытно, есть ли способ заставить мой код работать. Спасибо!

36
задан Anthony Mattox 14 December 2011 в 16:21
поделиться