当调查以编程方式更改屏幕亮度的功能,我碰到这篇文章Changing the screen brightness programmingly - By using the 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的角度描述了伽玛斜坡水平。这篇文章有关伽马斜坡水平的说法。
在Direct3D,术语伽马斜坡描述了一组值的映射 特定颜色的水平组件的红,绿,蓝中的帧缓冲器,以由接收到的新级别的所有 像素用于显示的DAC 。重映射通过三个查询表 表执行,每个颜色分量一个表。
以下是它的工作原理:Direct3D从帧缓冲区中获取一个像素,然后对其各个红色,绿色和蓝色分量进行评估。每个 组件都用0到65535之间的值表示。Direct3D以 为原始值并使用它来索引256元素的数组( 斜坡),其中每个元素都包含替换原始值的值。 Direct3D为帧缓冲区中每个像素的每个颜色分量执行此查找和替换过程,从而更改所有屏幕像素的最终颜色。
根据对GetDeviceGamaRamp()
和SetDeviceGamaRamp()
这些功能的在线文档是在Windows API与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);
}
微软提供的在线MSDN文章,Using gamma correction,这是描述伽马的基本如下Direct3D的文档的一部分:
在图形流水线的末端,就在那里该图像离开 计算机以沿着显示器电缆前进,还有一小块硬件可以实时转换像素值。这个硬件通常使用查找表来转换像素。此 硬件使用来自 表面的红色,绿色和蓝色值显示,以在表 中查找伽马校正值,然后将校正值发送到显示器,而不是实际表面值为 。所以,这个查找表是一个机会,以 取代任何其他颜色的颜色。虽然该表的功率级别为 ,但典型用法是巧妙地调整图像以补偿显示器响应差异 。显示器的响应是 这是将像素的红色,绿色和蓝色分量的数值与该像素的显示亮度相关联的功能。
此外,software application Redshift has a page Windows gamma adjustments其中有这么说微软Windows。
将Redshift移植到Windows时当设置 色温低于约4500K时,我遇到了麻烦。问题在于,Windows 对可以进行哪种伽玛调整设置了限制, 可能作为保护用户免受邪恶程序影响的一种手段,该程序可以反转颜色,使显示器空白或播放其他恼人的 技巧坡道。这种限制或许可以理解为 ,但问题是完全没有此功能的文档 (SetDeviceGammaRamp on MSDN)。一个程序尝试 设置不允许的伽马斜坡将仅仅失败,并且出现通用的 错误,使程序员不知道出了什么问题。
应该指出,“伽玛”与“亮度”没有什么关系,如果有的话。 Gamma是关于做一个非线性的每分量变换(非线性,除非γ= 1),在设备可以显示的内容和人眼所感知的内容之间进行转换,以及计算机在另一侧看到的线性RGB值。尽管如此,你已经提供了一个官方消息来源(DX手册页),它合理地暗示了范围从0到65535是正确的。因此,我会接受你的回答。 – Damon
@Damon,我的感觉是,通过修改伽玛斜坡,您基本上是通过对每个像素的RGB值执行平移来偏移显示输出,并因此将颜色范围移向黑色或朝向白色。通过此翻译,您正在修改显示图像的明亮度。从我可以告诉它看起来像一些屏幕显示亮度应用程序,如[Redshift](http://jonls.dk/redshift/)使用更改伽马斜坡。请参阅Redshift站点上的[Windows gamma调整](http://jonls.dk/2010/09/windows-gamma-adjustments/) –