正确使用 SetDeviceGammaRamp [英] Correct usage of SetDeviceGammaRamp

查看:47
本文介绍了正确使用 SetDeviceGammaRamp的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想添加在应用程序启动时调整屏幕伽玛并在退出时重置它的功能.虽然是否应该篡改伽玛是有争议的(我个人认为它无用且有害),但是嘿,有些人希望能够做那种事情.

I'd like to add the ability to adjust screen gamma at application startup and reset it at exit. While it's debatable whether one should tamper with gamma at all (personal I find it useless and detrimental), but hey, some people expect being able to do that kind of thing.

这也只是一个简单的 API 调用,所以一切都很简单,对吗?

It's just one simple API call too, so it's all easy, right?

MSDN 说:伽玛斜坡在三个包含 256 个 WORD 元素的数组中指定,每个 [...] 值必须存储在每个 WORD 的最高有效位中,以增加 DAC 的独立性.".这意味着,在我的理解中,类似于 word_value = byte_value<<<8,这听起来很奇怪,但我就是这么读的.

MSDN says: "The gamma ramp is specified in three arrays of 256 WORD elements each [...] values must be stored in the most significant bits of each WORD to increase DAC independence.". This means, in my understanding, something like word_value = byte_value<<8, which sounds rather weird, but it's how I read it.

Doom3 源代码包含一个函数,该函数接受三个 char 值数组,并将它们转换为具有相同字节值的 uint16_t 值数组 在上半部分和下半部分.换句话说,类似于 word_value = (byte_value<<8)|byte_value.这同样很奇怪,但更糟糕的是它与上面的不一样.

The Doom3 source code contains a function that takes three arrays of char values and converts them into an array of uint16_t values that have the same byte value both in the upper and lower half. In other words something like word_value = (byte_value<<8)|byte_value. This is equally weird, but what's worse it is not the same as above.

在互联网上的各种业余程序员网站上也有一些代码片段(显然是从另一个网站上偷来的,因为它们与字母相同),它们做了一些晦涩的数学运算,将线性索引与一个值相乘,有偏差与 128,并钳位到 65535.我不太确定这是关于什么的,但在我看来这完全是胡说八道,而且它与上述两者中的任何一个都不相同.

Also there exist a few of code snippets on the internet on various hobby programmer sites (apparently one stolen from the other, because they're identical to the letter) which do some obscure math multiplying the linear index with a value, biasing with 128, and clamping to 65535. I'm not quite sure what this is about, but it looks like total nonsense to me, and again it is not the same as either of the above two.

什么给?它必须是明确定义的——无需猜测——您提供的数据必须是什么样子的?最后,人们要做的是读取原始值并让用户无论如何调整一些滑块(并可选择使用用户的配置将该 blob 保存到磁盘),但仍然......为了修改这些值,需要知道它们是什么以及期望什么.

What gives? It must be well-defined -- without guessing -- how the data that you supply must look like? In the end, what one will do is read the original values and let the user tweak some sliders anyway (and optionally save that blob to disk with the user's config), but still... in order to modify these values, one needs to know what they are and what's expected.

有没有人做过(并测试过!)这个并且知道哪个是正确的?

Has anyone done (and tested!) this before and knows which one is right?

推荐答案

在研究以编程方式更改屏幕亮度的能力时,我看到了这篇文章 以编程方式更改屏幕亮度 - 通过使用 Gama Ramp API.

While investigating the ability to change screen brightness programmatically, I came across this article 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.

Using the debugger, I took a look at the values provided by the GetDeviceGamaRamp() function. The output is a two dimensional array defined as something like WORD GammaArray[3][256]; and is a table of 256 values to modify the Red, Green, and Blue values of displayed pixels. The values I saw started with a value of zero (0) at index 0 and adding a value of 256 to calculate the next value. So the sequence is 0, 256, 512, ..., 65024, 65280 for indices 0, 1, 2, ..., 254, 255.

我的理解是这些值用于修改每个像素的 RGB 值.通过修改表值,您可以修改显示亮度.但是,此技术的有效性可能因显示硬件而异.

My understanding is that these values are used to modify the RGB value for each pixel. By modifying the table value you can modify the display brightness. However the effectiveness of this technique may vary depending on display hardware.

您可能会找到这篇简短的文章,Gamma Controls,很有趣,因为它从 Direct3D 的角度描述了 Gamma 渐变级别.这篇文章是关于 Gamma Ramp Levels 的.

You may find this brief article, Gamma Controls, of interest as it describes gamma ramp levels though from a Direct3D perspective. The article has this to say about Gamma Ramp Levels.

在 Direct3D 中,术语 gamma 渐变描述了一组映射值特定颜色成分的水平——红色、绿色、蓝色——对于所有帧缓冲区中的像素到 DAC 接收的新级别用于展示.重映射是通过三查的方式进行的表,每个颜色分量一个.

In Direct3D, the term gamma ramp describes a set of values that map the level of a particular color component—red, green, blue—for all pixels in the frame buffer to new levels that are received by the DAC for display. The remapping is performed by way of three look-up tables, one for each color component.

这是它的工作原理:Direct3D 从帧缓冲区中获取一个像素,然后评估其单独的红色、绿色和蓝色分量.每个组件由 0 到 65535 之间的值表示. Direct3D 需要原始值并用它来索引一个 256 个元素的数组(斜坡),其中每个元素都包含一个替换原始值的值一.Direct3D 为每种颜色执行此查找和替换过程帧缓冲区中每个像素的分量,从而改变所有屏幕像素的最终颜色.

Here's how it works: Direct3D takes a pixel from the frame buffer and evaluates its individual red, green, and blue color components. Each component is represented by a value from 0 to 65535. Direct3D takes the original value and uses it to index a 256-element array (the ramp), where each element contains a value that replaces the original one. Direct3D performs this look-up and replace process for each color component of each pixel in the frame buffer, thereby changing the final colors for all of the on-screen pixels.

根据 GetDeviceGamaRamp()SetDeviceGamaRamp() 的在线文档,从 Windows 2000 Professional 开始,Windows API 支持这些函数.

According to the online documentation for GetDeviceGamaRamp() and SetDeviceGamaRamp() these functions are supported in the Windows API beginning with Windows 2000 Professional.

我将他们的源代码压缩为以下插入到 Windows 应用程序中的示例,以使用参考文章中的值测试效果.我的测试是在 Windows 7 和 AMD Radeon HD 7450 图形适配器上完成的.

I used their source condensed down to the following example inserted into a Windows application to test the effect using values from the referenced article. My testing was done with Windows 7 and an AMD Radeon HD 7450 Graphics adapter.

通过这个测试,我的两个显示器,我有两个显示器,都受到了影响.

With this test both of my displays, I have two displays, were affected.

//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] 已修改.结果是显示器泛黄.

As an additional note, I made a slight change to the above source so that instead of modifying each of the RGB values equally, I commented out the first two assignments so that only GammaArray[2][ik] was modified. The result was a yellowish cast to the display.

我还尝试将上述源代码放入循环中以检查显示的变化情况,从 wBrightness=0wBrightness=128 差别很大.>

I also tried putting the above source in a loop to check how the display changed and it was quite a difference from 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 文章,使用伽马校正,这是 Direct3D 文档的一部分,它描述了伽马的基础知识,如下所示:

Microsoft provides an on-line MSDN article, Using gamma correction, that is part of the Direct3D documentation which describes the basics of gamma as follows:

在图形管道的末端,就在图像离开的地方计算机沿着显示器电缆行驶,有一个小可以动态转换像素值的硬件.这个硬件通常使用查找表来转换像素.这个硬件使用来自要显示的表面以在表中查找伽马校正值然后将校正后的值发送到监视器而不是实际表面值.所以,这个查找表是一个机会用任何其他颜色替换任何颜色.虽然桌子有那个水平的力量,典型的用法是巧妙地调整图像以补偿对于监视器响应的差异.监视器的反应是将红色、绿色和绿色的数值关联起来的函数具有该像素显示亮度的像素的蓝色分量.

At the end of the graphics pipeline, just where the image leaves the computer to make its journey along the monitor cable, there is a small piece of hardware that can transform pixel values on the fly. This hardware typically uses a lookup table to transform the pixels. This hardware uses the red, green and blue values that come from the surface to be displayed to look up gamma-corrected values in the table and then sends the corrected values to the monitor instead of the actual surface values. So, this lookup table is an opportunity to replace any color with any other color. While the table has that level of power, the typical usage is to tweak images subtly to compensate for differences in the monitor’s response. The monitor’s response is the function that relates the numerical value of the red, green and blue components of a pixel with that pixel’s displayed brightness.

此外,软件应用程序 Redshift 有一个页面 Windows 伽马调整,其中有这是关于 Microsoft Windows.

Additionally the software application Redshift has a page Windows gamma adjustments which has this to say about Microsoft Windows.

将 Redshift 移植到 Windows 时,我在设置色温低于4500K左右.问题是 Windows对可以进行的伽马调整类型设置限制,可能是为了保护用户免受恶意程序的侵害反转颜色,空白显示,或播放一些其他烦人的用伽马斜坡把戏.这种限制也许是可以理解,但问题是完全缺乏文档此功能的介绍(MSDN 上的 SetDeviceGammaRamp).一个试图设置一个不允许的伽马斜坡将简单地失败并显示一个通用的错误让程序员想知道出了什么问题.

When porting Redshift to Windows I ran into trouble when setting a color temperature lower than about 4500K. The problem is that Windows sets limitations on what kinds of gamma adjustments can be made, probably as a means of protecting the user against evil programs that invert the colors, blank the display, or play some other annoying trick with the gamma ramps. This kind of limitation is perhaps understandable, but the problem is the complete lack of documentation of this feature (SetDeviceGammaRamp on MSDN). A program that tries to set a gamma ramp that is not allowed will simply fail with a generic error leaving the programmer wondering what went wrong.

这篇关于正确使用 SetDeviceGammaRamp的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆