将SWIG代理对象作为输入传递给PIL.Image.frombuffer
我正在使用SWIG中的array_class
宏,这个宏在carrays.i文件里定义,用来创建一个无符号字符的缓冲区,这个缓冲区可以发送到我项目的C++部分,负责拍照。这一切都很顺利——在相机触发后,缓冲区里填充了数据,我可以通过Python中的[]来查看这个缓冲区里的内容。现在,我想用这个缓冲区创建一个PIL图像,使用Image.frombuffer
:
Image.frombuffer(mode, size, data) => image
(这是PIL 1.1.4中新增加的功能)。它可以从字符串或缓冲对象中的像素数据创建一个图像内存,使用标准的“原始”解码器。
但是我收到一个错误信息,告诉我我提供的SWIG对象不是一个Python缓冲区:
文件 "/usr/lib/python2.7/dist-packages/PIL/Image.py",第1853行,在frombuffer中
core.map_buffer(data, size, decoder_name, None, 0, args)
TypeError: 期望字符串或缓冲区
我该如何让这个SWIG对象的代理与Image.frombuffer
所期望的缓冲区类型兼容呢?
1 个回答
如果你能处理好SWIG缓冲区的符号问题,你就可以直接创建一个PIL的ImagingMemoryInstance。在libImaging/Imaging.h
这个文件里,你会看到这样的内容:
struct ImagingMemoryInstance {
/* Format */
char mode[4+1]; /* Band names ("1", "L", "P", "RGB", "RGBA", "CMYK") */
int type; /* Data type (IMAGING_TYPE_*) */
int depth; /* Depth (ignored in this version) */
int bands; /* Number of bands (1, 2, 3, or 4) */
int xsize; /* Image dimension. */
int ysize;
/* Colour palette (for "P" images only) */
ImagingPalette palette;
/* Data pointers */
UINT8 **image8; /* Set for 8-bit images (pixelsize=1). */
INT32 **image32; /* Set for 32-bit images (pixelsize=4). */
/* Internals */
char **image; /* Actual raster data. */
char *block; /* Set if data is allocated in a single block. */
int pixelsize; /* Size of a pixel, in bytes (1, 2 or 4) */
int linesize; /* Size of a line, in bytes (xsize * pixelsize) */
/* Virtual methods */
void (*destroy)(Imaging im);
};
... ImagingMemoryInstance*被定义为Imaging
,这是一个基础结构体,你会在PIL的C扩展源代码中到处看到。别光听我说,自己去看看 -- 从API源代码来看,PIL的代码库相当清晰,结构也很合理。
正如@maxy提到的,你也可以很简单(甚至更简单)地创建一个NumPy数组结构体 -- 不过虽然NumPy的C API非常稳定,像是来自Guido的个人使用手册,我个人觉得在这种情况下,依赖一个库的源代码就足够了。