如何在 python 中将 COLORREF 从 GetPixel() 转换为 RGB?
How to convert COLORREF from GetPixel() to RGB in python?
我正在使用 ctypes 编写一个程序,它 returns 我在屏幕上单击鼠标的任何地方的 RGB 像素。我正在使用 GetPixel()
to returns a COLORREF
,我认为它是 ABGR 十六进制颜色 space(即 #00BBGGRR)。问题是我不确定如何将 COLORREF 转换为 RGB。
这是一个代码片段:
from ctypes import *
from ctypes.wintypes import LONG
from sys import exit
# DLLs
user32 = windll.user32
gdi32 = windll.gdi32
# Virtual Keys
LM_BUTTON = 0x01
RM_BUTTON = 0x02
def main():
while True:
if get_key_state(LM_BUTTON) > 1: # Detect key press.
colorref = get_pixel(*get_cursor())
print(colorref)
while get_key_state(LM_BUTTON) > 1: # Wait for key release.
pass
if get_key_state(RM_BUTTON) > 1:
exit()
class POINT(Structure):
_fields_ = [('x', LONG), ('y', LONG)]
def get_cursor():
pos = POINT()
user32.GetCursorPos(byref(pos))
return pos.x, pos.y
def get_pixel(x, y, hdc=0):
dc = user32.GetDC(hdc)
colorref = gdi32.GetPixel(dc, x, y)
return colorref
def get_key_state(vkey):
return user32.GetKeyState(vkey)
if __name__ == '__main__':
main()
有某些宏,例如 RGB macro
,可以将 COLORREF 转换为 RGB,但我不确定如何使用 ctypes 调用这些宏。
我试过创建一个转换函数,但它 hacky 并且非常丑陋,我觉得我正在采取不必要的步骤来实现它。在 python?
中必须有更常规的方法来执行此操作
def get_rgb(colorref):
color_hex = hex(colorref)[2:].zfill(6)[::-1]
rgb = tuple(int(rgb, 16) if '0' not in (rgb:=color_hex[i:i+2]) else int(rgb[::-1], 16) for i in (0, 2, 4))
return rgb
def main():
while True:
if get_key_state(LM_BUTTON) > 1: # Detect key press.
colorref = get_pixel(*get_cursor())
R = colorref & 0xff
G = (colorref >> 8) & 0xff
B = (colorref >> 16) & 0xff
print(R,G,B)
while get_key_state(LM_BUTTON) > 1: # Wait for key release.
pass
if get_key_state(RM_BUTTON) > 1:
exit()
没有找到适合python的API,不知道能不能满足你的需求
A COLORREF
定义为 32 位值(来自 windef.h
):
typedef DWORD COLORREF;
还有那 3 个宏(来自 wingdi.h
):
#define RGB(r,g,b) ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16)))
#define GetRValue(rgb) (LOBYTE(rgb))
#define GetGValue(rgb) (LOBYTE(((WORD)(rgb)) >> 8))
#define GetBValue(rgb) (LOBYTE((rgb)>>16))
所以通过查看这些宏我们可以看到:
R
分量是低位字节(位 0-7)
G
分量来自位 8 - 15。
B
分量来自位 16 - 23。
所以基本上你所要做的就是屏蔽和位移:
def rgba(colorref):
mask = 0xff
return [(colorref & (mask << (i * 8))) >> (i * 8) for i in range(4)]
测试:
>>> r, g, b, a = rgba(0x01020304)
>>> print(r,g,b,a)
4 3 2 1
我正在使用 ctypes 编写一个程序,它 returns 我在屏幕上单击鼠标的任何地方的 RGB 像素。我正在使用 GetPixel()
to returns a COLORREF
,我认为它是 ABGR 十六进制颜色 space(即 #00BBGGRR)。问题是我不确定如何将 COLORREF 转换为 RGB。
这是一个代码片段:
from ctypes import *
from ctypes.wintypes import LONG
from sys import exit
# DLLs
user32 = windll.user32
gdi32 = windll.gdi32
# Virtual Keys
LM_BUTTON = 0x01
RM_BUTTON = 0x02
def main():
while True:
if get_key_state(LM_BUTTON) > 1: # Detect key press.
colorref = get_pixel(*get_cursor())
print(colorref)
while get_key_state(LM_BUTTON) > 1: # Wait for key release.
pass
if get_key_state(RM_BUTTON) > 1:
exit()
class POINT(Structure):
_fields_ = [('x', LONG), ('y', LONG)]
def get_cursor():
pos = POINT()
user32.GetCursorPos(byref(pos))
return pos.x, pos.y
def get_pixel(x, y, hdc=0):
dc = user32.GetDC(hdc)
colorref = gdi32.GetPixel(dc, x, y)
return colorref
def get_key_state(vkey):
return user32.GetKeyState(vkey)
if __name__ == '__main__':
main()
有某些宏,例如 RGB macro
,可以将 COLORREF 转换为 RGB,但我不确定如何使用 ctypes 调用这些宏。
我试过创建一个转换函数,但它 hacky 并且非常丑陋,我觉得我正在采取不必要的步骤来实现它。在 python?
中必须有更常规的方法来执行此操作def get_rgb(colorref):
color_hex = hex(colorref)[2:].zfill(6)[::-1]
rgb = tuple(int(rgb, 16) if '0' not in (rgb:=color_hex[i:i+2]) else int(rgb[::-1], 16) for i in (0, 2, 4))
return rgb
def main():
while True:
if get_key_state(LM_BUTTON) > 1: # Detect key press.
colorref = get_pixel(*get_cursor())
R = colorref & 0xff
G = (colorref >> 8) & 0xff
B = (colorref >> 16) & 0xff
print(R,G,B)
while get_key_state(LM_BUTTON) > 1: # Wait for key release.
pass
if get_key_state(RM_BUTTON) > 1:
exit()
没有找到适合python的API,不知道能不能满足你的需求
A COLORREF
定义为 32 位值(来自 windef.h
):
typedef DWORD COLORREF;
还有那 3 个宏(来自 wingdi.h
):
#define RGB(r,g,b) ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16)))
#define GetRValue(rgb) (LOBYTE(rgb))
#define GetGValue(rgb) (LOBYTE(((WORD)(rgb)) >> 8))
#define GetBValue(rgb) (LOBYTE((rgb)>>16))
所以通过查看这些宏我们可以看到:
R
分量是低位字节(位 0-7)G
分量来自位 8 - 15。B
分量来自位 16 - 23。
所以基本上你所要做的就是屏蔽和位移:
def rgba(colorref):
mask = 0xff
return [(colorref & (mask << (i * 8))) >> (i * 8) for i in range(4)]
测试:
>>> r, g, b, a = rgba(0x01020304)
>>> print(r,g,b,a)
4 3 2 1