PyAPI: add imbuf.load_from_buffer to support loading images from memory

Add a Python wrapper for IMB_load_image_from_memory.
This commit is contained in:
Campbell Barton
2025-04-12 18:56:12 +10:00
parent d700bc5f54
commit 10e1aaf02c

View File

@@ -570,6 +570,72 @@ static PyObject *M_imbuf_load(PyObject * /*self*/, PyObject *args, PyObject *kw)
return result;
}
static PyObject *imbuf_load_from_memory_impl(const char *buffer,
const size_t buffer_size,
int flags)
{
ImBuf *ibuf = IMB_load_image_from_memory(
reinterpret_cast<const uchar *>(buffer), buffer_size, flags, "<imbuf.load_from_buffer>");
if (ibuf == nullptr) {
PyErr_Format(PyExc_ValueError, "load_from_buffer: Unable to load image from memory");
return nullptr;
}
return Py_ImBuf_CreatePyObject(ibuf);
}
PyDoc_STRVAR(
/* Wrap. */
M_imbuf_load_from_buffer_doc,
".. function:: load_from_buffer(buffer)\n"
"\n"
" Load an image from a buffer.\n"
"\n"
" :arg buffer: A buffer containing the image data.\n"
" :type buffer: collections.abc.Buffer\n"
" :return: the newly loaded image.\n"
" :rtype: :class:`ImBuf`\n");
static PyObject *M_imbuf_load_from_buffer(PyObject * /*self*/, PyObject *args, PyObject *kw)
{
PyObject *buffer_py_ob;
static const char *_keywords[] = {"buffer", nullptr};
static _PyArg_Parser _parser = {
PY_ARG_PARSER_HEAD_COMPAT()
"O" /* `buffer` */
":load_from_buffer",
_keywords,
nullptr,
};
if (!_PyArg_ParseTupleAndKeywordsFast(args, kw, &_parser, &buffer_py_ob)) {
return nullptr;
}
PyObject *result = nullptr;
/* TODO: should be arguments. */
int flags = IB_byte_data;
/* This supports `PyBytes`, no need for a separate check. */
if (PyObject_CheckBuffer(buffer_py_ob)) {
Py_buffer pybuffer;
if (PyObject_GetBuffer(buffer_py_ob, &pybuffer, PyBUF_SIMPLE) == -1) {
return nullptr;
}
result = imbuf_load_from_memory_impl(
reinterpret_cast<const char *>(pybuffer.buf), pybuffer.len, flags);
PyBuffer_Release(&pybuffer);
}
else {
PyErr_Format(PyExc_TypeError,
"load_from_buffer: expected a buffer, unsupported type %.200s",
Py_TYPE(buffer_py_ob)->tp_name);
return nullptr;
}
return result;
}
static PyObject *imbuf_write_impl(ImBuf *ibuf, const char *filepath)
{
const bool ok = IMB_save_image(ibuf, filepath, IB_byte_data);
@@ -647,6 +713,10 @@ static PyObject *M_imbuf_write(PyObject * /*self*/, PyObject *args, PyObject *kw
static PyMethodDef IMB_methods[] = {
{"new", (PyCFunction)M_imbuf_new, METH_VARARGS | METH_KEYWORDS, M_imbuf_new_doc},
{"load", (PyCFunction)M_imbuf_load, METH_VARARGS | METH_KEYWORDS, M_imbuf_load_doc},
{"load_from_buffer",
(PyCFunction)M_imbuf_load_from_buffer,
METH_VARARGS | METH_KEYWORDS,
M_imbuf_load_from_buffer_doc},
{"write", (PyCFunction)M_imbuf_write, METH_VARARGS | METH_KEYWORDS, M_imbuf_write_doc},
{nullptr, nullptr, 0, nullptr},
};