2010-05-29 15 views
5
código

Tengo que toma una imagen de PIL y la convierte en una matriz ctypes para pasar a una función C:convertir de manera eficiente cadena (o tupla) a ctypes gama

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) 

Pero estoy tratando con imágenes grandes, y desempaquetar muchos elementos en argumentos funcionales parece ser notablemente lento. ¿Qué es lo más simple que puedo hacer para obtener una aceleración razonable?

Solo estoy convirtiendo a una tupla como un paso intermedio, por lo que si no es necesario, mucho mejor.

+0

Hay también '(ctypes.c_int * n) .from_buffer', que puede usar con una cadena. Todavía estoy tratando de encontrar cómo usar eso sin el paso inmediato de convertir la 'Imagen' de PIL a una cadena. – Kos

Respuesta

7

primer lugar, puede construir una matriz sin inicializar:

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

y luego copiar el contenido de la imagen en ella:

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

El valor de retorno de establecimiento de memoria es una dirección que no se preocupan, así que lo "tragué" asignándole el nombre "guión bajo único" (que por convención significa "no me importa esto" ;-).

Editar: como señala @Mu mente en un comentario, el último fragmento útil se puede simplificar a utilizar ctypes.memmove sin la necesidad de ir más dependiente de la plataforma para descubrir a clib: Eso sí,

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

Parece que ctypes.memmove hace lo mismo de una manera independiente de la plataforma: ctypes.memmove (pixarray, im.tostring(), w_px * h_px * 4) –

+0

@Mu, excelente, +1 y ¡gracias! Déjame editar la respuesta en consecuencia. –

+0

Vaya, parece que la salida tiene problemas de endianness. ¿Alguna sugerencia? –

Cuestiones relacionadas