Image.frombuffer与16位图像数据

如果我的窗口是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位模式? 另外我怎样才能让这个function在任何位深度模式下工作,而不是说必须把它作为parameter passing?

更新:从这个问题我学到了我必须使用“BGR; 16”而不是“BGRX”为第二模式参数。 它需要一个正确的图片,无论是指定的步幅或不。 问题是像素值在某些值上略有偏离:

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

只是从同一个窗口中取得的值的一个样本。 截图看起来与肉眼完全一样,但我必须做一些像素操作..也是我想使用本地方法的原因是它速度更快,在双显示器的虚拟机内部运行时performance更好。 (是的,我觉得很复杂)。

Solutions Collecting From Web of "Image.frombuffer与16位图像数据"

对于stride参数,您需要以字节为单位给出行大小。 你的像素是每个16位,所以你可能天真地假设stride = 2*bmpinfo['bmWidth'] ; 不幸的是,Windows增加了填充以使跨度达到32位的倍数。 这意味着你必须把它四舍五入到4的下一个最高倍数: stride = (stride + 3) / 4) * 4

该文档没有提到16位原始格式,所以你必须检查Unpack.c模块,看看有什么可用的。

最后你会注意到Windows喜欢颠倒位图。

编辑:你最后的小问题很容易解释 – 从16位到24位的转换不是精确定义的,两个不同转换之间的偏差是完全正常的。 转换数据后调整数据并不困难,因为我确定这些差异是基于数值而不变的。