Blender V4.3
imbuf_py_api.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
11#include <Python.h>
12
13#include "BLI_rect.h"
14#include "BLI_string.h"
15#include "BLI_utildefines.h"
16
17#include "py_capi_utils.hh"
18
19#include "python_compat.hh"
20#include "python_utildefines.hh"
21
22#include "imbuf_py_api.hh" /* own include */
23
26
27/* File IO */
28#include "BLI_fileops.h"
29#include <cerrno>
30#include <fcntl.h>
31
32static PyObject *BPyInit_imbuf_types(void);
33
34static PyObject *Py_ImBuf_CreatePyObject(ImBuf *ibuf);
35
36/* -------------------------------------------------------------------- */
40struct Py_ImBuf {
41 PyObject_VAR_HEAD
42 /* can be nullptr */
44};
45
47{
48 if (LIKELY(self->ibuf)) {
49 return 0;
50 }
51
52 PyErr_Format(
53 PyExc_ReferenceError, "ImBuf data of type %.200s has been freed", Py_TYPE(self)->tp_name);
54 return -1;
55}
56
57#define PY_IMBUF_CHECK_OBJ(obj) \
58 if (UNLIKELY(py_imbuf_valid_check(obj) == -1)) { \
59 return nullptr; \
60 } \
61 ((void)0)
62#define PY_IMBUF_CHECK_INT(obj) \
63 if (UNLIKELY(py_imbuf_valid_check(obj) == -1)) { \
64 return -1; \
65 } \
66 ((void)0)
67
70/* -------------------------------------------------------------------- */
75 /* Wrap. */
76 py_imbuf_resize_doc,
77 ".. method:: resize(size, method='FAST')\n"
78 "\n"
79 " Resize the image.\n"
80 "\n"
81 " :arg size: New size.\n"
82 " :type size: tuple[int, int]\n"
83 " :arg method: Method of resizing ('FAST', 'BILINEAR')\n"
84 " :type method: str\n");
85static PyObject *py_imbuf_resize(Py_ImBuf *self, PyObject *args, PyObject *kw)
86{
88
89 int size[2];
90
91 enum { FAST, BILINEAR };
92 const PyC_StringEnumItems method_items[] = {
93 {FAST, "FAST"},
94 {BILINEAR, "BILINEAR"},
95 {0, nullptr},
96 };
97 PyC_StringEnum method = {method_items, FAST};
98
99 static const char *_keywords[] = {"size", "method", nullptr};
100 static _PyArg_Parser _parser = {
102 "(ii)" /* `size` */
103 "|$" /* Optional keyword only arguments. */
104 "O&" /* `method` */
105 ":resize",
106 _keywords,
107 nullptr,
108 };
109 if (!_PyArg_ParseTupleAndKeywordsFast(
110 args, kw, &_parser, &size[0], &size[1], PyC_ParseStringEnum, &method))
111 {
112 return nullptr;
113 }
114 if (size[0] <= 0 || size[1] <= 0) {
115 PyErr_Format(PyExc_ValueError, "resize: Image size cannot be below 1 (%d, %d)", UNPACK2(size));
116 return nullptr;
117 }
118
119 if (method.value_found == FAST) {
120 IMB_scale(self->ibuf, UNPACK2(size), IMBScaleFilter::Nearest, false);
121 }
122 else if (method.value_found == BILINEAR) {
123 IMB_scale(self->ibuf, UNPACK2(size), IMBScaleFilter::Box, false);
124 }
125 else {
127 }
128 Py_RETURN_NONE;
129}
130
132 /* Wrap. */
133 py_imbuf_crop_doc,
134 ".. method:: crop(min, max)\n"
135 "\n"
136 " Crop the image.\n"
137 "\n"
138 " :arg min: X, Y minimum.\n"
139 " :type min: tuple[int, int]\n"
140 " :arg max: X, Y maximum.\n"
141 " :type max: tuple[int, int]\n");
142static PyObject *py_imbuf_crop(Py_ImBuf *self, PyObject *args, PyObject *kw)
143{
145
146 rcti crop;
147
148 static const char *_keywords[] = {"min", "max", nullptr};
149 static _PyArg_Parser _parser = {
151 "(II)" /* `min` */
152 "(II)" /* `max` */
153 ":crop",
154 _keywords,
155 nullptr,
156 };
157 if (!_PyArg_ParseTupleAndKeywordsFast(
158 args, kw, &_parser, &crop.xmin, &crop.ymin, &crop.xmax, &crop.ymax))
159 {
160 return nullptr;
161 }
162
163 if (/* X range. */
164 !(crop.xmin >= 0 && crop.xmax < self->ibuf->x) ||
165 /* Y range. */
166 !(crop.ymin >= 0 && crop.ymax < self->ibuf->y) ||
167 /* X order. */
168 !(crop.xmin <= crop.xmax) ||
169 /* Y order. */
170 !(crop.ymin <= crop.ymax))
171 {
172 PyErr_SetString(PyExc_ValueError, "ImBuf crop min/max not in range");
173 return nullptr;
174 }
175 IMB_rect_crop(self->ibuf, &crop);
176 Py_RETURN_NONE;
177}
178
180 /* Wrap. */
181 py_imbuf_copy_doc,
182 ".. method:: copy()\n"
183 "\n"
184 " :return: A copy of the image.\n"
185 " :rtype: :class:`ImBuf`\n");
186static PyObject *py_imbuf_copy(Py_ImBuf *self)
187{
189 ImBuf *ibuf_copy = IMB_dupImBuf(self->ibuf);
190
191 if (UNLIKELY(ibuf_copy == nullptr)) {
192 PyErr_SetString(PyExc_MemoryError,
193 "ImBuf.copy(): "
194 "failed to allocate memory");
195 return nullptr;
196 }
197 return Py_ImBuf_CreatePyObject(ibuf_copy);
198}
199
200static PyObject *py_imbuf_deepcopy(Py_ImBuf *self, PyObject *args)
201{
202 if (!PyC_CheckArgs_DeepCopy(args)) {
203 return nullptr;
204 }
205 return py_imbuf_copy(self);
206}
207
209 /* Wrap. */
210 py_imbuf_free_doc,
211 ".. method:: free()\n"
212 "\n"
213 " Clear image data immediately (causing an error on re-use).\n");
214static PyObject *py_imbuf_free(Py_ImBuf *self)
215{
216 if (self->ibuf) {
217 IMB_freeImBuf(self->ibuf);
218 self->ibuf = nullptr;
219 }
220 Py_RETURN_NONE;
221}
222
223#if (defined(__GNUC__) && !defined(__clang__))
224# pragma GCC diagnostic push
225# pragma GCC diagnostic ignored "-Wcast-function-type"
226#endif
227
228static PyMethodDef Py_ImBuf_methods[] = {
229 {"resize", (PyCFunction)py_imbuf_resize, METH_VARARGS | METH_KEYWORDS, py_imbuf_resize_doc},
230 {"crop", (PyCFunction)py_imbuf_crop, METH_VARARGS | METH_KEYWORDS, (char *)py_imbuf_crop_doc},
231 {"free", (PyCFunction)py_imbuf_free, METH_NOARGS, py_imbuf_free_doc},
232 {"copy", (PyCFunction)py_imbuf_copy, METH_NOARGS, py_imbuf_copy_doc},
233 {"__copy__", (PyCFunction)py_imbuf_copy, METH_NOARGS, py_imbuf_copy_doc},
234 {"__deepcopy__", (PyCFunction)py_imbuf_deepcopy, METH_VARARGS, py_imbuf_copy_doc},
235 {nullptr, nullptr, 0, nullptr},
236};
237
238#if (defined(__GNUC__) && !defined(__clang__))
239# pragma GCC diagnostic pop
240#endif
241
244/* -------------------------------------------------------------------- */
249 /* Wrap. */
250 py_imbuf_size_doc,
251 "size of the image in pixels.\n"
252 "\n"
253 ":type: pair of ints");
254static PyObject *py_imbuf_size_get(Py_ImBuf *self, void * /*closure*/)
255{
257 ImBuf *ibuf = self->ibuf;
258 return PyC_Tuple_Pack_I32({ibuf->x, ibuf->y});
259}
260
262 /* Wrap. */
263 py_imbuf_ppm_doc,
264 "pixels per meter.\n"
265 "\n"
266 ":type: pair of floats");
267static PyObject *py_imbuf_ppm_get(Py_ImBuf *self, void * /*closure*/)
268{
270 ImBuf *ibuf = self->ibuf;
271 return PyC_Tuple_Pack_F64({ibuf->ppm[0], ibuf->ppm[1]});
272}
273
274static int py_imbuf_ppm_set(Py_ImBuf *self, PyObject *value, void * /*closure*/)
275{
277 double ppm[2];
278
279 if (PyC_AsArray(ppm, sizeof(*ppm), value, 2, &PyFloat_Type, "ppm") == -1) {
280 return -1;
281 }
282
283 if (ppm[0] <= 0.0 || ppm[1] <= 0.0) {
284 PyErr_SetString(PyExc_ValueError, "invalid ppm value");
285 return -1;
286 }
287
288 ImBuf *ibuf = self->ibuf;
289 ibuf->ppm[0] = ppm[0];
290 ibuf->ppm[1] = ppm[1];
291 return 0;
292}
293
295 /* Wrap. */
296 py_imbuf_filepath_doc,
297 "filepath associated with this image.\n"
298 "\n"
299 ":type: str");
300static PyObject *py_imbuf_filepath_get(Py_ImBuf *self, void * /*closure*/)
301{
303 ImBuf *ibuf = self->ibuf;
304 return PyC_UnicodeFromBytes(ibuf->filepath);
305}
306
307static int py_imbuf_filepath_set(Py_ImBuf *self, PyObject *value, void * /*closure*/)
308{
310
311 if (!PyUnicode_Check(value)) {
312 PyErr_SetString(PyExc_TypeError, "expected a string!");
313 return -1;
314 }
315
316 ImBuf *ibuf = self->ibuf;
317 const Py_ssize_t value_str_len_max = sizeof(ibuf->filepath);
318 Py_ssize_t value_str_len;
319 const char *value_str = PyUnicode_AsUTF8AndSize(value, &value_str_len);
320 if (value_str_len >= value_str_len_max) {
321 PyErr_Format(PyExc_TypeError, "filepath length over %zd", value_str_len_max - 1);
322 return -1;
323 }
324 memcpy(ibuf->filepath, value_str, value_str_len + 1);
325 return 0;
326}
327
329 /* Wrap. */
330 py_imbuf_planes_doc,
331 "Number of bits associated with this image.\n"
332 "\n"
333 ":type: int");
334static PyObject *py_imbuf_planes_get(Py_ImBuf *self, void * /*closure*/)
335{
337 ImBuf *imbuf = self->ibuf;
338 return PyLong_FromLong(imbuf->planes);
339}
340
342 /* Wrap. */
343 py_imbuf_channels_doc,
344 "Number of bit-planes.\n"
345 "\n"
346 ":type: int");
347static PyObject *py_imbuf_channels_get(Py_ImBuf *self, void * /*closure*/)
348{
350 ImBuf *imbuf = self->ibuf;
351 return PyLong_FromLong(imbuf->channels);
352}
353
354static PyGetSetDef Py_ImBuf_getseters[] = {
355 {"size", (getter)py_imbuf_size_get, (setter) nullptr, py_imbuf_size_doc, nullptr},
356 {"ppm", (getter)py_imbuf_ppm_get, (setter)py_imbuf_ppm_set, py_imbuf_ppm_doc, nullptr},
357 {"filepath",
358 (getter)py_imbuf_filepath_get,
359 (setter)py_imbuf_filepath_set,
360 py_imbuf_filepath_doc,
361 nullptr},
362 {"planes", (getter)py_imbuf_planes_get, nullptr, py_imbuf_planes_doc, nullptr},
363 {"channels", (getter)py_imbuf_channels_get, nullptr, py_imbuf_channels_doc, nullptr},
364 {nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
365};
366
369/* -------------------------------------------------------------------- */
374{
375 ImBuf *ibuf = self->ibuf;
376 if (ibuf != nullptr) {
377 IMB_freeImBuf(self->ibuf);
378 self->ibuf = nullptr;
379 }
380 PyObject_DEL(self);
381}
382
383static PyObject *py_imbuf_repr(Py_ImBuf *self)
384{
385 const ImBuf *ibuf = self->ibuf;
386 if (ibuf != nullptr) {
387 return PyUnicode_FromFormat("<imbuf: address=%p, filepath='%s', size=(%d, %d)>",
388 ibuf,
389 ibuf->filepath,
390 ibuf->x,
391 ibuf->y);
392 }
393
394 return PyUnicode_FromString("<imbuf: address=0x0>");
395}
396
397static Py_hash_t py_imbuf_hash(Py_ImBuf *self)
398{
399 return _Py_HashPointer(self->ibuf);
400}
401
402PyTypeObject Py_ImBuf_Type = {
403 /*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
404 /*tp_name*/ "ImBuf",
405 /*tp_basicsize*/ sizeof(Py_ImBuf),
406 /*tp_itemsize*/ 0,
407 /*tp_dealloc*/ (destructor)py_imbuf_dealloc,
408 /*tp_vectorcall_offset*/ 0,
409 /*tp_getattr*/ nullptr,
410 /*tp_setattr*/ nullptr,
411 /*tp_as_async*/ nullptr,
412 /*tp_repr*/ (reprfunc)py_imbuf_repr,
413 /*tp_as_number*/ nullptr,
414 /*tp_as_sequence*/ nullptr,
415 /*tp_as_mapping*/ nullptr,
416 /*tp_hash*/ (hashfunc)py_imbuf_hash,
417 /*tp_call*/ nullptr,
418 /*tp_str*/ nullptr,
419 /*tp_getattro*/ nullptr,
420 /*tp_setattro*/ nullptr,
421 /*tp_as_buffer*/ nullptr,
422 /*tp_flags*/ Py_TPFLAGS_DEFAULT,
423 /*tp_doc*/ nullptr,
424 /*tp_traverse*/ nullptr,
425 /*tp_clear*/ nullptr,
426 /*tp_richcompare*/ nullptr,
427 /*tp_weaklistoffset*/ 0,
428 /*tp_iter*/ nullptr,
429 /*tp_iternext*/ nullptr,
430 /*tp_methods*/ Py_ImBuf_methods,
431 /*tp_members*/ nullptr,
432 /*tp_getset*/ Py_ImBuf_getseters,
433 /*tp_base*/ nullptr,
434 /*tp_dict*/ nullptr,
435 /*tp_descr_get*/ nullptr,
436 /*tp_descr_set*/ nullptr,
437 /*tp_dictoffset*/ 0,
438 /*tp_init*/ nullptr,
439 /*tp_alloc*/ nullptr,
440 /*tp_new*/ nullptr,
441 /*tp_free*/ nullptr,
442 /*tp_is_gc*/ nullptr,
443 /*tp_bases*/ nullptr,
444 /*tp_mro*/ nullptr,
445 /*tp_cache*/ nullptr,
446 /*tp_subclasses*/ nullptr,
447 /*tp_weaklist*/ nullptr,
448 /*tp_del*/ nullptr,
449 /*tp_version_tag*/ 0,
450 /*tp_finalize*/ nullptr,
451 /*tp_vectorcall*/ nullptr,
452};
453
454static PyObject *Py_ImBuf_CreatePyObject(ImBuf *ibuf)
455{
456 Py_ImBuf *self = PyObject_New(Py_ImBuf, &Py_ImBuf_Type);
457 self->ibuf = ibuf;
458 return (PyObject *)self;
459}
460
463/* -------------------------------------------------------------------- */
468 /* Wrap. */
469 M_imbuf_new_doc,
470 ".. function:: new(size)\n"
471 "\n"
472 " Load a new image.\n"
473 "\n"
474 " :arg size: The size of the image in pixels.\n"
475 " :type size: tuple[int, int]\n"
476 " :return: the newly loaded image.\n"
477 " :rtype: :class:`ImBuf`\n");
478static PyObject *M_imbuf_new(PyObject * /*self*/, PyObject *args, PyObject *kw)
479{
480 int size[2];
481 static const char *_keywords[] = {"size", nullptr};
482 static _PyArg_Parser _parser = {
484 "(ii)" /* `size` */
485 ":new",
486 _keywords,
487 nullptr,
488 };
489 if (!_PyArg_ParseTupleAndKeywordsFast(args, kw, &_parser, &size[0], &size[1])) {
490 return nullptr;
491 }
492 if (size[0] <= 0 || size[1] <= 0) {
493 PyErr_Format(PyExc_ValueError, "new: Image size cannot be below 1 (%d, %d)", UNPACK2(size));
494 return nullptr;
495 }
496
497 /* TODO: make options. */
498 const uchar planes = 4;
499 const uint flags = IB_rect;
500
501 ImBuf *ibuf = IMB_allocImBuf(UNPACK2(size), planes, flags);
502 if (ibuf == nullptr) {
503 PyErr_Format(PyExc_ValueError, "new: Unable to create image (%d, %d)", UNPACK2(size));
504 return nullptr;
505 }
506 return Py_ImBuf_CreatePyObject(ibuf);
507}
508
509static PyObject *imbuf_load_impl(const char *filepath)
510{
511 const int file = BLI_open(filepath, O_BINARY | O_RDONLY, 0);
512 if (file == -1) {
513 PyErr_Format(PyExc_IOError, "load: %s, failed to open file '%s'", strerror(errno), filepath);
514 return nullptr;
515 }
516
517 ImBuf *ibuf = IMB_loadifffile(file, IB_rect, nullptr, filepath);
518
519 close(file);
520
521 if (ibuf == nullptr) {
522 PyErr_Format(
523 PyExc_ValueError, "load: Unable to recognize image format for file '%s'", filepath);
524 return nullptr;
525 }
526
527 STRNCPY(ibuf->filepath, filepath);
528
529 return Py_ImBuf_CreatePyObject(ibuf);
530}
531
533 /* Wrap. */
534 M_imbuf_load_doc,
535 ".. function:: load(filepath)\n"
536 "\n"
537 " Load an image from a file.\n"
538 "\n"
539 " :arg filepath: the filepath of the image.\n"
540 " :type filepath: str | bytes\n"
541 " :return: the newly loaded image.\n"
542 " :rtype: :class:`ImBuf`\n");
543static PyObject *M_imbuf_load(PyObject * /*self*/, PyObject *args, PyObject *kw)
544{
545 PyC_UnicodeAsBytesAndSize_Data filepath_data = {nullptr};
546
547 static const char *_keywords[] = {"filepath", nullptr};
548 static _PyArg_Parser _parser = {
550 "O&" /* `filepath` */
551 ":load",
552 _keywords,
553 nullptr,
554 };
555 if (!_PyArg_ParseTupleAndKeywordsFast(
556 args, kw, &_parser, PyC_ParseUnicodeAsBytesAndSize, &filepath_data))
557 {
558 return nullptr;
559 }
560
561 PyObject *result = imbuf_load_impl(filepath_data.value);
562 Py_XDECREF(filepath_data.value_coerce);
563 return result;
564}
565
566static PyObject *imbuf_write_impl(ImBuf *ibuf, const char *filepath)
567{
568 const bool ok = IMB_saveiff(ibuf, filepath, IB_rect);
569 if (ok == false) {
570 PyErr_Format(
571 PyExc_IOError, "write: Unable to write image file (%s) '%s'", strerror(errno), filepath);
572 return nullptr;
573 }
574 Py_RETURN_NONE;
575}
576
578 /* Wrap. */
579 M_imbuf_write_doc,
580 ".. function:: write(image, filepath=image.filepath)\n"
581 "\n"
582 " Write an image.\n"
583 "\n"
584 " :arg image: the image to write.\n"
585 " :type image: :class:`ImBuf`\n"
586 " :arg filepath: Optional filepath of the image (fallback to the images file path).\n"
587 " :type filepath: str | bytes | None\n");
588static PyObject *M_imbuf_write(PyObject * /*self*/, PyObject *args, PyObject *kw)
589{
590 Py_ImBuf *py_imb;
591 PyC_UnicodeAsBytesAndSize_Data filepath_data = {nullptr};
592
593 static const char *_keywords[] = {"image", "filepath", nullptr};
594 static _PyArg_Parser _parser = {
596 "O!" /* `image` */
597 "|$" /* Optional keyword only arguments. */
598 "O&" /* `filepath` */
599 ":write",
600 _keywords,
601 nullptr,
602 };
603 if (!_PyArg_ParseTupleAndKeywordsFast(args,
604 kw,
605 &_parser,
607 &py_imb,
609 &filepath_data))
610 {
611 return nullptr;
612 }
613
614 const char *filepath = filepath_data.value;
615 if (filepath == nullptr) {
616 /* Argument omitted, use images path. */
617 filepath = py_imb->ibuf->filepath;
618 }
619 PyObject *result = imbuf_write_impl(py_imb->ibuf, filepath);
620 Py_XDECREF(filepath_data.value_coerce);
621 return result;
622}
623
626/* -------------------------------------------------------------------- */
630#if (defined(__GNUC__) && !defined(__clang__))
631# pragma GCC diagnostic push
632# pragma GCC diagnostic ignored "-Wcast-function-type"
633#endif
634
635static PyMethodDef IMB_methods[] = {
636 {"new", (PyCFunction)M_imbuf_new, METH_VARARGS | METH_KEYWORDS, M_imbuf_new_doc},
637 {"load", (PyCFunction)M_imbuf_load, METH_VARARGS | METH_KEYWORDS, M_imbuf_load_doc},
638 {"write", (PyCFunction)M_imbuf_write, METH_VARARGS | METH_KEYWORDS, M_imbuf_write_doc},
639 {nullptr, nullptr, 0, nullptr},
640};
641
642#if (defined(__GNUC__) && !defined(__clang__))
643# pragma GCC diagnostic pop
644#endif
645
647 /* Wrap. */
648 IMB_doc,
649 "This module provides access to Blender's image manipulation API.\n"
650 "\n"
651 "It provides access to image buffers outside of Blender's\n"
652 ":class:`bpy.types.Image` data-block context.\n");
653static PyModuleDef IMB_module_def = {
654 /*m_base*/ PyModuleDef_HEAD_INIT,
655 /*m_name*/ "imbuf",
656 /*m_doc*/ IMB_doc,
657 /*m_size*/ 0,
658 /*m_methods*/ IMB_methods,
659 /*m_slots*/ nullptr,
660 /*m_traverse*/ nullptr,
661 /*m_clear*/ nullptr,
662 /*m_free*/ nullptr,
663};
664
665PyObject *BPyInit_imbuf()
666{
667 PyObject *mod;
668 PyObject *submodule;
669 PyObject *sys_modules = PyImport_GetModuleDict();
670
671 mod = PyModule_Create(&IMB_module_def);
672
673 /* `imbuf.types` */
674 PyModule_AddObject(mod, "types", (submodule = BPyInit_imbuf_types()));
675 PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
676
677 return mod;
678}
679
682/* -------------------------------------------------------------------- */
690 /* Wrap. */
691 IMB_types_doc,
692 "This module provides access to image buffer types.\n"
693 "\n"
694 ".. note::\n"
695 "\n"
696 " Image buffer is also the structure used by :class:`bpy.types.Image`\n"
697 " ID type to store and manipulate image data at runtime.\n");
698
699static PyModuleDef IMB_types_module_def = {
700 /*m_base*/ PyModuleDef_HEAD_INIT,
701 /*m_name*/ "imbuf.types",
702 /*m_doc*/ IMB_types_doc,
703 /*m_size*/ 0,
704 /*m_methods*/ nullptr,
705 /*m_slots*/ nullptr,
706 /*m_traverse*/ nullptr,
707 /*m_clear*/ nullptr,
708 /*m_free*/ nullptr,
709};
710
712{
713 PyObject *submodule = PyModule_Create(&IMB_types_module_def);
714
715 if (PyType_Ready(&Py_ImBuf_Type) < 0) {
716 return nullptr;
717 }
718
719 PyModule_AddType(submodule, &Py_ImBuf_Type);
720
721 return submodule;
722}
723
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
File and directory operations.
#define O_BINARY
int BLI_open(const char *filepath, int oflag, int pmode) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
#define STRNCPY(dst, src)
Definition BLI_string.h:593
unsigned char uchar
unsigned int uint
#define UNPACK2(a)
#define UNLIKELY(x)
#define LIKELY(x)
ImBuf * IMB_loadifffile(int file, int flags, char colorspace[IM_MAX_SPACE], const char *descr)
Definition readimage.cc:118
ImBuf * IMB_dupImBuf(const ImBuf *ibuf1)
void IMB_rect_crop(ImBuf *ibuf, const rcti *crop)
Definition rectop.cc:240
bool IMB_scale(ImBuf *ibuf, unsigned int newx, unsigned int newy, IMBScaleFilter filter, bool threaded=true)
Definition scaling.cc:779
Contains defines and structs used throughout the imbuf module.
@ IB_rect
PyObject * self
struct ImBuf * IMB_allocImBuf(unsigned int, unsigned int, unsigned char, unsigned int)
bool IMB_saveiff(struct ImBuf *, const char *, int)
void IMB_freeImBuf(ImBuf *)
static PyObject * Py_ImBuf_CreatePyObject(ImBuf *ibuf)
static PyObject * py_imbuf_filepath_get(Py_ImBuf *self, void *)
static PyObject * M_imbuf_load(PyObject *, PyObject *args, PyObject *kw)
static PyObject * py_imbuf_planes_get(Py_ImBuf *self, void *)
static PyObject * py_imbuf_channels_get(Py_ImBuf *self, void *)
static int py_imbuf_filepath_set(Py_ImBuf *self, PyObject *value, void *)
static PyObject * M_imbuf_write(PyObject *, PyObject *args, PyObject *kw)
static PyObject * py_imbuf_size_get(Py_ImBuf *self, void *)
static PyObject * imbuf_load_impl(const char *filepath)
static PyObject * py_imbuf_copy(Py_ImBuf *self)
static PyObject * py_imbuf_resize(Py_ImBuf *self, PyObject *args, PyObject *kw)
static Py_hash_t py_imbuf_hash(Py_ImBuf *self)
#define PY_IMBUF_CHECK_OBJ(obj)
static PyMethodDef IMB_methods[]
static PyObject * M_imbuf_new(PyObject *, PyObject *args, PyObject *kw)
#define PY_IMBUF_CHECK_INT(obj)
static PyObject * py_imbuf_ppm_get(Py_ImBuf *self, void *)
static PyModuleDef IMB_module_def
static PyObject * py_imbuf_crop(Py_ImBuf *self, PyObject *args, PyObject *kw)
static int py_imbuf_ppm_set(Py_ImBuf *self, PyObject *value, void *)
static PyObject * py_imbuf_repr(Py_ImBuf *self)
static PyObject * imbuf_write_impl(ImBuf *ibuf, const char *filepath)
PyObject * BPyInit_imbuf()
static PyObject * py_imbuf_free(Py_ImBuf *self)
static PyGetSetDef Py_ImBuf_getseters[]
PyTypeObject Py_ImBuf_Type
static PyMethodDef Py_ImBuf_methods[]
static PyObject * BPyInit_imbuf_types(void)
static int py_imbuf_valid_check(Py_ImBuf *self)
static PyModuleDef IMB_types_module_def
static void py_imbuf_dealloc(Py_ImBuf *self)
static PyObject * py_imbuf_deepcopy(Py_ImBuf *self, PyObject *args)
PyDoc_STRVAR(py_imbuf_resize_doc, ".. method:: resize(size, method='FAST')\n" "\n" " Resize the image.\n" "\n" " :arg size: New size.\n" " :type size: tuple[int, int]\n" " :arg method: Method of resizing ('FAST', 'BILINEAR')\n" " :type method: str\n")
int PyC_CheckArgs_DeepCopy(PyObject *args)
int PyC_ParseUnicodeAsBytesAndSize(PyObject *o, void *p)
int PyC_ParseStringEnum(PyObject *o, void *p)
PyObject * PyC_UnicodeFromBytes(const char *str)
int PyC_AsArray(void *array, const size_t array_item_size, PyObject *value, const Py_ssize_t length, const PyTypeObject *type, const char *error_prefix)
int PyC_ParseUnicodeAsBytesAndSize_OrNone(PyObject *o, void *p)
PyObject * PyC_Tuple_Pack_I32(const blender::Span< int > values)
PyObject * PyC_Tuple_Pack_F64(const blender::Span< double > values)
header-only compatibility defines.
#define PY_ARG_PARSER_HEAD_COMPAT()
header-only utilities
char filepath[IMB_FILEPATH_SIZE]
unsigned char planes
double ppm[2]
PyObject_VAR_HEAD ImBuf * ibuf
int ymin
int ymax
int xmin
int xmax
ccl_device_inline int mod(int x, int m)
Definition util/math.h:520