最近在做一个项目,需要获取电脑屏幕PPI,网上好多都是人云亦云,花了蛮多时间的,深感不易!记录一下结果,希望对后来者有所帮助。
PPI (Pixels Per Inch) : 即每一英寸长度上有多少个像素点;
DPI (Dots Per Inch): 即每一英寸上有多少个点;
这里一个是像素点(Pixel),一个是点(Dot),区别就在这里。像素点(Pixel)是一个最小的基本单位,是固定不变的。而点(Dot) 则不同,它可以根据输出或者显示需要来改变的,可以是 1Dot = 1Pixel,也可以是 1Dot = N Pixel。
在电脑里,分辩率是可以调节的,这里用的就是Dot ,密度用DPI描述;只有当使用屏幕最大分辩率的时候(即 1Dot = 1Pixel),这个时候 DPI = PPI。
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)
结果如下:
可以看到有屏幕分辨率和 PPI,但是这里的PPI只是一个逻辑尺寸上的PPI,并不准确,
而且貌似在WIN10上并不会显示屏幕分辩率,所以这种方法不可用。
通过读取注册表可以获取到显示器信息
代码如下:
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获取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)")
个人感觉,用WMI获取当前显示器并不是一种很恰当的方法,当有多个显示器的时候,貌似只能获取主显示器的信息。各位看官有什么想法建议,随时交流!