2011-01-15 25 views
18

I my application Passo il valore del colore RGB al server. La mia app utilizza i valori predefiniti di UIColor, come [UIColor grayColor], [UIColor redColor]. So che posso usare il codice seguente:Ottieni il valore RGB dai preset UIColor

const CGFloat *c = CGColorGetComponents(color.CGColor) 

ma solo per i colori che sono nello spazio di colore RBG, tuttavia, [UIColor grayColor] non lo è.

C'è un modo per ottenere valori RGB per i colori non RBG?

Grazie!

risposta

42

UIColor ha un metodo che fornisce i componenti RGB (-getRed:green:blue:alpha:) che funziona perfettamente su iOS 7 o versioni successive. Su iOS 6 e precedenti, questo metodo fallirà e restituirà NO se il colore non è in uno spazio colore RGB (come lo sarà per [UIColor grayColor]).

Per iOS 6 e precedenti, l'unico modo per cui so di farlo che funziona in tutti gli spazi colore è quello di creare un contesto bitmap di Core Graphics in uno spazio cromatico RGB e disegnarlo con il tuo colore. È quindi possibile leggere i valori RGB dalla bitmap risultante. Si noti che questo non funzionerà per determinati colori, come i colori del motivo (ad esempio [UIColor groupTableViewBackgroundColor]), che non hanno valori RGB accettabili.

- (void)getRGBComponents:(CGFloat [3])components forColor:(UIColor *)color { 
    CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB(); 
    unsigned char resultingPixel[4]; 
    CGContextRef context = CGBitmapContextCreate(&resultingPixel, 
               1, 
               1, 
               8, 
               4, 
               rgbColorSpace, 
               kCGImageAlphaNoneSkipLast); 
    CGContextSetFillColorWithColor(context, [color CGColor]); 
    CGContextFillRect(context, CGRectMake(0, 0, 1, 1)); 
    CGContextRelease(context); 
    CGColorSpaceRelease(rgbColorSpace); 

    for (int component = 0; component < 3; component++) { 
     components[component] = resultingPixel[component]/255.0f; 
    } 
} 

Si può usare qualcosa di simile:

CGFloat components[3]; 
    [self getRGBComponents:components forColor:[UIColor grayColor]]; 
    NSLog(@"%f %f %f", components[0], components[1], components[2]); 
+0

Grazie. Ho deciso che il mio problema non vale la soluzione, e sono passato a [UIColor colotWithRGB], ho ottenuto i valori RBG da http://foobarpig.com/iphone/uicolor-cheatsheet-color-list-conversion-from-and -to-rgb-values.html. – lstipakov

+0

Grazie. Il mio problema vale esattamente questa soluzione! –

+5

Nota: in iOS 5, 'UIColor' è' -getRed: green: blue: alpha' funziona solo per i colori che utilizzano lo spazio cromatico RGB. È rotto per i colori in scala di grigi. Hanno risolto questo problema in iOS 6? –

3

aggiunta alla risposta di Jesse, ecco come preservare alpha:

- (void)getRGBAComponents:(CGFloat [4])components forColor:(UIColor *)color { 
    CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB(); 
    unsigned char resultingPixel[4] = {0}; 
    CGContextRef context = CGBitmapContextCreate(&resultingPixel, 
               1, 
               1, 
               8, 
               4, 
               rgbColorSpace, 
               kCGImageAlphaPremultipliedLast); 
    CGContextSetFillColorWithColor(context, [color CGColor]); 
    CGContextFillRect(context, CGRectMake(0, 0, 1, 1)); 
    CGContextRelease(context); 
    CGColorSpaceRelease(rgbColorSpace); 

    CGFloat a = resultingPixel[3]/255.0; 
    CGFloat unpremultiply = (a != 0.0) ? 1.0/a/255.0 : 0.0; 
    for (int component = 0; component < 3; component++) { 
     components[component] = resultingPixel[component] * unpremultiply; 
    } 
    components[3] = a; 
} 
+0

Come non si inizializza 'resultPixel' a 0 il contesto bitmap contiene i valori garbage prima del disegno. Quindi questo restituirebbe valori corretti solo quando il colore ha un componente alfa di 1. –

+1

Inoltre, dovresti usare il caso speciale per alpha == 0. Altrimenti il ​​metodo restituirebbe infinito per i componenti del colore. –

+0

Un trucco intelligente! Ma (1) è un sacco di overhead quando 'CGColorGetComponents' funziona davvero bene (vedi la mia risposta su come farlo funzionare), e (2) questo trucco intelligente in realtà dà risultati errati quando il colore originale ha un valore alfa diverso da 0 o 1, perché la conversione in premoltiplicazione è lossy. Ad esempio, (0,8,0,0,0,1) diventa (20,0,0,26) quando premoltiplicato. Quando si annulla ciò, risulta il valore errato (0,76923,0,0,0,10196). –

7

so solo di un modo corretto di fare questo - e quello è chiamare CGGetColorComponents(). Ho provato a utilizzare UIColor di -getRed:green:blue:alpha, ma non funziona correttamente sui colori della scala di grigi. Quindi ecco cosa faccio:

In primo luogo, ho un semplice struct che mi consente di manipolare facilmente i colori RGBA. Questa struttura è utile altrove per fare ogni sorta di manipolazione del colore, come la correzione della gamma e la media del colore.

typedef struct 
{ 
    CGFloat r; // Red component (0 <= r <= 1) 
    CGFloat g; // Green component (0 <= g <= 1) 
    CGFloat b; // Blue component (0 <= b <= 1) 
    CGFloat a; // Alpha/opacity component (0 <= a <= 1) 
} 
RGBA; 

Poi, ho una funzione che restituisce un RGBA struttura data una UIColor.

RGBA RGBAFromUIColor(UIColor *color) 
{ 
    return RGBAFromCGColor(color.CGColor); 
} 

passa s' CGColor ad una funzione di livello inferiore la UIColor per fare il sollevamento di carichi pesanti.

RGBA RGBAFromCGColor(CGColorRef color) 
{ 
    RGBA rgba; 

    CGColorSpaceRef color_space = CGColorGetColorSpace(color); 
    CGColorSpaceModel color_space_model = CGColorSpaceGetModel(color_space); 
    const CGFloat *color_components = CGColorGetComponents(color); 
    int color_component_count = CGColorGetNumberOfComponents(color); 

    switch (color_space_model) 
    { 
    case kCGColorSpaceModelMonochrome: 
    { 
     assert(color_component_count == 2); 
     rgba = (RGBA) 
     { 
     .r = color_components[0], 
     .g = color_components[0], 
     .b = color_components[0], 
     .a = color_components[1] 
     }; 
     break; 
    } 

    case kCGColorSpaceModelRGB: 
    { 
     assert(color_component_count == 4); 
     rgba = (RGBA) 
     { 
     .r = color_components[0], 
     .g = color_components[1], 
     .b = color_components[2], 
     .a = color_components[3] 
     }; 
     break; 
    } 

    default: 
    { 
     NSLog(@"Unsupported color space model %i", color_space_model); 
     rgba = (RGBA) { 0, 0, 0, 0 }; 
     break; 
    } 
    } 

    return rgba; 
} 

Quindi, questo funziona alla grande per i colori in scala di grigi (come UIColor.whiteColor, UIColor.blackColor, UIColor.grayColor, ecc) così come qualsiasi verde blu/rosso// alpha. Tuttavia, non funzionerà con i colori HSB.

+1

Il poster originale chiedeva esplicitamente colori non RGB, quindi escluderli è chiaramente * non * una soluzione. – nschmidt

+2

@nschmidt - Perché l'hai contrassegnato ?? Ho risposto alla domanda. Vuole valori RGB da colori non RGB (in particolare monocromatico), che è esattamente quello che ho dato. Se si passa la funzione a un colore RGB, si ottengono valori RGB. Se si passa ad un valore grigio (ad es. Monocromatico), si ottengono comunque valori RGB. Leggi la risposta più da vicino e vedrai che entrambi sono gestiti correttamente.Questo è uno snippet di codice di produzione che uso, quindi so che funziona. Inoltre, come ho sottolineato in un commento, la tua risposta fornisce risultati errati. Non ti ho segnato per quello, anche se ... ti piacerebbe che io lo facessi? –

+2

Immagino che il mark-down sarebbe dovuto al modo in cui stai identificando il modello dello spazio colore. Ad esempio, i colori a 3 o 4 componenti potrebbero essere in spazi colore LAB o HSB. – damian

1

Crossposted from my answer to 'How to convert colors from one color space to another?'.

Per identificare i diversi spazi colore è possibile ottenere il CGColorSpaceModel dal di CGColorSpaceRef colore:

UIColor* color = some color; 
CGColorSpaceRef colorSpace = CGColorGetColorSpace([color CGColor]); 
CGColorSpaceModel colorSpaceModel = CGColorSpaceGetModel(colorSpace); 

Quindi è possibile confrontare colorSpaceModel con le costanti definite in CoreGraphics/CGColorSpace.h. UIColor's getRed:green:blue:alpha funziona per kCGColorSpaceModelRGB, mentre getWhite:alpha funziona per kCGColorSpaceModelMonochrome.

0

è possibile ottenere valore RGB semplicemente utilizzando questo

UIColor *chooseColor = view.backgroundColor; 
CGFloat red,green,blue,alpha; 

[chooseColor getRed:&red green:&green blue:&blue alpha:&alpha]; 

grazie :-)

+0

'UIColor getRed: green: blue: alpha:' soffre dello stesso problema 'CGColorGetComponents' fa in quanto avrà successo solo se il colore è nello spazio colore RGB (almeno su alcuni dispositivi/sistemi operativi). – devios1

Problemi correlati