OSX和ctypes:如何从CGDataProviderCopyData()检索原始像素?

2024-10-08 22:31:13 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试仅使用ctypes模块捕获屏幕。不幸的是,我无法从CGDataProviderCopyData检索原始像素。我需要访问原始数据:

#!/usr/bin/env python
# coding: utf-8

from sys import maxsize
from ctypes import POINTER, Structure, c_double, byref, c_void_p, c_int32, c_uint32, c_float, cdll
from ctypes.util import find_library


CGFloat = c_double if maxsize > 2 ** 32 else c_float


class CGPoint(Structure):
    _fields_ = [('x', CGFloat), ('y', CGFloat)]


class CGSize(Structure):
    _fields_ = [('width', CGFloat), ('height', CGFloat)]


class CGRect(Structure):
    _fields_ = [('origin', CGPoint), ('size', CGSize)]


# Library
cgs = cdll.LoadLibrary(find_library('CoreGraphics'))

# Argtypes
cgs.CGGetActiveDisplayList.argtypes = [c_uint32, POINTER(c_uint32), POINTER(c_uint32)]
cgs.CGDisplayBounds.argtypes = [c_uint32]
cgs.CGRectStandardize.argtypes = [CGRect]
cgs.CGDisplayRotation.argtypes = [c_uint32]
cgs.CGWindowListCreateImage.argtypes = [CGRect, c_uint32, c_uint32, c_uint32]
cgs.CGImageGetWidth.argtypes = [c_void_p]
cgs.CGImageGetHeight.argtypes = [c_void_p]
cgs.CGImageGetDataProvider.argtypes = [c_void_p]
cgs.CGDataProviderCopyData.argtypes = [c_void_p]
cgs.CGDataProviderRelease.argtypes = [c_void_p]

# Restypes
cgs.CGGetActiveDisplayList.restype = c_int32
cgs.CGDisplayBounds.restype = CGRect
cgs.CGRectStandardize.restype = CGRect
cgs.CGDisplayRotation.restype = c_float
cgs.CGWindowListCreateImage.restype = c_void_p
cgs.CGImageGetWidth.restype = c_uint32
cgs.CGImageGetHeight.restype = c_uint32
cgs.CGImageGetDataProvider.restype = c_void_p
cgs.CGDataProviderCopyData.restype = c_void_p
cgs.CGDataProviderRelease.restype = c_void_p

# Monitors
max_displays = 32
display_count = c_uint32(0)
active_displays = (c_uint32 * max_displays)()
cgs.CGGetActiveDisplayList(max_displays, active_displays, byref(display_count))
for idx in range(display_count.value):
    display = active_displays[idx]
    rect = cgs.CGDisplayBounds(display)
    rect = cgs.CGRectStandardize(rect)

    image_ref = cgs.CGWindowListCreateImage(rect, 1, 0, 0)
    width = int(cgs.CGImageGetWidth(image_ref))
    height = int(cgs.CGImageGetHeight(image_ref))
    prov = cgs.CGImageGetDataProvider(image_ref)
    data = cgs.CGDataProviderCopyData(prov)

    # How to get raw pixels from data`?

MacOS X版本10.11.3。你知道吗

Python版本2.7.10和2.6.9。你知道吗


Tags: fromrectimagerefdisplaystructureuint32void
2条回答

我没有使用CoreGraphics API的经验,但是查看文档,它看起来像CGDataProviderCopyData返回一个CFDataRef对象。用于CFDataRef的文档有一个关于“检查CFData对象”的部分,描述了CFDataGetLength函数和CFDataGetBytePtr函数,它们返回数据的长度和UInt8*。你知道吗

https://developer.apple.com/library/ios/documentation/GraphicsImaging/Reference/CGDataProvider/#//apple_ref/c/func/CGDataProviderCopyData

https://developer.apple.com/library/ios/documentation/CoreFoundation/Reference/CFDataRef/index.html

多亏了Snorfalorpagus,我终于成功了:

#...
data = cgs.CGDataProviderCopyData(prov)
data_ref = cgs.CFDataGetBytePtr(data)
buf_len = cgs.CFDataGetLength()
image_data = cast(data_ref, POINTER(c_ubyte * buf_len))
cgs.CGDataProviderRelease(prov)

# Raw pixels are in image_data.contents

相关问题 更多 >

    热门问题