在研究以编程方式更改屏幕亮度的能力时,我遇到了这篇文章以编程方式更改屏幕亮度 - 通过使用 Gama Ramp API。
使用调试器,我查看了函数提供的值GetDeviceGamaRamp()
。输出是一个定义为类似的二维数组WORD GammaArray[3][256];
,是一个包含 256 个值的表,用于修改显示像素的红色、绿色和蓝色值。我看到的值从索引 0 处的零 (0) 值开始,然后加上一个值 256 来计算下一个值。因此,对于索引 0、1、2、...、254、255,序列为 0、256、512、...、65024、65280。
我的理解是这些值用于修改每个像素的 RGB 值。通过修改表格值可以修改显示亮度。但是,此技术的有效性可能因显示硬件而异。
您可能会发现这篇简短的文章Gamma Controls很有趣,因为它从 Direct3D 的角度描述了 Gamma 斜坡级别。这篇文章有关于 Gamma Ramp Levels 的内容。
在 Direct3D 中,术语 gamma ramp 描述了一组值,这些值将帧缓冲区中所有像素的特定颜色分量(红色、绿色、蓝色)的级别映射到 DAC 接收的用于显示的新级别。重新映射是通过三个查找表来执行的,每个颜色分量一个。
下面是它的工作原理: Direct3D 从帧缓冲区中获取一个像素,并计算其单独的红色、绿色和蓝色分量。每个组件由一个从 0 到 65535 的值表示。Direct3D 采用原始值并使用它来索引一个 256 元素数组(斜坡),其中每个元素都包含一个替换原始值的值。Direct3D 对帧缓冲区中每个像素的每个颜色分量执行此查找和替换过程,从而更改所有屏幕像素的最终颜色。
根据在线文档,GetDeviceGamaRamp()
从SetDeviceGamaRamp()
Windows 2000 Professional 开始的 Windows API 支持这些功能。
我将他们的源代码浓缩为插入到 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
to有很大的不同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 文章Using gamma correction,它是 Direct3D 文档的一部分,它描述了 gamma 的基础知识,如下所示:
在图形管道的末端,也就是图像离开计算机沿显示器电缆传输的地方,有一小块硬件可以动态转换像素值。该硬件通常使用查找表来转换像素。该硬件使用来自要显示的表面的红色、绿色和蓝色值来查找表中的伽马校正值,然后将校正值而不是实际表面值发送到监视器。所以,这个查找表是一个用任何其他颜色替换任何颜色的机会。虽然该表具有该级别的功能,但典型的用途是巧妙地调整图像以补偿显示器响应的差异。监视器的响应是与红色数值相关的函数,
此外,软件应用程序 Redshift 有一个页面 Windows 伽玛调整,其中包含有关 Microsoft Windows 的信息。
在将 Redshift 移植到 Windows 时,我在设置低于 4500K 的色温时遇到了麻烦。问题在于 Windows 对可以进行哪些类型的 gamma 调整设置了限制,这可能是为了保护用户免受恶意程序的影响,这些程序会反转颜色、使显示器空白或使用 gamma 斜坡玩一些其他烦人的技巧。这种限制也许是可以理解的,但问题是完全缺乏此功能的文档(MSDN 上的 SetDeviceGammaRamp)。尝试设置不允许的伽马斜坡的程序将简单地失败并出现一般错误,让程序员想知道出了什么问题。