Python 3.x バッファー インターフェイスを介して画像ピクセル情報 (32 ビット RGBA) のバッファーを公開しようとしています。かなり遊んだ後、私はこれを次のように機能させることができました:
int Image_get_buffer(PyObject* self, Py_buffer* view, int flags)
{
int img_len;
void* img_bytes;
// Do my image fetch magic
get_image_pixel_data(self, &img_bytes, &img_len);
// Let python fill my buffer
PyBuffer_FillInfo(view, self, img_bytes, img_len, 0, flags);
}
そしてPythonでは、次のように遊ぶことができます:
mv = memoryview(image)
print(mv[0]) # prints b'\x00'
mv[0] = b'\xFF' # set the first pixels red component to full
mx[0:4] = b'\xFF\xFF\xFF\xFF' # set the first pixel to white
そして、それは見事に機能します。ただし、個々のバイトではなく、完全なピクセル値 (int、4 バイト) で作業できれば素晴らしいので、バッファ フェッチを次のように変更しました。
int Image_get_buffer(PyObject* self, Py_buffer* view, int flags)
{
int img_len;
void* img_bytes;
// Do my image fetch magic
get_image_pixel_data(self, &img_bytes, &img_len);
// Fill my buffer manually (derived from the PyBuffer_FillInfo source)
Py_INCREF(self);
view->readonly = 0;
view->obj = self;
view->buf = img_bytes;
view->itemsize = 4;
view->ndim = 1;
view->len = img_len;
view->suboffsets = NULL;
view->format = NULL;
if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT)
view->format = "I";
view->shape = NULL;
if ((flags & PyBUF_ND) == PyBUF_ND)
{
Py_ssize_t shape[] = { (int)(img_len/4) };
view->shape = shape;
}
view->strides = NULL;
if((flags & PyBUF_STRIDED) == PyBUF_STRIDED)
{
Py_ssize_t strides[] = { 4 };
view->strides = strides;
}
return 0;
}
これは実際にデータを返し、正しく読み取ることができますが、値を代入しようとすると失敗します!
mv = memoryview(image)
print(mv[0]) # prints b'\x00\x00\x00\x00'
mv[0] = 0xFFFFFFFF # ERROR (1)
mv[0] = b'\xFF\xFF\xFF\xFF' # ERROR! (2)
mv[0] = mv[0] # ERROR?!? (3)
ケース 1 の場合、エラーで が通知されますが'int' does not support the buffer interface
、これは残念で少し混乱します (結局、バッファー形式が "I" であることを指定しました) が、対処できます。mismatching item sizes for "my.Image" and "bytes"
ただし、2 と 3 の場合は非常に奇妙になりますmy.Image
。
私が渡すデータは明らかにその要素から得られるものと同じサイズであるため、これは私にとって非常に混乱します。itemsize が 1 より大きい場合、バッファは単純に代入を許可しないように見えます。もちろん、このインターフェイスのドキュメントは非常にまばらで、Python コードを熟読しても実際には使用例がまったく得られないため、かなり行き詰まっています。「itemsize > 1 の場合、バッファは本質的に役に立たなくなる」というドキュメントの一部が欠けているのでしょうか、何か間違ったことをしているのに見えないのでしょうか、それとも Python のバグですか? (3.1.1に対するテスト)
この(確かに高度な)問題についてあなたが与えることができる洞察に感謝します!