Как преобразовать COLORREF из GetPixel () в RGB в Python? - PullRequest
1 голос
/ 31 октября 2019

Я пишу программу, использующую ctypes, которая возвращает мне пиксели в RGB, где бы я ни щелкал мышью по экрану. Я использую GetPixel(), чтобы вернуть COLORREF, который, я считаю, является шестнадцатеричным цветовым пространством ABGR (т. Е. # 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.

Я пытался создать функцию преобразования, но она хакерская и очень уродливая, и я чувствую, что предпринимаю ненужные шаги для достижения этой цели. Должен быть более обычный способ сделать это в 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

Ответы [ 2 ]

2 голосов
/ 31 октября 2019

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
1 голос
/ 31 октября 2019
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()

Я не нашел подходящего API для Python, я не знаю, может ли это удовлетворить ваши потребности.

...