Windows 10 has a feature to change the screen's color temperature named Night Light. This is a blue light reduction feature.
I would like to implement a clone of this feature in C++, using windows API. But have no idea how to do so.
It's not always a valid expectation that the OS will allow you to do what it itself does. Just because "the os should be able to access the screen" doesn't mean that you (in userland) should be able to do that. And most certainly, under Windows you have no unfettered screen access, not least because of DRM: there is a protected media path (PMP) for protected video and audio content, and you won't be able to sniff it from an arbitrary process.
So: whatever night light you may implement by accessing the screen contents, won't work as soon as any protected content is displayed, e.g. from Netflix, Hulu, Youtube Red, system DVD player, BluRay player, etc. To get around PMP you'd need to write a driver, sign it using an EV code signing certificate, and then submit it for automated attestation signing by Microsoft. And you'd not dare put it on the web, because Microsoft would blacklist that driver (i.e. its presence in the kernel would cause PMP-using applications to refuse to play protected content), and perhaps quickly at that.
With that out of the way, there are several ways that Windows could implement it, but we don't care because we're not writing a direct replacement for the Windows Night Light component. All we have access to is userland. Here's what we got to work with, then:
Windows itself performs monitor colorspace calibration using the "gamma ramp" system: a lookup table, historically used mostly for linearization of the monitor response, and subsequently used as a kitchen sink. There are three generations of those APIs:
The most legacy-compatible way would be to use the Windows Color System APIs, supported since Windows 2000. The function to use is SetDeviceGammaRamp. There is a caveat: Windows doesn't allow compressing the color too much, and it's quite arbitrary about what it allows. This family of APIs may fail if you try to do "too much".
Another highly compatible API would be within Direct3D 9 (available since Windows 98 and XP). It offers SetGammaRamp, with same data table format as that of SetDeviceGammaRamp above.
Yet another highly compatible API would be within Direct3D 10-12's DirectX Graphics Interface - DXGI, specifically IDXGIOutput::SetGammaControl. This one was available since Windows Vista, and thus is available on currently (2020) supported Windows versions.
The next most compatible approach would be to use the Magnification API.
The last approach, working only on your own application's window, would be to apply a shader to your window.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With