2010-05-29 30 views
5
đang

Tôi đã có mà phải mất một hình ảnh PIL và chuyển đổi nó vào một mảng ctypes đến ngất xỉu để một hàm C:hiệu quả chuyển đổi chuỗi (hoặc tuple) để ctypes mảng

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) 

Nhưng tôi đối phó với hình ảnh lớn và giải nén nhiều mục vào đối số chức năng có vẻ chậm đáng kể. Điều đơn giản nhất tôi có thể làm để tăng tốc hợp lý là gì?

Tôi chỉ chuyển đổi thành bộ tuple làm bước trung gian, vì vậy nếu không cần thiết, tất cả đều tốt hơn.

+0

Có cũng '(ctypes.c_int * n) .from_buffer', mà bạn có thể sử dụng với chuỗi. Tôi vẫn đang cố gắng tìm cách sử dụng nó mà không cần bước ngay lập tức chuyển đổi PIL 'Image' thành một chuỗi. – Kos

Trả lời

7

Trước tiên, bạn có thể xây dựng một mảng chưa được khởi tạo:

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

và sau đó sao chép nội dung của hình ảnh vào nó:

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

Giá trị trả về của memcpy là một địa chỉ bạn không quan tâm, vì vậy tôi "nuốt" nó bằng cách gán cho nó để đặt tên "dấu gạch dưới đơn" (mà theo quy ước có nghĩa là "Tôi không quan tâm đến cái này" ;-).

Sửa: như @Mu tâm chỉ ra trong một chú thích, đoạn thứ hai một cách hữu ích có thể được đơn giản hóa để sử dụng ctypes.memmove mà không cần phải đi nền tảng phụ thuộc để chồn ra clib: chỉ cần làm

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

Có vẻ như ctypes.memmove thực hiện điều tương tự theo cách không phụ thuộc nền tảng: ctypes.memmove (pixarray, im.tostring(), w_px * h_px * 4) –

+0

@Mu, tuyệt vời, +1 và cảm ơn! Hãy để tôi chỉnh sửa câu trả lời cho phù hợp. –

+0

Rất tiếc, có vẻ như đầu ra có vấn đề về độ dài. Bất kỳ đề xuất? –

Các vấn đề liên quan