Sort Colors (Objective-C)
Asked Answered
C

2

10

I'm doing this sort of thing:

- (NSArray*)colors {
    float divisor = .3333;
    NSMutableArray *retVal = [NSMutableArray array];
    for (float one=0; one <= 1.0f; one += divisor) {
        for (float two = 0; two <= 1.0f; two += divisor) {
            for (float three = 0; three <= 1.0f; three += divisor) {
                UIColor *color = [UIColor colorWithRed:one green:two blue:three alpha:.5];
                // also bad
                // UIColor *color = [UIColor colorWithHue:one saturation:two brightness:three alpha:.5];
                [retVal addObject:color];
            }
        }
    }
    return retVal;
}

and, as I suspected, the colors come out horribly out of order (to the eye). The reds are not with the reds, purples not with the purples, etc.

Is there no easy way to create a list of diverse colors, nicely grouped according to human criteria like, "that looks blue?"

Conference answered 21/12, 2011 at 4:20 Comment(1)
No you should make that an answer :)Electropositive
C
10

This worked quite well. It will NOT help the fact that you have a lot of repeated colors. See below:

NSArray *sorted = [[dict allValues] sortedArrayUsingComparator:^NSComparisonResult(UIColor* obj1, UIColor* obj2) {
    float hue, saturation, brightness, alpha;
    [obj1 getHue:&hue saturation:&saturation brightness:&brightness alpha:&alpha];
    float hue2, saturation2, brightness2, alpha2;
    [obj2 getHue:&hue2 saturation:&saturation2 brightness:&brightness2 alpha:&alpha2];
    if (hue < hue2)
        return NSOrderedAscending;
    else if (hue > hue2)
        return NSOrderedDescending;

    if (saturation < saturation2)
        return NSOrderedAscending;
    else if (saturation > saturation2)
        return NSOrderedDescending;

    if (brightness < brightness2)
        return NSOrderedAscending;
    else if (brightness > brightness2)
        return NSOrderedDescending;

    return NSOrderedSame;
}];

You can access the components (HSBA) like this in iOS 4.x:

    CGFloat *components = (CGFloat *)CGColorGetComponents([color CGColor]);
    float hue = components[0];
    float saturation = components[1]; // etc. etc.

To avoid repeating colors: you can put the elements in an NSMutableDictionary, keyed on something like their hue-saturation-brightness (each rounded to the nearest .10)... then you get the array from THAT, and then sort.

Conference answered 21/12, 2011 at 5:4 Comment(1)
float values should be double, otherwise it gives an EXC_BAD_ACCESS error.Thud
C
3

I think using [UIColor colorWithHue:saturation: brightness: alpha:] is your best bet. If you fix saturation, brightness and alpha and just use Hue you'll get all the colours in order.

Check out the wiki for HSB for more information.

for (float hsb = 0; hsb <= 1.0f; hsb += divisor) {
             UIColor *color = [UIColor colorWithHue:hsb saturation:1.0f brightness:1.0f alpha:.5f];
            [retVal addObject:color];
}
Calumet answered 21/12, 2011 at 4:31 Comment(2)
If you look at the hsb colour information, you would only need one loop to get the full colour spectrum.Calumet
Wow, if you cycle through saturations on the outer loop, you get a coherent looking thing. Nice! +1Conference

© 2022 - 2024 — McMap. All rights reserved.