Вопрос по iphone, cgcolor, core-graphics, uicolor, cgcolorspace – Как преобразовать цвета из одного цветового пространства в другое?

17

Есть ли способ Cocoa Touch для преобразования цветов из одного цветового пространства в другое?

В конце этого кода:

UIColor *grey = [UIColor colorWithWhite: 0.5 alpha: 1.0];
CGColorRef greyRef = [grey CGColor];
int x = CGColorGetNumberOfComponents(greyRef);

...x это 2.

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

CGGradientRef createGradient(NSInteger inCount, NSArray* inColors, CGFloat* inLocations) {
 CGColorSpaceRef theColorspace = CGColorSpaceCreateDeviceRGB( );
 size_t numberOfComponents = 4;
 NSInteger colorSize = numberOfComponents * sizeof( CGFloat );
 CGFloat *theComponents = malloc( inCount * colorSize );
 CGFloat *temp = theComponents;
 for ( NSInteger i = 0; i < inCount; i++ ) {
  UIColor *theColor = [inColors objectAtIndex: i];
  CGColorRef cgColor = [theColor CGColor];
  const CGFloat *components = CGColorGetComponents( cgColor );
  memmove( temp, components, colorSize );
  temp += numberOfComponents;
 }
 CGGradientRef gradient = CGGradientCreateWithColorComponents( theColorspace,
                                               theComponents, inLocations, inCount );
 CGColorSpaceRelease( theColorspace );
 free( theComponents );
 return gradient;
}

Я знаю, что могу искать цвета в цветовом пространстве серого и преобразовывать их. Но это решает только один случай. От глядяна этот вопросЯ думаю, что HSB также обрабатывается. Но я хотел бы написать здесь некоторый код и больше никогда не думать об этом, что означает поддержку не только цветовых пространств, которые существуют сейчас, но и всего, что Apple могла бы добавить в будущем. Мне не повезло?

Ваш Ответ

4   ответа
7

как автоматически конвертировать их, но для определения различных цветовых пространств вы можете получитьCGColorSpaceModel из цветаCGColorSpaceRef:

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

Тогда ты можешь сравнитьcolorSpaceModel с константами, определенными вCoreGraphics/CGColorSpace.h. UIColor'sgetRed:green:blue:alpha работает наkCGColorSpaceModelRGB, в то время какgetWhite:alpha работает наkCGColorSpaceModelMonochrome.

Обратите внимание, чтоUIColor который был создан с помощьюcolorWithHue:saturation:brightness:alpha: на самом деле будет в цветовом пространстве RGB.

Это довольно хороший ответ, хотя вы можете упомянуть, что цвета HSB помещаются в цветовое пространство RGB. Таким образом, совершенно правильно называтьgetRed:green:blue:alpha: на них Steven Fisher
Хм, кажется, нетkCGColorSpaceModelHSB: / damian
Нет. Они отображаются в пространстве RGB; используйте метод RGB для них. Из документов дляcolorWithHue:saturation:brightness:alpha: Информация о цвете, представленная [возвращенным] объектом, находится в цветовом пространстве RGB устройства. Steven Fisher
Я добавил записку, которую вы предложили, но я чувствую, что это лишний шум в ответе. damian
2

[UIColor colorWithRed:green:blue:alpha:], вы можете использоватьUIColor getRed:green:blue:alpha:, описанный в UIColor Class Reference. Это часть iOS 5 и более поздних версий.

Если цвет был создан с помощьюcolorWithWhite:alpha: вы можете использоватьgetWhite:alpha: вместо этого, описано в UIColor Class Reference.

Чтобы определить, какое цветовое пространство используется, вы можете использоватьCGColorGetColorSpace([color colorSpace]). Но, вероятно, проще просто проверить результат вызова метода, а затем переключиться на следующую попытку. Что-то вроде этого

if ([color getRed:&red green:&green blue:&blue alpha:&alpha]) {
    // red, green and blue are all valid
} else if if ([color getWhite:&white alpha:&alpha]) {
    red = white; green = white; blue = white;
} else {
    // can't get it
}

Я не знаю, как обращаться с такими цветовыми константами, как[UIColor lightGrayColor], кроме рисования их во временное растровое изображение и обнаружения их. Некоторые из этих цветовых констант на самом деле являются текстурами; Лучше всего избегать их.

Если вы планируете делать это много, это подходящее использование категории:

@interface UIColor(sf)
- (BOOL)sfGetRed:(CGFloat *)red green:(CGFloat *)green blue:(CGFloat *)blue alpha:(CGFloat *)alpha;
@end

@implementation UIColor(sf)
- (BOOL)sfGetRed:(CGFloat *)red green:(CGFloat *)green blue:(CGFloat *)blue alpha:(CGFloat *)alpha {
    if ([self getRed:red green:green blue:blue alpha:alpha]) return YES;
    CGFloat white;
    if ([self getWhite:&white alpha:alpha]) {
        if (red) *red = white;
        if (green) *green = white;
        if (blue) *blue = white;
        return YES;
    }
    return NO;
}
@end
Вопрос, в частности, заключается в том, как преобразовать цвета между цветовыми пространствами; если вы вызываете этот метод, он может вернутьNO это означает, что получательUIColor находится в другом цветовом пространстве, чем текущее цветовое пространство. Например,BOOL success = [[UIColor lightGrayColor] getRed:&dummy green:&dummy blue:&dummy] возвращаетNO. damian
Требуется совместимое цветовое пространство, а не одно и то же цветовое пространство. Некоторые цвета просто не конвертируемы. Стоит сcolorWithWhite:alpha:. Похоже, вы не прочитали полный вопрос, и вы понизили голосование за то, что я разместил правильный ответ. Steven Fisher
Я не уверен, что означает «совместимое» цветовое пространство. Конечно, монохромное цветовое пространство «совместимо» с цветовым пространством RGB? Я отклонил ваш ответ, потому что в случае монохромного цвета упомянутый вами метод не только не работает, но и не очень хорошо работает, и неясно, почему. damian
Я думаю, что снова проверю все это и дополню свой ответ тем, что нашел. Спасибо, что предупредили меня, что это может быть неправильно. Steven Fisher
Похоже, ты прав. Я обновил ответ, чтобы отразить, что цветовое пространство в градациях серого не совместимо с RGB. Weird. Steven Fisher
2

В Swift 3 мы можем напрямую использовать

 let colorSpace = uiColor.cgColor.colorSpace
 let csModel = colorSpace.model

чтобы получить модель цветового пространства и цветового пространства отUIColor.

1

ь основной графике выполнить преобразование за вас. Смотрите мой ответ на этот вопрос:

Получить значение RGB из пресетов UIColor

Ого, правда? Это кажется ужасной идеей. damian
@ damian Без сомнения, это ужасно, но, насколько я знаю, это единственный способ, который надежно работает, независимо от того, как был создан оригинальный цвет. Учитывая, что первоначальный вопрос беспокоил «поддержку не только цветовых пространств, которые существуют сейчас, но и всего, что Apple могла бы добавить в будущем», я не вижу хорошей альтернативы. Jesse Rusak
ThinkDifferent (тм) damian

Похожие вопросы