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

背景

最近在做一个项目,需要获取电脑屏幕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 = w.Win32_DesktopMonitor()
for m in monitors:
	print(m)

结果如下:
在这里插入图片描述
可以看到有屏幕分辨率和 PPI,但是这里的PPI只是一个逻辑尺寸上的PPI,并不准确,
而且貌似在WIN10上并不会显示屏幕分辩率,所以这种方法不可用。

方法二(WINREG)

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

import winreg

#此处是显示器注册表路径,不同的电脑可能不一样(DISPLAY后面那部分路径)
# 要根据自己的电脑去填写,比如我的电脑是: \SYSTEM\ControlSet001\Enum\DISPLAY\CMN1604\1&8713bca&0&UID0\Device Parameters
monitorInfoPath =r"SYSTEM\\ControlSet001\\Enum\\你的显示器的路径信息"  
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		#
    #可能有多个注册表
    if subPath == None:
    	continue
    # 这个路径这里就是你的显示器在注册表中的路径,比如我现在的电脑是在HKEY_LOCAL_MACHINE下面的路径:
    # \SYSTEM\ControlSet001\Enum\DISPLAY\CMN1604\1&8713bca&0&UID0\Device Parameters
    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获取当前显示器并不是一种很恰当的方法,当有多个显示器的时候,貌似只能获取主显示器的信息。各位看官有什么想法建议,随时交流!

  • 13
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 14
    评论
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值