Pregunta

Me gustaría agregar la capacidad de ajustar la gamma de la pantalla al inicio de la aplicación y restablecerla en la salida. Si bien es discutible si uno debe manipular a Gamma (personal, lo encuentro inútil y perjudicial), pero bueno, algunas personas esperan poder hacer ese tipo de cosas.

También es una simple llamada API, así que todo es fácil, ¿verdad?

MSDN dice: "La rampa gamma se especifica en tres matrices de 256 elementos de palabras, cada uno de los valores [...] debe almacenarse en los bits más significativos de cada palabra para aumentar la independencia de DAC".. Esto significa, en mi opinión, algo como word_value = byte_value<<8, que suena bastante extraño, pero así es como lo leí.

El código fuente de Doom3 contiene una función que toma tres matrices de char valores y los convierte en una matriz de uint16_t valores que tienen el mismo valor de byte ambas cosas en la mitad superior e inferior. En otras palabras, algo como word_value = (byte_value<<8)|byte_value. Esto es igualmente extraño, pero lo peor es no es lo mismo que el anterior.

También existen algunos fragmentos de código en Internet en varios sitios de programadores de pasatiempos (aparentemente uno robado del otro, porque son idénticos a la letra) que hacen algunas matemáticas oscuras multiplicando el índice lineal con un valor, sesgo con 128, y sujetar a 65535. No estoy muy seguro de de qué se trata, pero me parece un total de tonterías, y nuevamente no es lo mismo que ninguno de los dos anteriores.

¿Lo que da? Debe estar bien definido, sin adivinar, ¿cómo deben ser los datos que suministra? Al final, lo que uno hará es leer los valores originales y dejar que el usuario modifique algunos controles deslizantes de todos modos (y opcionalmente guardar ese blob en el disco con la configuración del usuario), pero aún así ... para modificar estos valores, se necesita Sepa qué son y lo que se espera.

¿Alguien ha hecho (y probado!) Esto antes y sabe cuál es correcto?

¿Fue útil?

Solución

Mientras investigaba la capacidad de cambiar el brillo de la pantalla programáticamente, me encontré con este artículo Cambiar el brillo de la pantalla de programación: utilizando la API de rampa de Gama.

Usando el depurador, eché un vistazo a los valores proporcionados por el GetDeviceGamaRamp() función. La salida es una matriz bidimensional definida como algo así como WORD GammaArray[3][256]; y es una tabla de 256 valores para modificar los valores rojos, verdes y azules de los píxeles mostrados. Los valores que vi comenzaron con un valor de cero (0) en el índice 0 y agregaron un valor de 256 para calcular el siguiente valor. Entonces, la secuencia es 0, 256, 512, ..., 65024, 65280 para los índices 0, 1, 2, ..., 254, 255.

Entiendo que estos valores se utilizan para modificar el valor RGB para cada píxel. Al modificar el valor de la tabla, puede modificar el brillo de la pantalla. Sin embargo, la efectividad de esta técnica puede variar según el hardware de la pantalla.

Puede encontrar este breve artículo, Controles gamma, de interés tal como describe los niveles de rampa gamma desde una perspectiva directa 3D. El artículo tiene esto por decir sobre los niveles de rampa gamma.

En Direct3D, el término rampa gamma describe un conjunto de valores que asignan el nivel de un componente de color particular (rojo, verde, azul) para todos los píxeles en el búfer de cuadros a nuevos niveles que reciben el DAC para la pantalla. La reasignación se realiza a través de tres tablas de búsqueda, una para cada componente de color.

Así es como funciona: Direct3D toma un píxel del búfer de cuadros y evalúa sus componentes de color rojo, verde y azul individuales. Cada componente está representado por un valor de 0 a 65535. Direct3D toma el valor original y lo usa para indexar una matriz de 256 elementos (la rampa), donde cada elemento contiene un valor que reemplaza el original. Direct3D realiza este proceso de búsqueda y reemplazar para cada componente de color de cada píxel en el búfer de cuadros, cambiando así los colores finales para todos los píxeles en pantalla.

Según la documentación en línea para GetDeviceGamaRamp() y SetDeviceGamaRamp() Estas funciones son compatibles con la API de Windows que comienza con Windows 2000 Professional.

Utilicé su fuente condensada al siguiente ejemplo insertado en una aplicación de Windows para probar el efecto utilizando los valores del artículo referenciado. Mi prueba se realizó con Windows 7 y un adaptador de gráficos AMD Radeon HD 7450.

Con esta prueba, ambas pantallas, tengo dos pantallas, se vieron afectadas.

//Generate the 256-colors array for the specified wBrightness value.
WORD  GammaArray[3][256];
HDC   hGammaDC = ::GetDC(NULL);
WORD  wBrightness;

::GetDeviceGammaRamp (hGammaDC, GammaArray);

wBrightness = 64;     // reduce the brightness
for (int ik = 0; ik < 256; ik++) {
    int iArrayValue = ik * (wBrightness + 128);
    if (iArrayValue > 0xffff) iArrayValue = 0xffff;
    GammaArray[0][ik] = (WORD)iArrayValue;
    GammaArray[1][ik] = (WORD)iArrayValue;
    GammaArray[2][ik] = (WORD)iArrayValue;
}

::SetDeviceGammaRamp (hGammaDC, GammaArray);
Sleep (3000);

wBrightness = 128;    // set the brightness back to normal
for (int ik = 0; ik < 256; ik++) {
    int iArrayValue = ik * (wBrightness + 128);
    if (iArrayValue > 0xffff) iArrayValue = 0xffff;
    GammaArray[0][ik] = (WORD)iArrayValue;
    GammaArray[1][ik] = (WORD)iArrayValue;
    GammaArray[2][ik] = (WORD)iArrayValue;
}

::SetDeviceGammaRamp (hGammaDC, GammaArray);
Sleep (3000);

::ReleaseDC(NULL, hGammaDC);

Como nota adicional, hice un ligero cambio en la fuente anterior para que en lugar de modificar cada uno de los valores de RGB por igual, comenté las dos primeras tareas para que solo GammaArray[2][ik] fue modificado. El resultado fue un elenco amarillento a la pantalla.

También intenté poner la fuente anterior en un bucle para verificar cómo cambió la pantalla y fue una gran diferencia de wBrightness=0 a wBrightness=128.

for (wBrightness = 0; wBrightness <= 128; wBrightness += 16) {
    for (int ik = 0; ik < 256; ik++) {
        int iArrayValue = ik * (wBrightness + 128);
        if (iArrayValue > 0xffff) iArrayValue = 0xffff;
        GammaArray[0][ik] = (WORD)iArrayValue;
        GammaArray[1][ik] = (WORD)iArrayValue;
        GammaArray[2][ik] = (WORD)iArrayValue;
    }

    ::SetDeviceGammaRamp (hGammaDC, GammaArray);
    Sleep (3000);
}

Microsoft proporciona un artículo de MSDN en línea, Usando la corrección gamma, esa es parte de la documentación directa3D que describe los conceptos básicos de gamma de la siguiente manera:

Al final de la tubería de gráficos, justo donde la imagen deja la computadora para hacer su viaje a lo largo del cable del monitor, hay una pequeña pieza de hardware que puede transformar los valores de píxeles en la mosca. Este hardware generalmente usa una tabla de búsqueda para transformar los píxeles. Este hardware utiliza los valores rojos, verdes y azules que provienen de la superficie que se mostrarán para buscar valores corregidos por gamma en la tabla y luego envía los valores corregidos al monitor en lugar de los valores de la superficie reales. Por lo tanto, esta tabla de búsqueda es una oportunidad para reemplazar cualquier color con cualquier otro color. Si bien la tabla tiene ese nivel de potencia, el uso típico es ajustar las imágenes sutilmente para compensar las diferencias en la respuesta del monitor. La respuesta del monitor es la función que relaciona el valor numérico de los componentes rojos, verdes y azules de un píxel con el brillo mostrado de ese píxel.

Además el Aplicación de software Redshift tiene una página Ajustes de Windows Gamma que tiene esto que decir sobre Microsoft Windows.

Al portar el desplazamiento al rojo a las ventanas, me encontré con problemas al establecer una temperatura de color inferior a aproximadamente 4500k. El problema es que Windows establece limitaciones en qué tipos de ajustes gamma se pueden hacer, probablemente como un medio para proteger al usuario contra programas malvados que invierten los colores, en blanco la pantalla o juegan algún otro truco molesto con las rampas gamma. Este tipo de limitación es quizás comprensible, pero el problema es la falta completa de documentación de esta característica (SetDeviceGammaramp en MSDN). Un programa que intenta establecer una rampa gamma que no está permitida simplemente fallará con un error genérico, dejando al programador preguntándose qué salió mal.

Otros consejos

No he probado esto, pero si tuviera que adivinar, las primeras tarjetas gráficas no eran estándar en su implementación de SetDeviceGammaramp () cuando se escribió Doom y, a veces, usaban el Lobyte y, a veces, usaban el Hibyte del valor de la palabra. El consenso se movió a solo usar el hibyte, de ahí el word_value = byte_value<<8.

Aquí hay otro punto de datos, de la Biblioteca de Psychopy (en Python), que es solo intercambiar lobyte y hibyte:

 """Sets the hardware look-up table, using platform-specific ctypes functions. 
 For use with pyglet windows only (pygame has its own routines for this). 
 Ramp should be provided as 3x256 or 3x1024 array in range 0:1.0 
 """ 
if sys.platform=='win32':   
    newRamp= (255*newRamp).astype(numpy.uint16) 
    newRamp.byteswap(True)#necessary, according to pyglet post from Martin Spacek 
    success = windll.gdi32.SetDeviceGammaRamp(pygletWindow._dc, newRamp.ctypes) 
    if not success: raise AssertionError, 'SetDeviceGammaRamp failed' 

También parece que Windows no permite todas las configuraciones gamma, ver:http://jonls.dk/2010/09/windows-gamma-adjustments/

Actualizar:

Las primeras API de Windows que ofrecen control gamma son SetDeviceGammaramp y GetDeviceGammaramp de Windows Graphics Interface (GDI). Estas API funcionan con tres conjuntos de palabras de 256 entradas, con cada palabra que codifica cero hasta una, representada por los valores de palabras 0 y 65535. La precisión adicional de una palabra generalmente no está disponible en las tablas de búsqueda de hardware reales, pero estas API fueron destinado a ser flexible. Estas API, en contraste con las otras descritas más adelante en esta sección, permiten solo una pequeña desviación de una función de identidad. De hecho, cualquier entrada en la rampa debe estar dentro de 32768 del valor de identidad. Esta restricción significa que ninguna aplicación puede girar la pantalla completamente negra o en otro color ilegible.

http://msdn.microsoft.com/en-us/library/windows/desktop/jj635732(v=vs.85).aspx

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top