Forma adecuada de convertir CGColors entre espacios de colors

Hay varias preguntas por ahí que preguntan sobre la conversión de colors entre espacios de colors en las plataforms de Apple. Desafortunadamente, las respuestas con bastante frecuencia incluyen NSColor o UIColor : classs Objective-C no portátiles que no se pueden usar indistintamente en OS X e iOS.

Entonces me gustaría preguntar algo muy específico que estoy seguro de que debe haber una buena respuesta. Simplemente no puedo creer que Apple no previera la necesidad de esto.

¿Cómo se puede convertir CGColor de un espacio de color (por ejemplo, monocromático) a otro (por ejemplo, RGB) de manera genérica, soportando todos los types de CGColorSpace , mientras se usan únicamente las funciones de Core Graphics portátiles?


Algún context. Necesito multiplicar el valor provisto por un service en línea con un valor almacenado en UIColor . La forma correcta de extraer los componentes RGB antes de iOS5, que finalmente introdujo el método -[UIColor getRed:green:blue:alpha:] , es usar CGColorGetComponents() . Luego multiplico este color con el color obtenido del service en línea. Esto falla en caso de que se +[UIColor grayColor] para generar el UIColor . Es decir, necesito convertir el color del espacio de colors en escala de grises en RGB. En este caso, es fácil. ¿Qué pasa con algún otro espacio de colors que se proporciona? ¿O qué sucede si en un escenario futuro teórico solo quiero procesar el color de un solo píxel?

Hay una sugerencia en alguna parte que pinte un píxel en un context de bitmap y luego lea este píxel. Eso es una locura, y espero que no sea la única forma de hacerlo. Obviamente, el método de dibujo puede averiguar cómo realizar la conversión; ¿Cómo podemos aprovechar esto sin crear un context bitmap únicamente para dibujar un píxel en él?


Investigación adicional:

  • Este artículo sobre la conversión del color, además del UIColor indocumentado / privado -styleString , menciona de manera más interesante CGColorTransform no CGColorTransform .
  • ColorCG.cpp de WebKit sugiere que hay un encabezado llamado CoreGraphics/CGColorTransform.h . Desafortunadamente, este encabezado no existe, al less no en Mountain Lion. ¿Por qué Apple ocultaría estas API?
  • El único otro recurso sensato que encontré mencionando CGColorTransform s es FreeQuartz, una reimplementación de Core Graphics gratuita / de código abierto.

Archivado un radar con Apple, # 12141580, para abrir y documentar CGColorTransform . Sin embargo, no estoy conteniendo la respiración, así que si hay otras sugerencias sensatas, soy todo oídos.

Apple agregó esta API en iOS 9 y macOS 10.11:

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

La respuesta oficial de Apple a Rdar # 12141580 donde CGColorTransform exponer CGColorTransform :

Muchas gracias por sus comentarios.

Engineering ha determinado que el comportamiento no se cambiará en function de la siguiente información:

Usa ColorSync.

Si tiene preguntas sobre la resolución de este problema, actualice su informe de errores con esa información.

Ahora estamos cerrando este informe de errores.

Asegúrese de verificar regularmente las nuevas versiones de Apple para cualquier actualización que pueda afectar este problema.

Quien escribió esa respuesta obviamente se sintió obligado a explicar la decisión con gran detalle. Especialmente una decisión que recomienda el uso de una API altamente compleja como ColorSync.

La pregunta explícitamente dice que quieren evitar dibujar en un context bitmap creado únicamente con el propósito de convertir colors, pero no me di count y se me ocurrió esto.

Dejaré esto como reference para cualquier persona que pueda tropezar con esta pregunta y quiera saber cómo realizaría la transformación dibujando en un bitmap temporal

 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 */ 

No probé este código, podría necesitar algunas soluciones.

    Intereting Posts