mootymoots
mootymoots

Reputation: 4575

UIColor/RGB Way to go from X Color to Y Color

I wonder if anyone could suggest the best way to go from one color to another in a gradual process.

So - I have a text box which I have a text limit on. I'd like to have the text start at white, but be red by the time it gets to the max text limit.

Is there an easy way to do this? I'm unsure really where to start...

Upvotes: 2

Views: 1440

Answers (4)

Jonathan Ellis
Jonathan Ellis

Reputation: 5479

Here is a category for UIColor that can be used to linearly interpolate between two UIColors in either RGB or HSV:

@implementation UIColor (Interpolate)

+ (UIColor *)interpolateRGBColorFrom:(UIColor *)start to:(UIColor *)end withFraction:(float)f {

    f = MAX(0, f);
    f = MIN(1, f);

    const CGFloat *c1 = CGColorGetComponents(start.CGColor);
    const CGFloat *c2 = CGColorGetComponents(end.CGColor);

    CGFloat r = c1[0] + (c2[0] - c1[0]) * f;
    CGFloat g = c1[1] + (c2[1] - c1[1]) * f;
    CGFloat b = c1[2] + (c2[2] - c1[2]) * f;
    CGFloat a = c1[3] + (c2[3] - c1[3]) * f;

    return [UIColor colorWithRed:r green:g blue:b alpha:a];
}

+ (UIColor *)interpolateHSVColorFrom:(UIColor *)start to:(UIColor *)end withFraction:(float)f {

    f = MAX(0, f);
    f = MIN(1, f);

    CGFloat h1,s1,v1,a1;
    [start getHue:&h1 saturation:&s1 brightness:&v1 alpha:&a1];

    CGFloat h2,s2,v2,a2;
    [end getHue:&h2 saturation:&s2 brightness:&v2 alpha:&a2];

    CGFloat h = h1 + (h2 - h1) * f;
    CGFloat s = s1 + (s2 - s1) * f;
    CGFloat v = v1 + (v2 - v1) * f;
    CGFloat a = a1 + (a2 - a1) * f;

    return [UIColor colorWithHue:h saturation:s brightness:v alpha:a];
}

@end

Upvotes: 3

ergosys
ergosys

Reputation: 49049

You need to convert your end-point colors to a color space where one of the parameters is intensity so you can keep this constant. @jvenema's suggestion is decent. Then treat the other two values as two points in 2-dimensions, and find the correct point along the line connecting them according to the position of your slider. Convert the resulting color back to RGB for display.

You might also try NSColor's blendedColorWithFraction:ofColor:, depending on how it blends, it might do what you want.

Upvotes: 0

Notinlist
Notinlist

Reputation: 16650

Do it with simple linear interpolation. Float is for precision.

float dr = (r_end - r_start) / (text_limit*1.0 - 1);
float dg = (g_end - g_start) / (text_limit*1.0 - 1);
float db = (b_end - b_start) / (text_limit*1.0 - 1);
int x = start_x;
for(int i=0; i<text_size; ++i)
{
    PutOutColoredChar(x,start_y , text[i], (int)(r_start+(dr*i)) , ((int)g_start+(dg*i)), (int)(g_start+(db*i)) );
    x += WithOfChar(text[i]);
}

I am not a color expert but this does not used to be ugly for me.

Upvotes: 0

Jerod Venema
Jerod Venema

Reputation: 44642

Use HSL or HSV rather than RGB. They have various properties that go from 0 to 100 percent, so you can scale them nicely in code.

Here's the objective c reference.

Upvotes: 1

Related Questions