Question

Je voudrais ajouter la possibilité d'ajuster l'écran gamma au démarrage de l'application et le réinitialiser à la sortie. Bien qu'il peut se demander si l'on doit falsifier gamma du tout (personnel je trouve inutile et nuisible), mais bon, certaines personnes attendent d'être en mesure de faire ce genre de chose.

Il est juste un simple appel API aussi, il est donc tout facile, non?

MSDN dit: «La rampe gamma est spécifiée dans trois tableaux de 256 éléments WORD chaque [...] les valeurs doivent être stockées dans les bits les plus significatifs de chaque mot pour accroître l'indépendance du CAD » . Cela signifie, dans ma compréhension, quelque chose comme word_value = byte_value<<8, qui sonne plutôt bizarre, mais c'est la façon dont je l'ai lu.

Le code source Doom3 contient une fonction qui prend trois matrices de valeurs de char et les convertit en une matrice de valeurs de uint16_t qui ont la même valeur de l'octet deux dans la moitié supérieure et inférieure. En d'autres termes quelque chose comme word_value = (byte_value<<8)|byte_value. Ceci est tout aussi bizarre, mais ce qui est pire, il est pas la même chose que ci-dessus .

Il existe également quelques-unes des extraits de code sur Internet sur différents sites de programmeur de passe-temps (apparemment un vol de l'autre, parce qu'ils sont identiques à la lettre) qui font un peu de mathématiques obscures multipliant l'indice linéaire avec une valeur, la polarisation avec 128, et de serrage à 65535. Je ne suis pas tout à fait sûr ce qu'il en est, mais il semble que non-sens total pour moi, et encore ce n'est pas le même que l'une des deux ci-dessus.

Qu'est-ce qui se passe? Il doit être bien défini - sans deviner - comment les données fournies doivent ressembler? En fin de compte, ce que l'on va faire est de lire les valeurs et laisser l'utilisateur modifier certains curseurs de toute façon (et éventuellement sauf que blob sur le disque avec la configuration de l'utilisateur), mais quand même ... afin de modifier ces valeurs d'origine, il faut savoir ce qu'ils sont et ce qu'on attend.

Quelqu'un at-il fait (et testé!) Cela avant et sait que l'on a raison?

Était-ce utile?

La solution

Alors qu'il enquêtait sur la capacité de luminosité de l'écran de changement par programme, je suis tombé sur cet article Modification de la luminosité de l'écran programmingly -. En utilisant l'API Gama rampe

En utilisant le débogueur, je pris un regard sur les valeurs fournies par la fonction GetDeviceGamaRamp(). La sortie est une matrice bidimensionnelle définie comme étant quelque chose comme WORD GammaArray[3][256]; et un tableau de 256 valeurs pour modifier les rouge, vert, bleu et des valeurs de pixels affichés. Les valeurs I Saw a commencé avec une valeur de zéro (0) à l'index 0 et en ajoutant une valeur de 256 pour calculer la valeur suivante. Ainsi, la séquence est égal à 0, 256, 512, ..., 65024, 65280 pour les indices 0, 1, 2, ..., 254, 255.

Ma compréhension est que ces valeurs sont utilisées pour modifier la valeur RVB pour chaque pixel. En modifiant la valeur de la table, vous pouvez modifier la luminosité de l'écran. Cependant, l'efficacité de cette technique peut varier en fonction du matériel d'affichage.

Vous pouvez trouver cet article bref, Contrôle gamma , d'intérêt car il décrit gamma ramp niveaux quoique dans une perspective Direct3D. L'article a ceci à dire au sujet des niveaux Gamma rampe.

Direct3D, la rampe terme gamma décrit un ensemble de valeurs que la carte le niveau d'un composant rouge couleur particulière, vert, bleu pour tous tampon de pixels dans la trame à de nouveaux niveaux qui sont reçus par le DAC pour l'affichage. Le remappage est effectuée par trois consultation tables, une pour chaque composante de couleur.

Voici comment cela fonctionne: Direct3D prend un pixel dans la mémoire tampon de trame et évalue son rouge individuel, vert, et les composants de couleur bleue. Chaque le composant est représenté par une valeur de 0 à 65535. Direct3D prend la valeur d'origine et l'utilise pour indexer un tableau de 256 éléments (le rampe), où chaque élément contient une valeur qui remplace l'original un. Direct3D effectue cette consultation et remplacer processus pour chaque couleur composant de chaque pixel dans le tampon de trame, en changeant ainsi la couleurs finales pour tous les pixels à l'écran.

Selon la documentation en ligne et GetDeviceGamaRamp() SetDeviceGamaRamp() ces fonctions sont prises en charge dans l'API Windows en commençant par Windows 2000 Professionnel.

je source condensée vers le bas à l'exemple suivant inséré dans une application Windows pour tester l'effet en utilisant des valeurs de l'article référencé. Mon test a été fait avec Windows 7 et une AMD Radeon HD 7450 adaptateur graphique.

Avec ce test de mes deux écrans, j'ai deux écrans, ont été touchés.

//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);

Comme une note supplémentaire, je fait un léger changement à la source ci-dessus afin qu'au lieu de modifier chacune des valeurs RVB également, je commentais les deux premières missions de sorte que seul GammaArray[2][ik] a été modifié. Le résultat a été une teinte jaunâtre à l'écran.

J'ai aussi essayé de mettre la source ci-dessus dans une boucle pour vérifier la façon dont l'affichage a changé et il était tout à fait une différence par rapport à wBrightness=0 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 fournit un article MSDN en ligne, Utilisation de la correction gamma , qui fait partie de la documentation Direct3D qui décrit les bases de gamma comme suit:

A la fin du pipeline graphique, juste où l'image quitte la ordinateur pour faire son voyage le long du câble du moniteur, il y a un petit morceau de matériel qui peut transformer des valeurs de pixel à la volée. Cette matériel utilise généralement une table de consultation pour transformer les pixels. Cette matériel utilise les valeurs de rouge, vert et bleu qui viennent de la surface à afficher àrechercher des valeurs gamma corrigé dans le tableau et envoie ensuite les valeurs corrigées au moniteur au lieu du les valeurs réelles de surface. Ainsi, cette table de consultation est une occasion de remplacer une couleur avec une autre couleur. Alors que la table a ce niveau du pouvoir, l'utilisation typique est de modifier les images subtilement pour compenser des différences dans la réponse du moniteur. La réponse du moniteur est la fonction qui concerne la valeur numérique du rouge, vert et composantes bleues d'un pixel avec la luminosité affichée de ce pixel.

De plus, l'application logicielle Redshift a une page réglages de Windows gamma qui a ceci à dire à propos de Microsoft Windows.

Lors du portage Redshift vers Windows j'ai rencontré des problèmes lors de la mise en la température de couleur inférieure à environ 4500K. Le problème est que Windows établit des limites sur les types d'ajustements gamma peuvent être faites, probablement comme un moyen de protéger l'utilisateur contre les programmes du mal qui inverser les couleurs, l'écran blanc, ou jouer un autre ennuyeux tour avec les rampes gamma. Ce type de limitation est peut-être compréhensible, mais le problème est l'absence totale de documentation de cette fonctionnalité ( SetDeviceGammaRamp sur MSDN ). Un programme qui tente de définir une rampe gamma non autorisé sera tout simplement échouer avec un générique erreur en laissant le programmeur se demandant ce qui se passait mal.

Autres conseils

I haven't tested this, but if I had to guess, early graphics cards were non-standard in their implementation of SetDeviceGammaRamp() when Doom was written and sometimes used the LOBYTE and sometimes used the HIBYTE of the WORD value. The consensus moved to only using the HIBYTE, hence the word_value = byte_value<<8.

Here's another datapoint, from the PsychoPy library (in python) which is just swapping LOBYTE and 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' 

It also appears that Windows doesn't allow all gamma settings, see: http://jonls.dk/2010/09/windows-gamma-adjustments/

Update:

The first Windows APIs to offer gamma control are Windows Graphics Device Interface (GDI)’s SetDeviceGammaRamp and GetDeviceGammaRamp. These APIs work with three 256-entry arrays of WORDs, with each WORD encoding zero up to one, represented by WORD values 0 and 65535. The extra precision of a WORD typically isn’t available in actual hardware lookup tables, but these APIs were intended to be flexible. These APIs, in contrast to the others described later in this section, allow only a small deviation from an identity function. In fact, any entry in the ramp must be within 32768 of the identity value. This restriction means that no app can turn the display completely black or to some other unreadable color.

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

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top