2011-01-15 29 views
18

Tôi ứng dụng của tôi tôi chuyển giá trị màu RGB cho máy chủ. Ứng dụng của tôi sử dụng các giá trị được xác định trước của UIColor, như [UIColor grayColor], [UIColor redColor]. Tôi biết rằng tôi có thể sử dụng mã sau đây:Nhận giá trị RGB từ các giá trị đặt sẵn UIColor

const CGFloat *c = CGColorGetComponents(color.CGColor) 

nhưng chỉ dành cho màu sắc trong không gian màu RBG, tuy nhiên, [UIColor grayColor] thì không.

Có cách nào để nhận giá trị RGB cho màu không phải RBG không?

Cảm ơn!

Trả lời

42

UIColor có phương pháp cung cấp cho bạn các thành phần RGB (-getRed:green:blue:alpha:) hoạt động tốt trên iOS 7 trở lên. Trên iOS 6 trở về trước, phương thức này sẽ thất bại và trả lại NO nếu màu không nằm trong không gian màu RGB (như nó sẽ cho [UIColor grayColor].)

Đối với iOS 6 trở về trước, cách duy nhất tôi biết để thực hiện việc này hoạt động trong tất cả các không gian màu là tạo ra một bối cảnh bitmap đồ họa lõi trong không gian màu RGB và vẽ nó với màu của bạn. Sau đó bạn có thể đọc các giá trị RGB từ bitmap kết quả. Lưu ý rằng điều này sẽ không hoạt động đối với một số màu nhất định, như màu mẫu (ví dụ: [UIColor groupTableViewBackgroundColor]), không có giá trị RGB hợp lý.

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

Bạn có thể sử dụng nó một cái gì đó như thế này:

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

Cảm ơn. Tôi quyết định rằng vấn đề của tôi không có giá trị giải pháp này, và tôi chuyển sang [UIColor colotWithRGB] thứ, tôi nhận giá trị RBG từ http://foobarpig.com/iphone/uicolor-cheatsheet-color-list-conversion-from-and -to-rgb-values.html. – lstipakov

+0

Cảm ơn. Vấn đề của tôi đáng giá chính xác giải pháp này! –

+5

Lưu ý: Trong iOS 5, 'Ugetolor''s' -getRed: green: blue: alpha' chỉ hoạt động với các màu sử dụng vùng màu RGB. Nó bị hỏng cho màu xám. Họ đã sửa lỗi này trong iOS 6 chưa? –

3

Thêm vào câu trả lời của Jesse, đây là cách để giữ gìn 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

Vì bạn không khởi tạo 'resultPixel' thành 0 ngữ cảnh bitmap chứa các giá trị rác trước khi vẽ. Vì vậy, điều này sẽ chỉ trả lại giá trị chính xác khi màu sắc có thành phần alpha là 1. –

+1

Ngoài ra, bạn nên đặc biệt cho alpha == 0. Nếu không phương thức sẽ trả về vô hạn cho các thành phần màu. –

+0

Một thông minh hack! Nhưng (1) nó là rất nhiều chi phí khi 'CGColorGetComponents' thực sự hoạt động tốt (xem câu trả lời của tôi về cách thực hiện công việc đó), và (2) hack thông minh này thực sự cho kết quả không chính xác khi màu gốc có giá trị alpha khác 0 hoặc 1, bởi vì chuyển đổi sớm là mất mát. Ví dụ: (0,8,0,0,0,1) trở thành (20,0,0,26) khi được cấp phép trước. Khi bạn hoàn tác thao tác này, kết quả là giá trị không chính xác (0,76923,0,0,0,10196). –

7

tôi chỉ biết một cách chính xác để làm điều này - và đó là để gọi CGGetColorComponents(). Tôi đã thử sử dụng của UIColor, nhưng nó không hoạt động chính xác trên các màu xám. Vì vậy, đây là những gì tôi làm:

Đầu tiên, tôi có một đơn giản struct cho phép tôi thao tác màu RGBA dễ dàng. Cấu trúc này hữu ích ở nơi khác để thực hiện tất cả các loại công cụ thao tác màu sắc như hiệu chỉnh gamma và màu trung bình.

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; 

Sau đó, tôi có hàm trả về cấu trúc RGBA cho UIColor.

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

Nó vượt qua 's CGColor đến một chức năng cấp dưới UIColor để làm việc nặng nhọc.

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

Vì vậy, hoạt động này rất tốt cho màu sắc màu xám (như UIColor.whiteColor, UIColor.blackColor, UIColor.grayColor, vv) cũng như bất kỳ màu đỏ/xanh/xanh/alpha màu. Tuy nhiên, nó sẽ không hoạt động với màu HSB.

+1

Các poster ban đầu được yêu cầu một cách rõ ràng cho các màu không phải RGB, vì vậy loại trừ chúng rõ ràng là * không * một giải pháp. – nschmidt

+2

@nschmidt - Tại sao bạn đánh dấu sự cố này? Tôi trả lời câu hỏi. Anh ta muốn các giá trị RGB từ các màu không phải RGB (đặc biệt là đơn sắc), đó chính xác là những gì tôi đã đưa ra. Nếu bạn vượt qua chức năng một màu RGB, bạn sẽ nhận được các giá trị RGB. Nếu bạn chuyển một giá trị màu xám (ví dụ: đơn sắc), bạn vẫn nhận được giá trị RGB. Đọc câu trả lời gần hơn và bạn sẽ thấy cả hai được xử lý đúng cách.Đây là một đoạn mã sản xuất mà tôi sử dụng, vì vậy tôi biết nó hoạt động. Ngoài ra, như tôi đã chỉ ra trong một bình luận, câu trả lời của bạn cho kết quả không chính xác. Tôi đã không đánh dấu bạn xuống cho rằng, mặc dù ... bạn có muốn tôi? –

+2

Tôi đoán đánh dấu xuống sẽ là do cách bạn đang xác định mô hình không gian màu. 3 hoặc 4 màu thành phần có thể có trong không gian màu LAB hoặc HSB chẳng hạn. – damian

1

Đã đăng chéo từ my answer to 'How to convert colors from one color space to another?'.

Để xác định không gian màu khác nhau mà bạn có thể nhận được CGColorSpaceModel từ của CGColorSpaceRef màu:

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

Sau đó, bạn có thể so sánh colorSpaceModel với các hằng số được định nghĩa trong CoreGraphics/CGColorSpace.h. Số điện thoại getRed:green:blue:alpha của UIColor hoạt động cho kCGColorSpaceModelRGB, trong khi getWhite:alpha hoạt động cho kCGColorSpaceModelMonochrome.

0

bạn có thể nhận được giá trị RGB chỉ đơn giản bằng cách sử dụng này

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

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

nhờ :-)

+0

'UIColor getRed: xanh lá cây: xanh dương: alpha:' bị ảnh hưởng bởi cùng một vấn đề 'CGColorGetComponents' thực hiện ở chỗ nó sẽ chỉ thành công nếu màu trong không gian màu RGB (ít nhất là trên một số thiết bị/OS). – devios1

Các vấn đề liên quan