使用脚本更改Windows中的色度子采样设置(YCbCr 4:4:4到RGB,反之亦然)(Python)

时间:2017-07-28 14:40:53

标签: python windows nvidia

一些上下文:我正在编写一个程序来自动化监视器上的测试。为此,我想动态更改显示设置(分辨率,刷新率等),而无需每次手动通过NVIDIA控制面板。

我发现NirCmd实用程序允许您通过命令行更改其中一些设置,所以我首先想到的是使用它。遗憾的是,它无法修改更高级的参数,如色度子采样(NVIDIA控制面板中的“输出颜色格式”),输出动态范围或输出颜色深度。

然后我想用我的程序直接修改注册表值并通过调用ChangeDisplaySettings()来更新设置。在Windows上使用ProcMon,我通过更改显示设置确定修改了哪些键,然后直接使用Python更改它们,然后调用ChangeDisplaySettings()从键中读取并显示新设置。感觉有点像使用大炮杀死蚂蚁,但它在大多数情况下都有效:我能够使用此方法更改分辨率,刷新率,桌面颜色深度和显示的窗口大小。

以下是我正在使用的代码的相关部分(请注意,此代码需要修改为在特定计算机上运行,​​因为“LAPTOP_ID”和“DESKTOP_ID”注册表项是唯一的):

from Tkinter import *
import tkFont
import time
import ctypes
import serial
import _winreg
import win32gui
import win32con
import win32api
import wmi

def get_reg(name, reg_path):
    registry_key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, reg_path, 0, _winreg.KEY_READ)
    value, regtype = _winreg.QueryValueEx(registry_key, name)
    _winreg.CloseKey(registry_key)
    return value

def set_reg(name, value, reg_path):
    registry_key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, reg_path, 0, _winreg.KEY_WRITE)
    _winreg.SetValueEx(registry_key, name, 0, _winreg.REG_DWORD, value)
    _winreg.CloseKey(registry_key)

def set_reg_bin(name, value, reg_path):
    registry_key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, reg_path, 0, _winreg.KEY_WRITE)
    _winreg.SetValueEx(registry_key, name, 0, _winreg.REG_BINARY, value)
    _winreg.CloseKey(registry_key)

def reg_enum(reg_path):
    registry_key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, reg_path, 0, _winreg.KEY_READ)
    lastkey=_winreg.EnumKey(registry_key, _winreg.QueryInfoKey(registry_key)[0]-1)
    firstkey=_winreg.EnumKey(registry_key, 0)
    print lastkey
    print firstkey
    return lastkey

def deleteSubkey(key0, key1, key2=""):
    if key2=="":
        currentkey = key1
    else:
        currentkey = key1+ "\\" +key2
    open_key = _winreg.OpenKey(key0, currentkey ,0,_winreg.KEY_ALL_ACCESS)
    infokey = _winreg.QueryInfoKey(open_key)
    for x in range(0, infokey[0]):
        subkey = _winreg.EnumKey(open_key, 0)
        try:
            _winreg.DeleteKey(open_key, subkey)
            print "Removed %s\\%s " % ( currentkey, subkey)
        except:
            deleteSubkey( key0, currentkey, subkey )
    _winreg.DeleteKey(open_key,"")
    open_key.Close()
    print "Removed %s" % (currentkey)
    return

if __name__ =="__main__":
    DESKTOP_ID = "{########-####-####-####-############}"
    LAPTOP_ID = "{########-####-####-####-############}"
    REG_PATH_SCRID = r"SYSTEM\CurrentControlSet\Control\GraphicsDrivers\Configuration"
    deleteSubkey(_winreg.HKEY_LOCAL_MACHINE, REG_PATH_SCRID)
    try:
        input = raw_input('In Windows Display settings, under "Multiple displays", choose "Show only on 2", then press ENTER to continue.')
    except NameError:
        pass
    win32api.ChangeDisplaySettings(None, 0)
    ColorRGB = chr(0x00)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x0A)+chr(0x01)+chr(0x08)+chr(0x00)
    Color422 = chr(0x01)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x0A)+chr(0x01)+chr(0x08)+chr(0x00)
    Color444 = chr(0x02)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x0A)+chr(0x01)+chr(0x08)+chr(0x00)
    Color420 = chr(0x03)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x0A)+chr(0x01)+chr(0x08)+chr(0x00)
    ColorRGB_DriverExtra = chr(0x60)+chr(0xEA)+chr(0x00)+chr(0x00)+chr(0xE8)+chr(0x03)+chr(0x00)+chr(0x00)+chr(0x15)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x04)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x06)+chr(0x00)+chr(0x00)+chr(0x00)
    Color444_DriverExtra = chr(0x60)+chr(0xEA)+chr(0x00)+chr(0x00)+chr(0xE8)+chr(0x03)+chr(0x00)+chr(0x00)+chr(0x15)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x04)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x06)+chr(0x00)+chr(0x00)+chr(0x00)
    Color422_DriverExtra = chr(0x60)+chr(0xEA)+chr(0x00)+chr(0x00)+chr(0xE8)+chr(0x03)+chr(0x00)+chr(0x00)+chr(0x15)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x04)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x06)+chr(0x00)+chr(0x00)+chr(0x00)
    Color422_DriverExtra = chr(0x60)+chr(0xEA)+chr(0x00)+chr(0x00)+chr(0xE8)+chr(0x03)+chr(0x00)+chr(0x00)+chr(0x15)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x04)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x00)+chr(0x06)+chr(0x00)+chr(0x00)+chr(0x00)
    SCREEN_ID = reg_enum(REG_PATH_SCRID)
    print SCREEN_ID
    SCREEN_ID_SHORT = SCREEN_ID.partition("^")[0]
    print SCREEN_ID_SHORT
    REG_PATH = r"SYSTEM\CurrentControlSet\Hardware Profiles\UnitedVideo\CONTROL\VIDEO"+"\\"+LAPTOP_ID+r"\0000"
    REG_PATH2 = r"SYSTEM\CurrentControlSet\Hardware Profiles\UnitedVideo\CONTROL\VIDEO"+"\\"+LAPTOP_ID+r"\0001"
    REG_PATH3 = r"SYSTEM\CurrentControlSet\Control\GraphicsDrivers\Configuration"+"\\"+SCREEN_ID+r"\00\00"
    REG_PATH4 = r"SYSTEM\CurrentControlSet\Control\GraphicsDrivers\Configuration"+"\\"+SCREEN_ID+r"\00"
    REG_PATH5 = r"SYSTEM\CurrentControlSet\Control\GraphicsDrivers\Configuration"+"\\"+SCREEN_ID
    REG_PATH_COLOR = r"SYSTEM\CurrentControlSet\Services\nvlddmkm\DisplayDatabase"+"\\"+SCREEN_ID_SHORT

    set_reg('DefaultSettings.XResolution', 3840, REG_PATH)
    set_reg('DefaultSettings.YResolution', 2160, REG_PATH)
    set_reg_bin('DefaultSettings.DriverExtra', ColorRGB_DriverExtra, REG_PATH)
    set_reg('DefaultSettings.VRefresh', 60, REG_PATH)
    set_reg_bin('ColorformatConfig', ColorRGB, REG_PATH_COLOR)
    set_reg('Attach.ToDesktop', 1, REG_PATH)
    set_reg('VSyncFreq.Numerator', 60000, REG_PATH3)
    set_reg('VSyncFreq.Denominator', 1000, REG_PATH3)
    set_reg('PrimSurfSize.cx', 3840, REG_PATH3)
    set_reg('PrimSurfSize.cy', 2160, REG_PATH3)
    set_reg('DwmClipBox.left', 0, REG_PATH3)
    set_reg('DwmClipBox.top', 0, REG_PATH3)
    set_reg('DwmClipBox.right', 3840, REG_PATH3)
    set_reg('DwmClipBox.bottom', 2160, REG_PATH3)
    set_reg('PrimSurfSize.cx', 3840, REG_PATH4)
    set_reg('PrimSurfSize.cy', 2160, REG_PATH4)
    win32api.ChangeDisplaySettings(None, 0)

然而,由于我仍无法找到并更改控制更高级显示设置的按键,因此我没有进一步深入。看来他们没有被Nvidia存储在注册表中,所以我被卡住了。正如您所看到的,我确实找到了一个名为“ColorformatConfig”的密钥,当在NVIDIA控制面板中更改输出颜色格式时,该密钥正在被修改,但实际上它似乎并未直接使用。

我也尝试了Nvidia SDK,但发现它有点超出了我作为程序员的能力......

欢迎任何想法! (包括摆脱难看的连续chr()演员表的方法)

1 个答案:

答案 0 :(得分:0)

SetDisplayConfig提供了对源模式和目标模式的更大控制。如果您对所涉及的嵌套结构感到有些不知所措,我建议您手动将系统置于所需的配置中,然后使用QueryDisplayConfig获取当前配置。将每个配置保存在某处,然后让测试应用程序加载它们并将它们传递给SetDisplayConfig。