Подтвердить что ты не робот

Правильный способ преобразования CGColors между цветами

Есть несколько вопросов, которые задают вопрос о преобразовании цветов между цветами на платформах Apple. К сожалению, ответы довольно часто включают классы NSColor или UIColor - не переносимые Objective-C, которые не могут быть взаимозаменяемы для OS X и iOS.

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

Как преобразовать CGColor из одного цветового пространства (например, монохромного) в другой (например, RGB) общим способом, поддерживая все типы CGColorSpace, используя только переносимые функции Core Graphics?


В некотором контексте. Мне нужно умножить значение, предоставляемое онлайн-службой, со значением, хранящимся в UIColor. Правильный способ извлечения компонентов RGB до iOS5, который, наконец, ввел метод -[UIColor getRed:green:blue:alpha:], заключается в использовании CGColorGetComponents(). Затем я умножу этот цвет на цвет, полученный из онлайн-сервиса. Это не удается, если +[UIColor grayColor] был использован для генерации UIColor. Смысл, мне нужно преобразовать цвет из цветового пространства оттенков серого в RGB. В этом случае это легко. Как насчет другого цветового пространства? Или что, если в теоретическом будущем сценарии я просто хочу обработать один пиксельный цвет?

Есть предположение, что я рисую пиксель в контексте растрового изображения, а затем читаю этот пиксель. Это безумие, и я надеюсь, что это не единственный способ сделать это. Очевидно, что метод рисования может определить, как выполнить преобразование; как мы можем использовать это без создания растрового контекста исключительно для рисования пикселя?


Дополнительные исследования:

  • В этой статье о преобразовании цвета, кроме UIColor недокументированного/приватного метода -styleString, более интересно упоминается также недокументированный CGColorTransform s.
  • ColorCG.cpp из WebKit предполагает наличие заголовка с именем CoreGraphics/CGColorTransform.h. К сожалению, этот заголовок не существует, по крайней мере, не для Mountain Lion. Почему Apple скрывает эти API?
  • Единственным другим разумным ресурсом, который я нашел упоминанием CGColorTransform, является FreeQuartz, повторная реализация Core Graphics без свободного/открытого источника.

Подал радар с Apple, № 12141580, чтобы открыть и занести документ CGColorTransform. Я не задерживаю дыхание, поэтому, если есть другие разумные предложения, я все уши.

4b9b3361

Ответ 1

Apple добавила этот API в iOS 9 и macOS 10.11:

  • ObjC: CGColorCreateCopyByMatchingToColorSpace
  • Swift: CGColor.converted(to:intent:options:)

Ответ 2

Официальный ответ Apple на rdar # 12141580, где я просил выставить CGColorTransform:

Большое спасибо за ваши отзывы.

Инженерия определила, что поведение не будет изменено на основе на следующей информации:

Использовать ColorSync.

Если у вас есть вопросы относительно разрешения этой проблемы, пожалуйста, обновите свой отчет об ошибке с помощью этой информации.

Теперь мы закрываем этот отчет об ошибке.

Пожалуйста, регулярно проверяйте новые выпуски Apple для любых обновлений что может повлиять на эту проблему.

Тот, кто написал этот ответ, очевидно, был вынужден объяснить это решение очень подробно. Особенно решение, которое рекомендует использовать очень сложный API, такой как ColorSync.

Ответ 3

В вопросе явно говорится, что они хотят избежать рисования контекста растрового изображения, созданного исключительно для целей преобразования цветов, но я не понимал и не придумал этого.

Я оставлю это ссылкой для тех, кто может наткнуться на этот вопрос и захочет узнать, как вы сделаете преобразование, используя временное растровое изображение

CGColorRef source;
CGColorSpaceRef targetColorSpace;
int components = CGColorSpaceGetNumberOfComponents(targetColorSpace);
CGFloat temp-buffer[components];
CGContextRef temp-bmp = CGBitmapContextCreate(
    temp-buffer,
    1,1,8 * sizeof(CGFloat),components,
    targetColorSpace,
    kCGBitmapFloatComponents );
CGContextSetFillColorWithColor(temp-bmp,source);
CGContextFillRect(temp-bmp,CGRectMake(0,0,1,1));
CGColor target = CGColorCreate(targetColorSpace,temp-buffer);

/* then you cleanup and destroy created objects */

Я не пробовал этот код, ему могут потребоваться некоторые исправления.