эффективно преобразовать строку (или кортеж) в массив ctypes - PullRequest
5 голосов
/ 29 мая 2010

У меня есть код, который берет изображение PIL и преобразует его в массив ctypes для передачи функции C:

w_px, h_px = img.size
pixels = struct.unpack('%dI'%(w_px*h_px), img.convert('RGBA').tostring())
pixels_array = (ctypes.c_int * len(pixels))(*pixels)

Но я имею дело с большими изображениями, и распаковка такого количества элементов в аргументы функций кажется заметно медленной. Как проще всего добиться разумного ускорения?

Я преобразую в кортеж только в качестве промежуточного шага, так что, если это не нужно, тем лучше.

1 Ответ

7 голосов
/ 29 мая 2010

Сначала вы можете создать неинициализированный массив:

pixarray = (ctypes.c_int * (w_px * h_px))()

, а затем скопируйте в него содержимое изображения:

# dylib in MacOSX, cdll.wincrt in Win, libc.so.? in Unix, ...
clib = ctypes.CDLL('libc.dylib')

_ = clib.memcpy(pixarray, im.tostring(), w_px * h_px * 4)

Возвращаемое значение memcpy - это адрес, который вас не волнует, поэтому я «проглотил» его, присвоив ему имя «единственное подчеркивание» (что по соглашению означает «меня это не волнует»; - ).

Редактировать : поскольку @Mu Mind указывает в комментарии, последний фрагмент может быть с пользой упрощен для использования ctypes.memmove без необходимости зависеть от платформы для поиска. clib: просто сделайте

_ = ctypes.memmove(pixarray, im.tostring(), w_px * h_px * 4)
...