Windows下用Python获取电脑显示器物理尺寸和PPI

Windows下用Python获取电脑显示器物理尺寸和PPI

  • 背景
  • PPI 和 DPI
  • Python获取PPI
    • 方法一(WMI)
    • 方法二(WINREG)
    • 方法三(WMI+WINREG)
  • 总结

背景

最近在做一个项目,需要获取电脑屏幕PPI,网上好多都是人云亦云,花了蛮多时间的,深感不易!记录一下结果,希望对后来者有所帮助。

PPI 和 DPI

PPI (Pixels Per Inch) : 即每一英寸长度上有多少个像素点;
DPI (Dots Per Inch): 即每一英寸上有多少个点;

这里一个是像素点(Pixel),一个是点(Dot),区别就在这里。像素点(Pixel)是一个最小的基本单位,是固定不变的。而点(Dot) 则不同,它可以根据输出或者显示需要来改变的,可以是 1Dot = 1Pixel,也可以是 1Dot = N Pixel。

在电脑里,分辩率是可以调节的,这里用的就是Dot ,密度用DPI描述;只有当使用屏幕最大分辩率的时候(即 1Dot = 1Pixel),这个时候 DPI = PPI。

Python获取PPI

方法一(WMI)

1、安装wmi模块: pip install wmi
2、wmi依赖文win32com模块: pip install pywin32

使用wmi获取屏幕信息:

import wmi

w = wmi.WMI()
monitors = m.Win32.DesktopMonitor()
for m in monitors:
	print(m)

结果如下:
Windows下用Python获取电脑显示器物理尺寸和PPI_第1张图片
可以看到有屏幕分辨率和 PPI,但是这里的PPI只是一个逻辑尺寸上的PPI,并不准确,
而且貌似在WIN10上并不会显示屏幕分辩率,所以这种方法不可用。

方法二(WINREG)

通过读取注册表可以获取到显示器信息
代码如下:

import winreg

monitorInfoPath =r"SYSTEM\\ControlSet001\\Enum\\你的显示器信息"  #上面的PNPDeviceID
monitorInfoPath = monitorInfoPath   + "Device Parameters"
info = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, monitorInfoPath)
#EDID有128Bytes,包含很多显示器相关信息,感兴趣可以去查一下EDID解析
value = winreg.QueryValueEx(info,"EDID")[0]
#屏幕实际尺寸
width, height = value[21], value[22]
#推荐屏幕分辨率
widthResolution = value[56] +(value[58]>>4)*256
heightResolution = value[59] +(value[61]>>4)*256
#屏幕像素密度(Pixels Per Inch)
widthDensity = widthResolution/(width/2.54)
heightDensity = heightResolution/(height/2.54)

print("屏幕宽度:", width, " (厘米)")
print("屏幕高度:", height, " (厘米)")
print("水平分辩率: ", widthResolution, " (像素)")
print("垂直分辩率: ", heightResolution, " (像素)")
print("水平像素密度: ", widthDensity, " (PPI)")
print("垂直像素密度: ", heightDensity, " (PPI)")

这里我们可以得到显示器的实际尺寸,推荐(最大)分辩率,从而计算出PPI。

但是这里有一个问题,注册表中有时候会包含好几个显示器的信息(只要你连过的显示器,都在里面),到底哪一个是正在用的呢?

方法三(WMI+WINREG)

结合上面的两个方法就可以了,wmi获取PNPDeviceID,再用winreg读取相关信息!
代码如下:

import winreg
import wmi

PATH = "SYSTEM\\ControlSet001\\Enum\\"

m = wmi.WMI()
#获取屏幕信息
monitors = m.Win32_DesktopMonitor()

for m in monitors:
    subPath = m.PNPDeviceID
    infoPath = PATH + subPath + "\\Device Parameters"
    key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,infoPath)
    #屏幕信息按照一定的规则保存(EDID)
    value = winreg.QueryValueEx(key,"EDID")[0]
    winreg.CloseKey(key)
    
    #屏幕实际尺寸
    width, height = value[21], value[22]
    #推荐屏幕分辨率
    widthResolution = value[56] +(value[58]>>4)*256
    heightResolution = value[59] +(value[61]>>4)*256
    #屏幕像素密度(Pixels Per Inch)
    widthDensity = widthResolution/(width/2.54)
    heightDensity = heightResolution/(height/2.54)
    
    print("屏幕宽度:", width, " (厘米)")
    print("屏幕高度:", height, " (厘米)")
    print("水平分辩率: ", widthResolution, " (像素)")
    print("垂直分辩率: ", heightResolution, " (像素)")
    #保留小数点固定位数的两种方法
    print("水平像素密度: ", round(widthDensity, 2), " (PPI)")
    print("垂直像素密度: ", "%2.f"%heightDensity, " (PPI)")

结果如下:
Windows下用Python获取电脑显示器物理尺寸和PPI_第2张图片

总结

个人感觉,用WMI获取当前显示器并不是一种很恰当的方法,当有多个显示器的时候,貌似只能获取主显示器的信息。各位看官有什么想法建议,随时交流!

你可能感兴趣的:(Python编程)