2010-11-16 5 views
0

Si mes fenêtres est en mode profondeur de couleur 32 bits, le code suivant obtient une belle image PIL d'une fenêtre:Image.frombuffer avec 16 bits de données d'image

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 

Cependant, lors de l'exécution en 16 le mode -bit, je reçois l'erreur:

>>> 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 

Comment dois-je faire l'appel frombuffer pour fonctionner en mode 16 bits? Comment puis-je faire fonctionner cette fonction dans n'importe quel mode de profondeur de bits, au lieu de dire que je dois le passer en paramètre? J'ai appris que je dois utiliser "BGR; 16" au lieu de "BGRX" pour le paramètre 2nd mode. Il prend une image correcte, soit en spécifiant la foulée ou non. Le problème est que les valeurs de pixel sont légèrement sur certaines valeurs:

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) 

juste un échantillon de valeurs prises à partir de la même fenêtre. Les captures d'écran sont identiques à l'œil nu, mais je dois faire quelques manipulations de pixels. La raison pour laquelle je veux utiliser l'approche native est qu'elle est un peu plus rapide et se comporte mieux dans les machines virtuelles avec deux moniteurs. . (oui assez compliqué au hasard je sais).

Répondre

2

Pour le paramètre stride, vous devez indiquer la taille de la ligne en octets. Vos pixels sont chacun de 16 bits donc vous pouvez supposer naïvement stride = 2*bmpinfo['bmWidth']; Malheureusement, Windows ajoute un rembourrage pour faire de la foulée un multiple pair de 32 bits. Cela signifie que vous devrez l'arrondir au prochain multiple le plus élevé de 4: stride = (stride + 3)/4) * 4.

Le documentation ne mentionne pas de format brut 16 bits, vous devrez donc vérifier le module Unpack.c pour voir ce qui est disponible. La dernière chose que vous remarquerez est que Windows aime rendre ses bitmaps à l'envers. Votre dernier petit problème est facile à expliquer: la conversion de 16 bits en 24 bits n'est pas définie avec précision, et une différence entre deux conversions est parfaitement normale. Il ne serait pas difficile d'ajuster les données après la conversion, car je suis sûr que les différences sont constantes en fonction de la valeur.

+0

Je suis dense bien sûr mais lequel est le paramètre de foulée? est ce que j'ai actuellement comme un tuple? – Claudiu

+3

'bmpstr, 'raw', 'BGRX', 0, 1)' <- c'est le 0 dans cette ligne –

+0

hmm petit nouveau problème, voir la mise à jour – Claudiu

Questions connexes