usar saber recomendado quickgamma programa para pantalla imagenes esta contraste configurar como calibrar calibrada brillo aoc opengl graphics rendering gamma

opengl - saber - ¿Necesito corregir con rayos gamma la salida de color final en una computadora/monitor moderno?



imagenes para calibrar pantalla (1)

He estado bajo la suposición de que mi canalización de corrección de gamma debería ser la siguiente:

  • Utilice el formato sRGB para todas las texturas cargadas en ( GL_SRGB8_ALPHA8 ) ya que todos los programas de arte pre-gamma corrigen sus archivos. Al tomar muestras de una textura GL_SRGB8_ALPHA8 en un sombreador, OpenGL se convertirá automáticamente en espacio lineal.
  • Haga todos los cálculos de iluminación, procesamiento posterior, etc. en espacio lineal.
  • Vuelva a convertir a espacio sRGB al escribir el color final que se mostrará en la pantalla.

Tenga en cuenta que en mi caso la escritura del color final implica que escriba desde un FBO (que es una textura RGB lineal) al buffer posterior.

Mi suposición ha sido desafiada como si fuera gamma correcta en la etapa final, mis colores son más brillantes de lo que deberían ser. Configuré para que un color sólido sea dibujado por mis luces de valor {255, 106 , 0}, pero cuando renderizo obtengo {255, 171 , 0} (según lo determinado por el cribado de impresión y la selección de color). En lugar de naranja me pongo amarillo. Si no hago corrección gamma en el paso final, obtengo exactamente el valor correcto de {255, 106 , 0}.

Según algunos recursos, las pantallas LCD modernas imitan a CRT gamma. ¿Ellos siempre? Si no, ¿cómo puedo saber si debo hacer una gamma correcta? ¿Me estoy equivocando en otro lado?

Editar 1

Ahora he notado que aunque el color que escribo con la luz es correcto, los lugares donde uso colores de texturas no son correctos (pero bastante más oscuros de lo que esperaría sin la corrección gamma). No sé de dónde viene esta disparidad.

Editar 2

Después de probar GL_RGBA8 para mis texturas en lugar de GL_SRGB8_ALPHA8 , todo parece perfecto, incluso cuando GL_SRGB8_ALPHA8 los valores de textura en los cálculos de iluminación (si tengo la mitad de la intensidad de la luz, los valores de color de salida están medio).

Mi código ya no tiene en cuenta la corrección de gamma en ninguna parte, y mi salida parece correcta.

Esto me confunde aún más, ¿la corrección gamma ya no es necesaria / no se usa?

Edit 3 - En respuesta a la respuesta de datenwolf

Después de experimentar un poco más, estoy confundido con un par de puntos aquí.

1 - La mayoría de los formatos de imagen se almacenan de forma no lineal (en el espacio sRGB)

He cargado algunas imágenes (en mi caso, ambas imágenes .png y .bmp) y examiné los datos binarios en bruto. Me parece que las imágenes están realmente en el espacio de color RGB , como si comparase los valores de píxeles con un programa de edición de imágenes con la matriz de bytes que obtengo en mi programa, que coinciden perfectamente. Como mi editor de imágenes me está dando valores RGB, esto indicaría la imagen almacenada en RGB.

Estoy usando stb_image.h / .c para cargar mis imágenes y lo seguí durante todo el proceso cargando un .png y no vi en ningún lado que la gamma corrigiera la imagen mientras se cargaba. También examiné los .bmps en un editor hexadecimal y los valores en el disco coinciden para ellos.

Si estas imágenes están realmente almacenadas en un disco en un espacio RGB lineal, ¿cómo se supone que debo (programáticamente) saber cuándo especificar una imagen en el espacio sRGB? ¿Hay alguna forma de consultar esto que podría proporcionar un cargador de imágenes más destacado? ¿O corresponde a los creadores de la imagen guardar su imagen como gamma corregida (o no), lo que significa establecer una convención y seguirla para un proyecto determinado. Le pregunté a un par de artistas y ninguno de ellos sabía qué es la corrección gamma.

Si especifico que mis imágenes son sRGB, son demasiado oscuras a menos que gamma corrija al final (lo cual sería comprensible si la salida del monitor utiliza sRGB, pero vea el punto n. ° 2).

2 - "¡En la mayoría de las computadoras, el escaneo efectivo de LUT es lineal! ¿Qué significa esto?"

No estoy seguro de poder encontrar dónde terminó este pensamiento en tu respuesta.

Por lo que puedo decir, después de haber experimentado, todos los monitores que he probado en los valores de salida lineal. Si dibujo un cuadrángulo de pantalla completa y lo coloreo con un valor codificado en un sombreador sin corrección gamma, el monitor muestra el valor correcto que especifiqué.

Lo que la frase que mencioné arriba de su respuesta y mis resultados me llevarían a creer es que los monitores modernos emiten valores lineales (es decir, no emulan el CRT gamma) .

La plataforma objetivo para nuestra aplicación es la PC. Para esta plataforma (excluyendo personas con CRT o monitores realmente antiguos), ¿sería razonable hacer lo que sea que responda al # 1, luego el # 2 no gamma correcto (es decir, no realizar la transformación final RGB-> sRGB, ya sea manualmente? o usando GL_FRAMEBUFFER_SRGB)?

Si esto es así, ¿para qué sirven GL_FRAMEBUFFER_SRGB (o dónde sería válido usarlo hoy), o son monitores que usan RGB lineal realmente nuevo (dado que GL_FRAMEBUFFER_SRGB se introdujo en 2008)?

-

He hablado con algunos desarrolladores de gráficos en mi escuela y, por lo que se dice, ninguno de ellos ha tenido en cuenta la corrección de gamma y no han notado nada incorrecto (algunos ni siquiera lo conocían). Un desarrollador en particular dijo que obtuvo resultados incorrectos al tomar gamma en cuenta, por lo que decidió no preocuparse por la gamma. No estoy seguro de qué hacer en mi proyecto para mi plataforma de destino dada la información conflictiva que obtengo en línea / viendo con mi proyecto.

Edit 4 - En respuesta a la respuesta actualizada de datenwolf

Sí, de hecho. Si en alguna parte de la cadena de señal se aplica una transformación no lineal, pero todos los valores de píxel no se modifican de la imagen a la pantalla, entonces esa no linealidad ya se ha aplicado previamente en los valores de píxel de la imagen. Lo que significa que la imagen ya está en un espacio de color no lineal.

Su respuesta tendría sentido para mí si estuviera examinando la imagen en mi pantalla. Para estar seguro de que estaba claro, cuando dije que estaba examinando la matriz de bytes para la imagen quiero decir que estaba examinando el valor numérico en la memoria para la textura, no la salida de la imagen en la pantalla (lo que hice para el punto n. ° 2) . Para mí, la única forma en que podía ver lo que decías que era cierto era si el editor de imágenes me estaba dando valores en el espacio sRGB.

También tenga en cuenta que sí intenté examinar la salida en el monitor, así como también modificar el color de la textura (por ejemplo, dividirlo a la mitad o duplicarlo) y la salida parecía correcta (medida usando el método que describo a continuación).

¿Cómo midió la respuesta de la señal?

Lamentablemente mis métodos de medición son mucho más crudos que los tuyos. Cuando dije que experimenté en mis monitores lo que quise decir fue que saqué un cuadrante de pantalla completa en color sólido cuyo color estaba codificado en un sombreador a un framebuffer OpenGL (que no hace ninguna conversión de espacio de color cuando se escribe en él). Cuando produzco blanco, se muestran 75% de gris, 50% de gris, 25% de gris y negro. Ahora bien, aquí mi interpretación de los colores correctos podría estar equivocada. Tomo una captura de pantalla y luego uso un programa de edición de imágenes para ver cuáles son los valores de los píxeles (así como una evaluación visual para garantizar que los valores tengan sentido). Si entiendo correctamente, si mis monitores no fueran lineales, necesitaría realizar una transformación RGB-> sRGB antes de presentarlos al dispositivo de visualización para que sean correctos.

No voy a mentir, siento que estoy saliendo un poco de mi profundidad aquí. Estoy pensando que la solución que podría persistir para mi segundo punto de confusión (la transformación RGB-> sRGB final) será una configuración de brillo modificable y predeterminada a lo que parece correcto en mis dispositivos (sin corrección gamma).


En primer lugar, debe comprender que el mapeo no lineal aplicado a los canales de color a menudo es más que una simple función de potencia. La no linealidad sRGB se puede aproximar aproximadamente a x ^ 2.4, pero eso no es realmente el verdadero problema. De todos modos, sus suposiciones principales son más o menos correctas.

Si sus texturas se almacenan en los formatos de archivo de imagen más comunes, contendrán los valores tal como se presentan en el escaneo de gráficos. Ahora hay dos escenarios de hardware comunes:

  • La interfaz de escaneo genera una señal lineal y el dispositivo de visualización aplicará internamente un mapeo no lineal. Los viejos monitores CRT no eran lineales debido a su física: los amplificadores podían poner mucha corriente en el haz de electrones, la saturación de fósforo y demás, por eso todo el gamma se introdujo en primer lugar para modelar las no linealidades de las pantallas CRT. .

  • Las modernas pantallas LCD y OLED utilizan escalas de resistencia en sus amplificadores de controladores o tienen tablas de búsqueda de rampa gamma en sus procesadores de imágenes.

  • Sin embargo, algunos dispositivos son lineales y le piden al dispositivo de producción de imágenes que suministre un LUT correspondiente apropiado para el perfil de color de salida deseado en el escaneo.

¡En la mayoría de las computadoras, el escaneo efectivo LUT es lineal! ¿Qué significa esto sin embargo? Un pequeño desvío:

Para ilustración, conecté rápidamente la salida de la pantalla analógica de mi computadora portátil (conector VGA) a mi osciloscopio analógico: canal azul en el canal de alcance 1, canal verde al canal de alcance 2, señal de sincronización en línea (HSync). Un programa OpenGL rápido y sucio, escrito deliberadamente con modo inmediato se utilizó para generar una rampa de color lineal:

#include <GL/glut.h> void display() { GLuint win_width = glutGet(GLUT_WINDOW_WIDTH); GLuint win_height = glutGet(GLUT_WINDOW_HEIGHT); glViewport(0,0, win_width, win_height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, 1, 0, 1, -1, 1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glBegin(GL_QUAD_STRIP); glColor3f(0., 0., 0.); glVertex2f(0., 0.); glVertex2f(0., 1.); glColor3f(1., 1., 1.); glVertex2f(1., 0.); glVertex2f(1., 1.); glEnd(); glutSwapBuffers(); } int main(int argc, char *argv[]) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE); glutCreateWindow("linear"); glutFullScreen(); glutDisplayFunc(display); glutMainLoop(); return 0; }

La salida de gráficos se configuró con Modeline

"1440x900_60.00" 106.50 1440 1528 1672 1904 900 903 909 934 -HSync +VSync

(porque ese es el mismo modo en que funciona el panel plano, y estaba usando el modo de clonación)

  • gamma = 2 LUT en el canal verde.
  • lineal (gamma = 1) LUT en el canal azul

Así es como se ven las señales de una sola línea de escaneo (curva superior: Ch2 = verde, curva inferior: Ch1 ​​= azul):

Puede ver claramente las asignaciones x⟼x² y x⟼x (parábola y formas lineales de las curvas).

Ahora, después de este pequeño rodeo, sabemos que los valores de píxel que van al framebuffer principal van allí tal como están: la rampa lineal OpenGL no sufrió más cambios y solo cuando se aplicó un LUT de escaneo no lineal, alteró la señal enviada a la pantalla .

De cualquier forma, los valores que presente en el escaneo (lo que significa que los framebuffers en pantalla) se someterán a un mapeo no lineal en algún punto de la cadena de señal. Y para todos los dispositivos de consumo estándar, esta asignación estará de acuerdo con el estándar sRGB, porque es el factor común más pequeño (es decir, las imágenes representadas en el espacio de color sRGB se pueden reproducir en la mayoría de los dispositivos de salida).

Dado que la mayoría de los programas, como navegadores web asumen que la salida se somete a sRGB para visualizar la asignación de espacio de color, simplemente copian los valores de píxel de los formatos de archivo de imagen estándar al marco en pantalla tal como están, sin realizar una conversión de espacio de color, lo que implica que los valores de color dentro de esas imágenes están en el espacio de color sRGB (o que a menudo simplemente convertirán a sRGB, si el perfil de color de la imagen no es sRGB); lo correcto (si, y solo si los valores de color escritos en el framebuffer se escanean a la pantalla sin alterar, suponiendo que el escaneo LUT es parte de la pantalla), se convertiría al perfil de color especificado que la pantalla espera.

Pero esto implica, que el framebuffer en pantalla está en el espacio de color sRGB (no quiero dividir el asunto sobre cuán idiota es eso, solo aceptemos este hecho).

¿Cómo juntar esto con OpenGL? En primer lugar, OpenGL realiza todas sus operaciones de color de forma lineal. Sin embargo, dado que se espera que el escaneo esté en un espacio de color no lineal, esto significa que, de alguna manera, el resultado final de las operaciones de renderizado de OpenGL debe introducirse en el espacio de color del marco de foto en pantalla.

Aquí es donde ARB_framebuffer_sRGB extensión ARB_framebuffer_sRGB (que se convirtió en núcleo con OpenGL-3), que introdujo nuevos indicadores utilizados para la configuración de formatos de píxeles de ventana:

New Tokens Accepted by the <attribList> parameter of glXChooseVisual, and by the <attrib> parameter of glXGetConfig: GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20B2 Accepted by the <piAttributes> parameter of wglGetPixelFormatAttribivEXT, wglGetPixelFormatAttribfvEXT, and the <piAttribIList> and <pfAttribIList> of wglChoosePixelFormatEXT: WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20A9 Accepted by the <cap> parameter of Enable, Disable, and IsEnabled, and by the <pname> parameter of GetBooleanv, GetIntegerv, GetFloatv, and GetDoublev: FRAMEBUFFER_SRGB 0x8DB9

Entonces, si tiene una ventana configurada con un formato de pixel sRGB y habilita el modo de rasterización sRGB en OpenGL con glEnable(GL_FRAMEBUFFER_SRGB); el resultado de las operaciones de representación del espacio de color lineal se transformará en el espacio de color sRGB.

Otra forma sería convertir todo en un FBO fuera de la pantalla y en la conversión de color en un sombreador de posprocesamiento.

Pero eso es solo el lado de salida de la cadena de señal de renderizado. También recibiste señales de entrada, en forma de texturas. Y esas suelen ser imágenes, con sus valores de píxeles almacenados de forma no lineal. Entonces, antes de que se puedan usar en operaciones de imagen lineales, dichas imágenes deben colocarse primero en un espacio de color lineal. Simplemente ignoremos por el momento que mapear espacios de color no lineales en espacios de color lineales abre varias latas de gusanos sobre sí mismo, razón por la cual el espacio de color sRGB es tan ridículamente pequeño, es decir, para evitar esos problemas.

Entonces, para abordar esto, se introdujo una extensión EXT_texture_sRGB , que resultó ser tan vital, que nunca pasó por ser ARB, sino que pasó directamente a la especificación OpenGL misma: He aquí los formatos de textura interna GL_SRGB…

Una textura cargada con este formato se somete a una transformación de espacio de color RGB de sRGB a lineal, antes de ser utilizada para obtener muestras. Esto proporciona valores de píxel lineales, adecuados para operaciones de renderizado lineal, y el resultado puede transformarse válidamente a sRGB cuando vaya al framebuffer principal en pantalla.

Una nota personal sobre todo el problema: la presentación de imágenes en el framebuffer en pantalla en el espacio de color del dispositivo de destino en mi humilde opinión es un gran defecto de diseño. No hay forma de hacer todo bien en tal configuración sin volverse loco.

Lo que uno realmente quiere es tener el framebuffer en pantalla en un espacio de color de contacto lineal; la elección natural sería CIEXYZ. Las operaciones de renderizado se llevarían a cabo naturalmente en el mismo espacio de color de contacto. Hacer todas las operaciones gráficas en los espacios de color de contacto, evita la apertura de los botes de gusanos antes mencionados involucrados en tratar de empujar una clavija cuadrada llamada RGB lineal a través de un agujero redondo no lineal llamado sRGB.

Y aunque no me gusta mucho el diseño de Weston / Wayland, al menos ofrece la oportunidad de implementar dicho sistema de visualización, haciendo que los clientes rendericen y el compositor opere en el espacio de color de contacto y aplique los perfiles de color del dispositivo de salida. en un último paso de posprocesamiento.

El único inconveniente de los espacios de color de contacto es que es imperativo usar colores profundos (es decir,> 12 bits por canal de color). De hecho, 8 bits son completamente insuficientes, incluso con RGB no lineal (la no linealidad ayuda un poco a cubrir la falta de resolución perceptible).

Actualizar

He cargado algunas imágenes (en mi caso, ambas imágenes .png y .bmp) y examiné los datos binarios en bruto. Me parece que las imágenes están realmente en el espacio de color RGB, como si comparase los valores de píxeles con un programa de edición de imágenes con la matriz de bytes que obtengo en mi programa, que coinciden perfectamente. Como mi editor de imágenes me está dando valores RGB, esto indicaría la imagen almacenada en RGB.

Sí, de hecho. Si en alguna parte de la cadena de señal se aplica una transformación no lineal, pero todos los valores de píxel no se modifican de la imagen a la pantalla, entonces esa no linealidad ya se ha aplicado previamente en los valores de píxel de la imagen. Lo que significa que la imagen ya está en un espacio de color no lineal.

2 - "¡En la mayoría de las computadoras, el escaneo efectivo de LUT es lineal! ¿Qué significa esto?

No estoy seguro de poder encontrar dónde terminó este pensamiento en tu respuesta.

Este pensamiento se desarrolla en la sección que sigue inmediatamente, donde muestro cómo los valores que usted pone en un framebuffer simple (OpenGL) van directamente al monitor, sin modificaciones. La idea de sRGB es "poner los valores en las imágenes exactamente como se envían al monitor y crear pantallas de consumo para seguir ese espacio de color sRGB".

Por lo que puedo decir, después de haber experimentado, todos los monitores que he probado en los valores de salida lineal.

¿Cómo midió la respuesta de la señal? ¿Usó un medidor de potencia calibrado o un dispositivo similar para medir la intensidad de la luz emitida por el monitor en respuesta a la señal? No puedes confiar en tus ojos con eso, porque como todos nuestros sentidos, nuestros ojos tienen una respuesta de señal logarítmica.

Actualización 2

Para mí, la única forma en que podía ver lo que decías que era cierto era si el editor de imágenes me estaba dando valores en el espacio sRGB.

Ese es de hecho el caso. Debido a que la administración del color se agregó a todos los sistemas gráficos generalizados como una idea de último momento, la mayoría de los editores de imágenes editan valores de píxeles en el espacio de color de destino. Obsérvese que un parámetro de diseño particular de sRGB era que especificara retroactivamente las operaciones de color de transferencia directa de valor no gestionadas, tal como estaban (y todavía se realizan) en dispositivos de consumidor. Dado que no existe gestión del color, los valores contenidos en las imágenes y manipulados en los editores deben estar ya en sRGB. Esto funciona durante tanto tiempo, ya que las imágenes largas no se crean sintéticamente en un proceso de representación lineal; en el caso de lo posterior, el sistema de renderizado debe tener en cuenta el espacio de color de destino.

Tomo una captura de pantalla y luego uso un programa de edición de imágenes para ver cuáles son los valores de los píxeles

Lo que le da, por supuesto, solo los valores brutos en el búfer de escaneado sin la gamma LUT y la no linealidad de la pantalla aplicada.