3D View: re-use select id buffer for circle select on cursor-motion
[blender.git] / source / blender / python / generic / imbuf_py_api.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16
17 /** \file
18  * \ingroup pygen
19  *
20  * This file defines the 'imbuf' image manipulation module.
21  */
22
23 #include <Python.h>
24
25 #include "BLI_utildefines.h"
26 #include "BLI_string.h"
27
28 #include "py_capi_utils.h"
29
30 #include "python_utildefines.h"
31
32 #include "imbuf_py_api.h" /* own include */
33
34 #include "../../imbuf/IMB_imbuf.h"
35 #include "../../imbuf/IMB_imbuf_types.h"
36
37 /* File IO */
38 #include <fcntl.h>
39 #include <errno.h>
40 #include "BLI_fileops.h"
41
42 static PyObject *Py_ImBuf_CreatePyObject(ImBuf *ibuf);
43
44 /* -------------------------------------------------------------------- */
45 /** \name Type & Utilities
46  * \{ */
47
48 typedef struct Py_ImBuf {
49   PyObject_VAR_HEAD
50       /* can be NULL */
51       ImBuf *ibuf;
52 } Py_ImBuf;
53
54 static int py_imbuf_valid_check(Py_ImBuf *self)
55 {
56   if (LIKELY(self->ibuf)) {
57     return 0;
58   }
59   else {
60     PyErr_Format(
61         PyExc_ReferenceError, "ImBuf data of type %.200s has been freed", Py_TYPE(self)->tp_name);
62     return -1;
63   }
64 }
65
66 #define PY_IMBUF_CHECK_OBJ(obj) \
67   if (UNLIKELY(py_imbuf_valid_check(obj) == -1)) { \
68     return NULL; \
69   } \
70   ((void)0)
71 #define PY_IMBUF_CHECK_INT(obj) \
72   if (UNLIKELY(py_imbuf_valid_check(obj) == -1)) { \
73     return -1; \
74   } \
75   ((void)0)
76
77 /** \} */
78
79 /* -------------------------------------------------------------------- */
80 /** \name Methods
81  * \{ */
82
83 PyDoc_STRVAR(py_imbuf_resize_doc,
84              ".. method:: resize(size, method='FAST')\n"
85              "\n"
86              "   Resize the image.\n"
87              "\n"
88              "   :arg size: New size.\n"
89              "   :type size: pair of ints\n"
90              "   :arg method: Method of resizing (TODO)\n"
91              "   :type method: str\n");
92 static PyObject *py_imbuf_resize(Py_ImBuf *self, PyObject *args, PyObject *kw)
93 {
94   PY_IMBUF_CHECK_OBJ(self);
95
96   uint size[2];
97   char *method = NULL;
98
99   static const char *_keywords[] = {"size", "method", NULL};
100   static _PyArg_Parser _parser = {"(II)|s:resize", _keywords, 0};
101   if (!_PyArg_ParseTupleAndKeywordsFast(args, kw, &_parser, &size[0], &size[1], &method)) {
102     return NULL;
103   }
104   IMB_scaleImBuf(self->ibuf, UNPACK2(size));
105   Py_RETURN_NONE;
106 }
107
108 PyDoc_STRVAR(py_imbuf_copy_doc,
109              ".. method:: copy()\n"
110              "\n"
111              "   :return: A copy of the image.\n"
112              "   :rtype: :class:`ImBuf`\n");
113 static PyObject *py_imbuf_copy(Py_ImBuf *self)
114 {
115   PY_IMBUF_CHECK_OBJ(self);
116   return Py_ImBuf_CreatePyObject(self->ibuf);
117 }
118
119 static PyObject *py_imbuf_deepcopy(Py_ImBuf *self, PyObject *args)
120 {
121   if (!PyC_CheckArgs_DeepCopy(args)) {
122     return NULL;
123   }
124   return py_imbuf_copy(self);
125 }
126
127 PyDoc_STRVAR(py_imbuf_free_doc,
128              ".. method:: free()\n"
129              "\n"
130              "   Clear image data immediately (causing an error on re-use).\n");
131 static PyObject *py_imbuf_free(Py_ImBuf *self)
132 {
133   if (self->ibuf) {
134     IMB_freeImBuf(self->ibuf);
135     self->ibuf = NULL;
136   }
137   Py_RETURN_NONE;
138 }
139
140 static struct PyMethodDef Py_ImBuf_methods[] = {
141     {"resize",
142      (PyCFunction)py_imbuf_resize,
143      METH_VARARGS | METH_KEYWORDS,
144      (char *)py_imbuf_resize_doc},
145     {"free", (PyCFunction)py_imbuf_free, METH_NOARGS, (char *)py_imbuf_free_doc},
146     {"copy", (PyCFunction)py_imbuf_copy, METH_NOARGS, (char *)py_imbuf_copy_doc},
147     {"__copy__", (PyCFunction)py_imbuf_copy, METH_NOARGS, (char *)py_imbuf_copy_doc},
148     {"__deepcopy__", (PyCFunction)py_imbuf_deepcopy, METH_VARARGS, (char *)py_imbuf_copy_doc},
149     {NULL, NULL, 0, NULL},
150 };
151
152 /** \} */
153
154 /* -------------------------------------------------------------------- */
155 /** \name Attributes
156  * \{ */
157
158 PyDoc_STRVAR(py_imbuf_size_doc, "size of the image in pixels.\n\n:type: pair of ints");
159 static PyObject *py_imbuf_size_get(Py_ImBuf *self, void *UNUSED(closure))
160 {
161   PY_IMBUF_CHECK_OBJ(self);
162   ImBuf *ibuf = self->ibuf;
163   return PyC_Tuple_Pack_I32(ibuf->x, ibuf->y);
164 }
165
166 PyDoc_STRVAR(py_imbuf_ppm_doc, "pixels per meter.\n\n:type: pair of floats");
167 static PyObject *py_imbuf_ppm_get(Py_ImBuf *self, void *UNUSED(closure))
168 {
169   PY_IMBUF_CHECK_OBJ(self);
170   ImBuf *ibuf = self->ibuf;
171   return PyC_Tuple_Pack_F64(ibuf->ppm[0], ibuf->ppm[1]);
172 }
173
174 static int py_imbuf_ppm_set(Py_ImBuf *self, PyObject *value, void *UNUSED(closure))
175 {
176   PY_IMBUF_CHECK_INT(self);
177   double ppm[2];
178
179   if (PyC_AsArray(ppm, value, 2, &PyFloat_Type, true, "ppm") == -1) {
180     return -1;
181   }
182
183   if (ppm[0] <= 0.0 || ppm[1] <= 0.0) {
184     PyErr_SetString(PyExc_ValueError, "invalid ppm value");
185     return -1;
186   }
187
188   ImBuf *ibuf = self->ibuf;
189   ibuf->ppm[0] = ppm[0];
190   ibuf->ppm[1] = ppm[1];
191   return 0;
192 }
193
194 static PyGetSetDef Py_ImBuf_getseters[] = {
195     {(char *)"size", (getter)py_imbuf_size_get, (setter)NULL, (char *)py_imbuf_size_doc, NULL},
196     {(char *)"ppm",
197      (getter)py_imbuf_ppm_get,
198      (setter)py_imbuf_ppm_set,
199      (char *)py_imbuf_ppm_doc,
200      NULL},
201     {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
202 };
203
204 /** \} */
205
206 /* -------------------------------------------------------------------- */
207 /** \name Type & Implementation
208  * \{ */
209
210 static void py_imbuf_dealloc(Py_ImBuf *self)
211 {
212   ImBuf *ibuf = self->ibuf;
213   if (ibuf != NULL) {
214     IMB_freeImBuf(self->ibuf);
215     self->ibuf = NULL;
216   }
217   PyObject_DEL(self);
218 }
219
220 static PyObject *py_imbuf_repr(Py_ImBuf *self)
221 {
222   const ImBuf *ibuf = self->ibuf;
223   if (ibuf != NULL) {
224     return PyUnicode_FromFormat(
225         "<imbuf: address=%p, filename='%s', size=(%d, %d)>", ibuf, ibuf->name, ibuf->x, ibuf->y);
226   }
227   else {
228     return PyUnicode_FromString("<imbuf: address=0x0>");
229   }
230 }
231
232 static Py_hash_t py_imbuf_hash(Py_ImBuf *self)
233 {
234   return _Py_HashPointer(self->ibuf);
235 }
236
237 PyTypeObject Py_ImBuf_Type = {
238     PyVarObject_HEAD_INIT(NULL, 0)
239     /*  For printing, in format "<module>.<name>" */
240     "ImBuf",          /* tp_name */
241     sizeof(Py_ImBuf), /* int tp_basicsize; */
242     0,                /* tp_itemsize;  For allocation */
243
244     /* Methods to implement standard operations */
245
246     (destructor)py_imbuf_dealloc, /* destructor tp_dealloc; */
247     NULL,                         /* printfunc tp_print; */
248     NULL,                         /* getattrfunc tp_getattr; */
249     NULL,                         /* setattrfunc tp_setattr; */
250     NULL,                         /* cmpfunc tp_compare; */
251     (reprfunc)py_imbuf_repr,      /* reprfunc tp_repr; */
252
253     /* Method suites for standard classes */
254
255     NULL, /* PyNumberMethods *tp_as_number; */
256     NULL, /* PySequenceMethods *tp_as_sequence; */
257     NULL, /* PyMappingMethods *tp_as_mapping; */
258
259     /* More standard operations (here for binary compatibility) */
260
261     (hashfunc)py_imbuf_hash, /* hashfunc tp_hash; */
262     NULL,                    /* ternaryfunc tp_call; */
263     NULL,                    /* reprfunc tp_str; */
264     NULL,                    /* getattrofunc tp_getattro; */
265     NULL,                    /* setattrofunc tp_setattro; */
266
267     /* Functions to access object as input/output buffer */
268     NULL, /* PyBufferProcs *tp_as_buffer; */
269
270     /*** Flags to define presence of optional/expanded features ***/
271     Py_TPFLAGS_DEFAULT, /* long tp_flags; */
272
273     NULL, /*  char *tp_doc;  Documentation string */
274     /*** Assigned meaning in release 2.0 ***/
275     /* call function for all accessible objects */
276     NULL, /* traverseproc tp_traverse; */
277
278     /* delete references to contained objects */
279     NULL, /* inquiry tp_clear; */
280
281     /***  Assigned meaning in release 2.1 ***/
282     /*** rich comparisons ***/
283     NULL, /* richcmpfunc tp_richcompare; */
284
285     /***  weak reference enabler ***/
286     0, /* long tp_weaklistoffset; */
287
288     /*** Added in release 2.2 ***/
289     /*   Iterators */
290     NULL, /* getiterfunc tp_iter; */
291     NULL, /* iternextfunc tp_iternext; */
292     /*** Attribute descriptor and subclassing stuff ***/
293     Py_ImBuf_methods,   /* struct PyMethodDef *tp_methods; */
294     NULL,               /* struct PyMemberDef *tp_members; */
295     Py_ImBuf_getseters, /* struct PyGetSetDef *tp_getset; */
296 };
297
298 static PyObject *Py_ImBuf_CreatePyObject(ImBuf *ibuf)
299 {
300   Py_ImBuf *self = PyObject_New(Py_ImBuf, &Py_ImBuf_Type);
301   self->ibuf = ibuf;
302   return (PyObject *)self;
303 }
304
305 /** \} */
306
307 /* -------------------------------------------------------------------- */
308 /** \name Module Functions
309  * \{ */
310
311 PyDoc_STRVAR(M_imbuf_new_doc,
312              ".. function:: new(size)\n"
313              "\n"
314              "   Load a new image.\n"
315              "\n"
316              "   :arg size: The size of the image in pixels.\n"
317              "   :type size: pair of ints\n"
318              "   :return: the newly loaded image.\n"
319              "   :rtype: :class:`ImBuf`\n");
320 static PyObject *M_imbuf_new(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
321 {
322   int size[2];
323   static const char *_keywords[] = {"size", NULL};
324   static _PyArg_Parser _parser = {"(ii)|i:new", _keywords, 0};
325   if (!_PyArg_ParseTupleAndKeywordsFast(args, kw, &_parser, &size[0], &size[1])) {
326     return NULL;
327   }
328
329   /* TODO, make options */
330   uchar planes = 4;
331   uint flags = IB_rect;
332
333   ImBuf *ibuf = IMB_allocImBuf(UNPACK2(size), planes, flags);
334   if (ibuf == NULL) {
335     PyErr_Format(PyExc_ValueError, "new: Unable to create image (%d, %d)", UNPACK2(size));
336     return NULL;
337   }
338   return Py_ImBuf_CreatePyObject(ibuf);
339 }
340
341 PyDoc_STRVAR(M_imbuf_load_doc,
342              ".. function:: load(filename)\n"
343              "\n"
344              "   Load an image from a file.\n"
345              "\n"
346              "   :arg filename: the filename of the image.\n"
347              "   :type filename: string\n"
348              "   :return: the newly loaded image.\n"
349              "   :rtype: :class:`ImBuf`\n");
350 static PyObject *M_imbuf_load(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
351 {
352   const char *filename;
353
354   static const char *_keywords[] = {"filename", NULL};
355   static _PyArg_Parser _parser = {"s:load", _keywords, 0};
356   if (!_PyArg_ParseTupleAndKeywordsFast(args, kw, &_parser, &filename)) {
357     return NULL;
358   }
359
360   const int file = BLI_open(filename, O_BINARY | O_RDONLY, 0);
361   if (file == -1) {
362     PyErr_Format(PyExc_IOError, "load: %s, failed to open file '%s'", strerror(errno));
363     return NULL;
364   }
365
366   ImBuf *ibuf = IMB_loadifffile(file, filename, IB_rect, NULL, filename);
367
368   close(file);
369
370   if (ibuf == NULL) {
371     PyErr_Format(
372         PyExc_ValueError, "load: Unable to recognize image format for file '%s'", filename);
373     return NULL;
374   }
375
376   BLI_strncpy(ibuf->name, filename, sizeof(ibuf->name));
377
378   return Py_ImBuf_CreatePyObject(ibuf);
379 }
380
381 PyDoc_STRVAR(M_imbuf_write_doc,
382              ".. function:: write(image, filename)\n"
383              "\n"
384              "   Write an image.\n"
385              "\n"
386              "   :arg image: the image to write.\n"
387              "   :type image: :class:`ImBuf`\n"
388              "   :arg filename: the filename of the image.\n"
389              "   :type filename: string\n");
390 static PyObject *M_imbuf_write(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
391 {
392   Py_ImBuf *py_imb;
393   const char *filename = NULL;
394
395   static const char *_keywords[] = {"image", "filename", NULL};
396   static _PyArg_Parser _parser = {"O!|s:write", _keywords, 0};
397   if (!_PyArg_ParseTupleAndKeywordsFast(args, kw, &_parser, &Py_ImBuf_Type, &py_imb, &filename)) {
398     return NULL;
399   }
400
401   if (filename == NULL) {
402     filename = py_imb->ibuf->name;
403   }
404
405   bool ok = IMB_saveiff(py_imb->ibuf, filename, IB_rect);
406   if (ok == false) {
407     PyErr_Format(
408         PyExc_IOError, "write: Unable to write image file (%s) '%s'", strerror(errno), filename);
409     return NULL;
410   }
411
412   Py_RETURN_NONE;
413 }
414
415 /** \} */
416
417 /* -------------------------------------------------------------------- */
418 /** \name Module Definition
419  * \{ */
420
421 static PyMethodDef IMB_methods[] = {
422     {"new", (PyCFunction)M_imbuf_new, METH_VARARGS | METH_KEYWORDS, M_imbuf_new_doc},
423     {"load", (PyCFunction)M_imbuf_load, METH_VARARGS | METH_KEYWORDS, M_imbuf_load_doc},
424     {"write", (PyCFunction)M_imbuf_write, METH_VARARGS | METH_KEYWORDS, M_imbuf_write_doc},
425     {NULL, NULL, 0, NULL},
426 };
427
428 PyDoc_STRVAR(IMB_doc, "This module provides access to Blender's image manipulation API.");
429 static struct PyModuleDef IMB_module_def = {
430     PyModuleDef_HEAD_INIT,
431     "imbuf",     /* m_name */
432     IMB_doc,     /* m_doc */
433     0,           /* m_size */
434     IMB_methods, /* m_methods */
435     NULL,        /* m_reload */
436     NULL,        /* m_traverse */
437     NULL,        /* m_clear */
438     NULL,        /* m_free */
439 };
440
441 PyObject *BPyInit_imbuf(void)
442 {
443   PyObject *submodule;
444
445   submodule = PyModule_Create(&IMB_module_def);
446
447   PyType_Ready(&Py_ImBuf_Type);
448
449   return submodule;
450 }
451
452 /** \} */