Вопрос

Я хотел бы добавить возможность настраивать гамма экрана при запуске приложения и сбросить ее при выходе. Хотя спорно, следует ли вообще вмешиваться в гамма (личная, я нахожу это бесполезным и вредным), но, эй, некоторые люди ожидают, что смогут делать такие вещи.

Это просто один простой звонок API, так что все это просто, верно?

MSDN говорит: «Гамма -рампа указана в трех массивах из 256 элементов слов, каждый из которых [...] значения должны храниться в наиболее значимых битах каждого слова, чтобы повысить независимость DAC».. Анкет Это означает, в моем понимании, что -то вроде word_value = byte_value<<8, что звучит довольно странно, но это то, как я это читал.

Исходный код DOOM3 содержит функцию, которая занимает три массива char ценит и преобразует их в массив uint16_t значения, которые имеют одинаковое значение байта оба В верхней и нижней половине. Другими словами word_value = (byte_value<<8)|byte_value. Анкет Это одинаково странно, но что еще хуже не то же самое, что и выше.

Также существует несколько фрагментов кода в Интернете на различных сайтах программистов Hobby (по -видимому, один украден у другого, потому что они идентичны букве), которые делают некоторые неясные математические умножения, умножая линейный индекс со значением, смеется с 128, и зажимать до 65535. Я не совсем уверен, что это такое, но это похоже на полную чушь, и опять же, это не то же самое, что и любой из двух вышеупомянутых.

Что дает? Это должно быть четко определенным-не догадая-как должны выглядеть данные, которые вы поставляете? В конце концов, то, что можно будет прочитать исходные значения и позволить пользователю в любом случае направлять некоторые слайдеры (и, необязательно сохранить эту BLOB, чтобы диск с конфигурацией пользователя), но все же ... Чтобы изменить эти значения, нужно, чтобы нужно было Знайте, что они и что ожидают.

Кто -нибудь сделал (и проверял!) Это раньше и знает, какой из них прав?

Это было полезно?

Решение

Изучая способность программно изменять яркости экрана, я наткнулся на эту статью Изменение яркости экрана программирующим - с помощью API Gama Rampi.

Используя отладчик, я посмотрел на значения, предоставленные GetDeviceGamaRamp() функция Выход - это двухмерный массив, определенный как что -то вроде WORD GammaArray[3][256]; и представляет собой таблицу из 256 значений для изменения красных, зеленых и синих значений отображаемых пикселей. Значения, которые я видел, начались со значением нуля (0) при индексе 0 и добавили значение 256 для вычисления следующего значения. Таким образом, последовательность 0, 256, 512, ..., 65024, 65280 для индексов 0, 1, 2, ..., 254, 255.

Насколько я понимаю, эти значения используются для изменения значения RGB для каждого пикселя. Изменив значение таблицы, вы можете изменить яркость дисплея. Однако эффективность этой техники может варьироваться в зависимости от оборудования для отображения.

Вы можете найти эту краткую статью, Гамма контроли, В интересах, поскольку он описывает уровни гамма -рампа, хотя с точки зрения Direct3D. В статье есть это, чтобы сказать о уровнях гамма -рампа.

В Direct3D термин гамма -рампа описывает набор значений, которые отображают уровень определенного цветового компонента - Red, зеленый, синий - для всех пикселей в буфере кадров на новые уровни, которые получены DAC для дисплея. Передача выполняется с помощью трех таблиц поиска, по одной для каждого цветового компонента.

Вот как это работает: Direct3D берет пиксель из кадриста и оценивает его индивидуальные компоненты красного, зеленого и синего цвета. Каждый компонент представлен значением от 0 до 65535. Direct3D принимает исходное значение и использует его для индексации массива 256 элементов (рампа), где каждый элемент содержит значение, которое заменяет исходное. Direct3D выполняет этот процесс поиска и замены для каждого цветового компонента каждого пикселя в буфере рамы, тем самым изменяя последние цвета для всех пикселей на экране.

Согласно онлайн -документации для GetDeviceGamaRamp() а также SetDeviceGamaRamp() Эти функции поддерживаются в API Windows, начиная с Professional Windows 2000.

Я использовал их источник, конденсированный к следующему примеру, вставленному в приложение Windows, чтобы проверить эффект, используя значения из ссылочной статьи. Мои тестирование было сделано с помощью Windows 7 и графического адаптера AMD Radeon HD 7450.

С этим тестом были затронуты оба моих дисплея, у меня есть два дисплея.

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

В качестве дополнительного примечания я внес небольшой изменение при вышеуказанном источнике, так что вместо того, чтобы в равной степени изменять каждое из значений RGB, я прокомментировал первые два назначения, чтобы только чтобы только что было GammaArray[2][ik] был изменен. Результатом стал желтоватый состав на дисплее.

Я также попытался поместить приведенный выше источник в цикл, чтобы проверить, как изменился дисплей, и это было довольно сильно 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 предоставляет онлайн-статью MSDN, Используя гамма -коррекцию, это является частью документации Direct3D, которая описывает основы гаммы следующим образом:

В конце графического трубопровода, где изображение покидает компьютер, чтобы отправиться в путь вдоль кабеля монитора, существует небольшой кусок аппаратного обеспечения, который может преобразовать значения пикселей на лету. Это оборудование обычно использует таблицу поиска для преобразования пикселей. Это оборудование использует красные, зеленые и синие значения, которые поступают с поверхности, которая будет отображаться, чтобы найти гамма-корректные значения в таблице, а затем отправляет исправленные значения на монитор вместо фактических значений поверхности. Таким образом, этот таблица поиска - это возможность заменить любой цвет на любой другой цвет. В то время как таблица имеет такой уровень мощности, типичное использование состоит в том, чтобы тонко настраивать изображения, чтобы компенсировать различия в ответе монитора. Ответ монитора - это функция, которая связывает числовое значение красного, зеленого и синего компонентов пикселя с яркости этого пикселя.

Дополнительно программное приложение RedShift имеет настройки Gamma Page Windows Что может сказать о Microsoft Windows.

При переносе красного смещения в окна я столкнулся с неприятностями при установлении цветовой температуры ниже, чем около 4500K. Проблема заключается в том, что Windows устанавливает ограничения на то, какие правила гамма могут быть внесены, вероятно, в качестве средства защиты пользователя от злых программ, которые инвертируют цвета, блуждают дисплей или воспроизводят какой -то другой раздражающий трюк с гамма -рампами. Такое ограничение, возможно, понятно, но проблема заключается в полном отсутствии документации этой функции (SetDevicegammaramp на MSDN) Программа, которая пытается установить гамма -рампу, которая не разрешена, просто не пройдет с общей ошибкой, оставив программиста задуматься, что пошло не так.

Другие советы

Я не проверял это, но если бы мне пришлось догадаться, ранние видеокарты были нестандартными в их реализации SetDevicegammaramp (), когда Doom был написан, а иногда использовал Lobyte, а иногда использовал Hibyte из значения слова. Консенсус перешел на использование Hibyte, отсюда word_value = byte_value<<8.

Вот еще один данных, из библиотеки психопии (в Python), которая просто меняет Lobyte и 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' 

Также появляется, что Windows не допускает всех настроек гамма, см.http://jonls.dk/2010/09/windows-gamma-adjustments/

Обновлять:

Первые API Windows, предложившие управление гамма, - это интерфейс Graphics Device Windows (GDI) SetDeviceGammaramp и GetDevicegammaramp. Эти API работают с тремя массивами слов 256-входов, с каждым словом, кодирующим нуль до одного, представленным значениями слов 0 и 65535 предназначен для того, чтобы быть гибким. Эти API, в отличие от других, описанных позже в этом разделе, позволяют только небольшое отклонение от идентификационной функции. Фактически, любая запись в рампе должна быть в пределах 32768 от значения идентификации. Это ограничение означает, что ни одно приложение не может повернуть дисплей полностью черным или в какой -то другой нечитаемый цвет.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top