Image.frombuffer с 16-битными данными изображения - PullRequest
0 голосов
/ 17 ноября 2010

Если мои окна находятся в 32-битном режиме глубины цвета, то следующий код получает хорошее изображение PIL из окна:

def image_grab_native(window):
    hwnd = win32gui.GetDesktopWindow()

    left, top, right, bot = get_rect(window)
    w = right - left
    h = bot - top

    hwndDC = win32gui.GetWindowDC(hwnd)
    mfcDC  = win32ui.CreateDCFromHandle(hwndDC)
    saveDC = mfcDC.CreateCompatibleDC()

    saveBitMap = win32ui.CreateBitmap()
    saveBitMap.CreateCompatibleBitmap(mfcDC, w, h)

    saveDC.SelectObject(saveBitMap)
    saveDC.BitBlt((0, 0), (w, h),  mfcDC,  (left, top),  win32con.SRCCOPY)

    bmpinfo = saveBitMap.GetInfo()
    bmpstr = saveBitMap.GetBitmapBits(True)

    im = Image.frombuffer(
        'RGB',
        (bmpinfo['bmWidth'], bmpinfo['bmHeight']),
        bmpstr, 'raw', 'BGRX', 0, 1)

    win32gui.DeleteObject(saveBitMap.GetHandle())
    saveDC.DeleteDC()
    mfcDC.DeleteDC()
    win32gui.ReleaseDC(hwnd, hwndDC)

    return im

Однако при работе в 16-битном режиме я получаюошибка:

>>> image_grab_native(win)
Traceback (most recent call last):
  File "<pyshell#3>", line 1, in <module>
    image_grab_native(win)
  File "C:\claudiu\bumhunter\finderbot\ezpoker\utils\win32.py", line 204, in image_grab_native
    bmpstr, 'raw', 'BGRX', 0, 1)
  File "c:\python25\lib\site-packages\PIL\Image.py", line 1808, in frombuffer
    return apply(fromstring, (mode, size, data, decoder_name, args))
  File "c:\python25\lib\site-packages\PIL\Image.py", line 1747, in fromstring
    im.fromstring(data, decoder_name, args)
  File "c:\python25\lib\site-packages\PIL\Image.py", line 575, in fromstring
    raise ValueError("not enough image data")
ValueError: not enough image data

Как мне сформировать вызов frombuffer для работы в 16-битном режиме?Также, как я могу заставить эту функцию работать в любом режиме глубины в битах, вместо того, чтобы сказать, что нужно передавать ее как параметр?

ОБНОВЛЕНИЕ: С этот вопрос Я узнал, что должен использовать "BGR;16 "вместо" BGRX "для параметра 2-го режима.Он принимает правильное изображение, либо с указанием шага или нет.Проблема заключается в том, что значения пикселей слегка смещены для некоторых значений:

x   y native           ImageGrab
280 0  (213, 210, 205) (214, 211, 206)
280 20 (156, 153, 156) (156, 154, 156)
280 40 (213, 210, 205) (214, 211, 206)
300 0  (213, 210, 205) (214, 211, 206)

- просто образец значений, взятых из того же окна.скриншоты выглядят невооруженным глазом, но я должен сделать некоторые манипуляции с пикселями ... еще одна причина, по которой я хочу использовать нативный подход, заключается в том, что он немного быстрее и ведет себя лучше при работе внутри виртуальных машин с двумя мониторами.Да, довольно сложно, я знаю.

1 Ответ

2 голосов
/ 17 ноября 2010

Для параметра stride необходимо указать размер строки в байтах.Ваши пиксели имеют размер 16 бит каждый, поэтому вы можете наивно предполагать, stride = 2*bmpinfo['bmWidth'];К сожалению, Windows добавляет отступы, чтобы сделать шаг равным 32 битам.Это означает, что вам нужно округлить его до следующего наибольшего значения, кратного 4: stride = (stride + 3) / 4) * 4.

В документации нет 16-битного необработанного формата, поэтому вы получитепроверить модуль Unpack.c, чтобы увидеть, что доступно.

Последнее, что вы заметите, это то, что Windows любит делать свои растровые изображения вверх ногами.

Редактировать: Ваша последняя небольшая проблема легко объяснима - преобразование из 16-битного в 24-битное точно не определено, и различие между двумя различными преобразованиями между ними совершенно нормально.Нетрудно откорректировать данные после преобразования, так как я уверен, что различия постоянны в зависимости от значения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...