Fórmulas alternativas para la conversión de CMYK a RGB para visualización en pantalla

Estoy escribiendo software para extraer secciones de texto de archivos PDF y renderizar en pantalla para su análisis; Necesito mostrar el texto en la pantalla en el color del documento.

Cuando el PDF contiene colores CMYK en este momento, estoy usando la fórmula simple que se encuentra ampliamente en la web (por ejemplo, aquí ), que es:

R = 255 × (1-C) × (1-K)

Y lo mismo para los demás colores.

Sin embargo, esto está dando malos resultados. Por ejemplo, una muestra que tengo está especificada en el documento PDF con el comando "0.62 0 0.05 0 k" (es decir, esos son los componentes CMYK en una escala de 0-1). La fórmula anterior convierte esto en un RGB de #60fff2. Sin embargo, Adobe Reader representa este texto usando RGB #3dc6ea. No solo se ven muy diferentes, mi color es tan brillante que el texto es difícil de leer. Probé esto en varios monitores y, aunque hay variaciones en los colores, el resultado general es el mismo: el lector de PDF muestra un pastel claro o azul cielo, mientras que la conversión anterior da un cian brillante.

Para verificar que esto no se deba a que se haya perdido algo en el PDF, probé el mismo color en Illustrator: ingresé un CMYK de (62 %, 0 %, 5 %, 0 %) representado en la pantalla como #3ec6ea. Cambiar el cuadro de edición de color a RGB mostró valores de #40c4e8; y esto también se representó si cambié la configuración de color a "Monitor de color". Son 3 resultados diferentes de Adobe, pero las diferencias son pequeñas y deberían ser imperceptibles.

Entonces, ¿existen conversiones alternativas factibles que darían resultados más cercanos a las conversiones de Adobe? Soy consciente de que la conversión entre RGB y CMYK es problemática, pero este caso ayuda un poco en eso:

  • la conversión es solo para visualización en pantalla. Las salidas no se imprimirán.

  • Las diferencias entre monitores no son muy importantes. Si un color se reproduce mal en un monitor determinado en (por ejemplo) Adobe Reader, no espero producir un buen resultado.

  • Una coincidencia exacta es irrelevante para mí: solo necesito una conversión que se vea similar y sea legible.

¿Qué lenguaje de programación usas? Es posible que haya una biblioteca que pueda hacer HardWork™️ por usted.
Estamos usando C#, pero creo que lo hemos resuelto lo suficientemente bien. Publicaré lo que hacemos ahora como respuesta.
¡Hola Estuardo! Que bueno verte aquí. ¿Hemos, por casualidad, trabajado juntos recientemente? :)
@Vincent: si estaba produciendo algunos logotipos para nosotros que necesitaba en una versión anterior de Illustrator, entonces sí :)

Respuestas (4)

Lo que estás haciendo es una versión muy ingenua de la conversión. Nunca jamás deberías hacer eso. Porque no es en absoluto cómo funciona. Pero cuidado, lo que pides es en realidad increíblemente complicado, más complicado de lo que puedes apreciar ahora mismo. Podría literalmente escribir cien páginas sobre esto y no terminar.

O recurres a trucos que son fáciles o necesitas hacer el trabajo completo.

No hay una fórmula

Necesita un sistema de gestión del color, sin opciones. Lo que debe hacer es obtener el perfil de color y la intención de reproducción del elemento en cuestión. Luego haga una conversión de perfil a perfil a su perfil de monitores.*

Consulte el PDF que contiene la mitad de la información sobre cómo realizar la simulación en pantalla de sus colores. Sin embargo, esta información tiene la forma de un perfil ICC, y los perfiles ICC son básicamente un minilenguaje de programación para la conversión de color. Por lo tanto, implementar el suyo propio sería mucho más trabajo del que espero que la mayoría de la gente tenga que gastar.

Ahora, lo más probable es que su sistema operativo tenga un sistema de administración de color, puede usarlo o usar algo como un pequeño CMS para hacer la conversión. Hacer un sistema ad hoc no lo hará feliz, pero usar un CMS listo para usar no es tan difícil, simplemente pídale al CMS que haga la conversión por usted.

* Si desea un color preciso, debe medir periódicamente su monitor y las condiciones de iluminación de fondo de su habitación. ¡Y sí, el color RGB es diferente en cada monitor!

Gracias por el pequeño enlace de CMS. Volveré a eso si resulta que necesitamos una mejor solución. Por el momento, la situación a partir de su último párrafo: "Si desea un color preciso...", es que no necesitamos información precisa, solo legible. Entonces, con suerte, nos las arreglaremos con la solución rápida.
El problema de @StuartWhitehouse es que es posible que no lo requiera, pero sus usuarios seguramente tienen la expectativa de que lo que ven es correcto. Mono mira mono hace...

Una solución rápida para la legibilidad puede ser reducir el colorido. Para una reducción del 25%, sea G=0,25.

Calcule el promedio de sus números RGB del resultado de conversión demasiado brillante. Que sea A.

Para cada número RGB X, calcule el nuevo con un colorido reducido, llamémoslo Y.

Utilice la fórmula Y=(1-G)X+GA

AGREGAR debido al comentario:

Puede tomar otro número ad-hoc, el factor de reducción de brillo =F. Sea F=0,8 para reducir el brillo al 80%. Multiplica todos los números RGB con él.

Asegúrese de que estos no reemplacen las matemáticas reales de gestión del color.

Una sugerencia interesante; Lo probé rápidamente y lo mejora hasta cierto punto; pero aún deja el texto muy claro: una de las diferencias entre el RGB que Adobe está renderizando y la fórmula simple que me da, es que Adobe es más oscuro en los 3 canales del RGB.
@StuartWhitehouse no puede obtener simultáneamente los mismos resultados que un CMS completo. Es lo suficientemente bueno o si eres más pedante que eso, entonces necesita una gestión completa del color.
Acepté esto como la respuesta, porque parece que la sugerencia de reducir el colorido probablemente sea lo suficientemente buena para nosotros. Ya había considerado reducir el brillo según la adición, aunque eso es arriesgado si el texto es claro sobre un fondo oscuro. Si luego resulta que este bodge no es suficiente, tendremos que ir por el camino largo y hacer los ColorSpaces correctamente.

R = 255 × (1-C) × (1-K)

No tengo idea de lo que acabas de decir... :o)

Probablemente necesite comprender que CMYK o RGB no son valores absolutos.

Mi ejemplo clásico es un marcador cian. Úselo en un papel de revista y en un periódico. Es el mismo valor de cian, la misma tinta... diferente color.

Para representar un color CMYK en una pantalla RGB, debe tomar un perfil de color para lo que se supone que significan los valores CMYK (¿papel brillante? ¿Periódico? ¿Papel sin recubrimiento?) y luego mostrarlo en una pantalla RGB.

Normalmente se supone que esta pantalla RGB tiene un perfil sRGB, pero también puede tener un perfil adicional específico para la pantalla.

En mi opinión, es mejor que estudies cómo aplicar y convertir entre perfiles de color, más que hacer una tabla de 16 millones de conversiones individuales.


Editado en base al comentario.

Toda la salida aquí está solo en la pantalla

No. Un valor CMYK de C100, como mi ejemplo anterior, es 100% en ambos casos, pero no es el mismo color.

Una salida RGB no es una salida RGB, es una simulación de las condiciones que se supone que tiene una impresión CMYK. Por eso es necesario definir cuál sería esa impresión CMYK para poder simularla.


Se ha dicho que probablemente desee apegarse a la calidad de impresión más óptima que pueda tener, probablemente usando papel estucado, para reducirlo, estudie cómo funciona Fogra 39.


Y sí, R = 255 × (1-C) × (1-K) significa que no está usando cian o (K) negro, por lo tanto, en realidad está usando los otros dos componentes restantes en un sistema de impresión de 4 tintas. amarillo y magenta. Pero es curioso cómo implica mencionar lo que no estás usando en lugar de definir lo que realmente estás usando.

Esto podría ser problemático, especialmente si su sistema realmente usa más de 4 tintas. Había un sistema Hexachrome que usaba 6. CMYK+GO


Editado 2.

Un método de conversión directa podría ser usar el inverso del color usado como indica su fórmula.

El rojo es la ausencia de cian. Pero esto descarta toda la información negra.

Los perfiles de color no son lineales ni tampoco tienen una curva suave.

El negro no se agrega a un color desde el principio, los colores pastel no tienen negro, y cuando el color es más oscuro, no solo agrega negro sino que también disminuye el resto de los colores para algunas cosas de absorción de papel.

Toda esa información está presente en el perfil de color.


Además, echa un vistazo a esto. Hay algunas explicaciones. Los valores CMYK siguen cambiando en el modo de color RGB/8, CS6

La fórmula que citó es para el canal rojo de RGB, basada en C y K del color CMYK. Con respecto al papel de la revista y el periódico... Entiendo que los colores dan diferentes resultados en diferentes contextos, sin embargo, todos los resultados aquí están solo en la pantalla, de hecho, en los mismos monitores. Es un software diferente que da resultados radicalmente diferentes.

La respuesta del usuario 287001 proporcionó algunas mejoras, pero aún era problemática en muchos casos. Estoy publicando nuestra solución final en caso de que ayude a otros.

Descargo de responsabilidad: esto no es "correcto" de ninguna manera. Los coeficientes a continuación son los que inventamos. (De hecho, hicimos una hoja de cálculo de las entradas y salidas deseadas y las resolvimos) Como otros han comentado, la conversión depende del uso de CMYK. Sin embargo, en algunos casos solo tenemos la información ColorSpace = "DeviceCMYK", components = c,m,y,k. No hay otra información disponible y esto debe representarse en la pantalla. En qué situación específica nos funciona el siguiente código c#...

// inputs are c,m,y,k components on a 0-1 scale
// work with INVERSE of CMYK values, on a 0-255 scale
float C = 255 * (1 - c);
float M = 255 * (1 - m);
float Y = 255 * (1 - y);
float K = 255 * (1 - k);

float r = 80 + 0.5882f * C - 0.3529f * M - 0.1373f * Y + 0.00185f * C * M + 0.00046f * Y * C; // no YM
float g = 66 - 0.1961f * C + 0.2745f * M - 0.0627f * Y + 0.00215f * C * M + 0.00008f * Y * C + 0.00062f * Y * M;
float b = 86 - 0.3255f * C - 0.1569f * M + 0.1647f * Y + 0.00046f * C * M + 0.00123f * Y * C + 0.00215f * Y * M;
// (for non c# readers, the 'f' suffix on the numbers just indicates the precision of the data type to hold the value)
r = r * K / 255;
g = g * K / 255;
b = b * K / 255;
// b,g,r are now the RGB components on a 0-255 scale, but will be out of bounds sometimes and need to be truncated to 0 and 255
Color RGB = Color.FromArgb(255, ((int)r).LimitTo(0, 255), ((int)g).LimitTo(0, 255), ((int)b).LimitTo(0, 255));
// LimitTo is an extension defined elsewhere - the usage should be obvious!

Esto produce resultados que son indistinguibles de los lectores de PDF estándar para nuestros casos de prueba.