Merge branch 'blender2.7'
[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(PyExc_ReferenceError,
61                              "ImBuf data of type %.200s has been freed",
62                              Py_TYPE(self)->tp_name);
63                 return -1;
64         }
65 }
66
67 #define PY_IMBUF_CHECK_OBJ(obj) \
68         if (UNLIKELY(py_imbuf_valid_check(obj) == -1)) { return NULL; } ((void)0)
69 #define PY_IMBUF_CHECK_INT(obj) \
70         if (UNLIKELY(py_imbuf_valid_check(obj) == -1)) { return -1; }   ((void)0)
71
72 /** \} */
73
74 /* -------------------------------------------------------------------- */
75 /** \name Methods
76  * \{ */
77
78 PyDoc_STRVAR(py_imbuf_resize_doc,
79 ".. method:: resize(size, method='FAST')\n"
80 "\n"
81 "   Resize the image.\n"
82 "\n"
83 "   :arg size: New size.\n"
84 "   :type size: pair of ints\n"
85 "   :arg method: Method of resizing (TODO)\n"
86 "   :type method: str\n"
87 );
88 static PyObject *py_imbuf_resize(Py_ImBuf *self, PyObject *args, PyObject *kw)
89 {
90         PY_IMBUF_CHECK_OBJ(self);
91
92         uint size[2];
93         char *method = NULL;
94
95         static const char *_keywords[] = {"size", "method", NULL};
96         static _PyArg_Parser _parser = {"(II)|s:resize", _keywords, 0};
97         if (!_PyArg_ParseTupleAndKeywordsFast(
98                 args, kw, &_parser,
99                 &size[0], &size[1],
100                 &method))
101         {
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 );
114 static PyObject *py_imbuf_copy(Py_ImBuf *self)
115 {
116         PY_IMBUF_CHECK_OBJ(self);
117         return Py_ImBuf_CreatePyObject(self->ibuf);
118 }
119
120 static PyObject *py_imbuf_deepcopy(Py_ImBuf *self, PyObject *args)
121 {
122         if (!PyC_CheckArgs_DeepCopy(args)) {
123                 return NULL;
124         }
125         return py_imbuf_copy(self);
126 }
127
128
129 PyDoc_STRVAR(py_imbuf_free_doc,
130 ".. method:: free()\n"
131 "\n"
132 "   Clear image data immediately (causing an error on re-use).\n"
133 );
134 static PyObject *py_imbuf_free(Py_ImBuf *self)
135 {
136         if (self->ibuf) {
137                 IMB_freeImBuf(self->ibuf);
138                 self->ibuf = NULL;
139         }
140         Py_RETURN_NONE;
141 }
142
143 static struct PyMethodDef Py_ImBuf_methods[] = {
144         {"resize", (PyCFunction)py_imbuf_resize, METH_VARARGS | METH_KEYWORDS, (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,
159 "size of the image in pixels.\n\n:type: pair of ints"
160 );
161 static PyObject *py_imbuf_size_get(Py_ImBuf *self, void *UNUSED(closure))
162 {
163         PY_IMBUF_CHECK_OBJ(self);
164         ImBuf *ibuf = self->ibuf;
165         return PyC_Tuple_Pack_I32(ibuf->x, ibuf->y);
166 }
167
168 PyDoc_STRVAR(py_imbuf_ppm_doc,
169 "pixels per meter.\n\n:type: pair of floats"
170 );
171 static PyObject *py_imbuf_ppm_get(Py_ImBuf *self, void *UNUSED(closure))
172 {
173         PY_IMBUF_CHECK_OBJ(self);
174         ImBuf *ibuf = self->ibuf;
175         return PyC_Tuple_Pack_F64(ibuf->ppm[0], ibuf->ppm[1]);
176 }
177
178 static int py_imbuf_ppm_set(Py_ImBuf *self, PyObject *value, void *UNUSED(closure))
179 {
180         PY_IMBUF_CHECK_INT(self);
181         double ppm[2];
182
183         if (PyC_AsArray(ppm, value, 2, &PyFloat_Type, true, "ppm") == -1) {
184                 return -1;
185         }
186
187         if (ppm[0] <= 0.0 || ppm[1] <= 0.0) {
188                 PyErr_SetString(PyExc_ValueError, "invalid ppm value");
189                 return -1;
190         }
191
192         ImBuf *ibuf = self->ibuf;
193         ibuf->ppm[0] = ppm[0];
194         ibuf->ppm[1] = ppm[1];
195         return 0;
196 }
197
198 static PyGetSetDef Py_ImBuf_getseters[] = {
199         {(char *)"size", (getter)py_imbuf_size_get, (setter)NULL, (char *)py_imbuf_size_doc, NULL},
200         {(char *)"ppm", (getter)py_imbuf_ppm_get, (setter)py_imbuf_ppm_set, (char *)py_imbuf_ppm_doc, 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)>",
226                         ibuf, ibuf->name, ibuf->x, ibuf->y);
227         }
228         else {
229                 return PyUnicode_FromString(
230                         "<imbuf: address=0x0>");
231         }
232 }
233
234 static Py_hash_t py_imbuf_hash(Py_ImBuf *self)
235 {
236         return _Py_HashPointer(self->ibuf);
237 }
238
239 PyTypeObject Py_ImBuf_Type = {
240         PyVarObject_HEAD_INIT(NULL, 0)
241         /*  For printing, in format "<module>.<name>" */
242         "ImBuf",                    /* tp_name */
243         sizeof(Py_ImBuf),           /* int tp_basicsize; */
244         0,                          /* tp_itemsize;  For allocation */
245
246         /* Methods to implement standard operations */
247
248         (destructor)py_imbuf_dealloc, /* destructor tp_dealloc; */
249         NULL,                       /* printfunc tp_print; */
250         NULL,                       /* getattrfunc tp_getattr; */
251         NULL,                       /* setattrfunc tp_setattr; */
252         NULL,                       /* cmpfunc tp_compare; */
253         (reprfunc)py_imbuf_repr,    /* reprfunc tp_repr; */
254
255         /* Method suites for standard classes */
256
257         NULL,                       /* PyNumberMethods *tp_as_number; */
258         NULL,                       /* PySequenceMethods *tp_as_sequence; */
259         NULL,                       /* PyMappingMethods *tp_as_mapping; */
260
261         /* More standard operations (here for binary compatibility) */
262
263         (hashfunc)py_imbuf_hash,   /* hashfunc tp_hash; */
264         NULL,                       /* ternaryfunc tp_call; */
265         NULL,                       /* reprfunc tp_str; */
266         NULL,                       /* getattrofunc tp_getattro; */
267         NULL,                       /* setattrofunc tp_setattro; */
268
269         /* Functions to access object as input/output buffer */
270         NULL,                       /* PyBufferProcs *tp_as_buffer; */
271
272         /*** Flags to define presence of optional/expanded features ***/
273         Py_TPFLAGS_DEFAULT,         /* long tp_flags; */
274
275         NULL,                       /*  char *tp_doc;  Documentation string */
276         /*** Assigned meaning in release 2.0 ***/
277         /* call function for all accessible objects */
278         NULL,                       /* traverseproc tp_traverse; */
279
280         /* delete references to contained objects */
281         NULL,                       /* inquiry tp_clear; */
282
283         /***  Assigned meaning in release 2.1 ***/
284         /*** rich comparisons ***/
285         NULL,                       /* richcmpfunc tp_richcompare; */
286
287         /***  weak reference enabler ***/
288         0,                          /* long tp_weaklistoffset; */
289
290         /*** Added in release 2.2 ***/
291         /*   Iterators */
292         NULL, /* getiterfunc tp_iter; */
293         NULL,                       /* iternextfunc tp_iternext; */
294         /*** Attribute descriptor and subclassing stuff ***/
295         Py_ImBuf_methods,           /* struct PyMethodDef *tp_methods; */
296         NULL,                       /* struct PyMemberDef *tp_members; */
297         Py_ImBuf_getseters,         /* struct PyGetSetDef *tp_getset; */
298 };
299
300 static PyObject *Py_ImBuf_CreatePyObject(ImBuf *ibuf)
301 {
302         Py_ImBuf *self = PyObject_New(Py_ImBuf, &Py_ImBuf_Type);
303         self->ibuf = ibuf;
304         return (PyObject *)self;
305 }
306
307 /** \} */
308
309 /* -------------------------------------------------------------------- */
310 /** \name Module Functions
311  * \{ */
312
313 PyDoc_STRVAR(M_imbuf_new_doc,
314 ".. function:: new(size)\n"
315 "\n"
316 "   Load a new image.\n"
317 "\n"
318 "   :arg size: The size of the image in pixels.\n"
319 "   :type size: pair of ints\n"
320 "   :return: the newly loaded image.\n"
321 "   :rtype: :class:`ImBuf`\n"
322 );
323 static PyObject *M_imbuf_new(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
324 {
325         int size[2];
326         static const char *_keywords[] = {"size", NULL};
327         static _PyArg_Parser _parser = {"(ii)|i:new", _keywords, 0};
328         if (!_PyArg_ParseTupleAndKeywordsFast(
329                 args, kw, &_parser,
330                 &size[0], &size[1]))
331         {
332                 return NULL;
333         }
334
335         /* TODO, make options */
336         uchar planes = 4;
337         uint flags = IB_rect;
338
339         ImBuf *ibuf = IMB_allocImBuf(UNPACK2(size), planes, flags);
340         if (ibuf == NULL) {
341                 PyErr_Format(PyExc_ValueError, "new: Unable to create image (%d, %d)", UNPACK2(size));
342                 return NULL;
343         }
344         return Py_ImBuf_CreatePyObject(ibuf);
345 }
346
347 PyDoc_STRVAR(M_imbuf_load_doc,
348 ".. function:: load(filename)\n"
349 "\n"
350 "   Load an image from a file.\n"
351 "\n"
352 "   :arg filename: the filename of the image.\n"
353 "   :type filename: string\n"
354 "   :return: the newly loaded image.\n"
355 "   :rtype: :class:`ImBuf`\n"
356 );
357 static PyObject *M_imbuf_load(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
358 {
359         const char *filename;
360
361         static const char *_keywords[] = {"filename", NULL};
362         static _PyArg_Parser _parser = {"s:load", _keywords, 0};
363         if (!_PyArg_ParseTupleAndKeywordsFast(
364                 args, kw, &_parser,
365                 &filename))
366         {
367                 return NULL;
368         }
369
370         const int file = BLI_open(filename, O_BINARY | O_RDONLY, 0);
371         if (file == -1) {
372                 PyErr_Format(PyExc_IOError, "load: %s, failed to open file '%s'", strerror(errno));
373                 return NULL;
374         }
375
376         ImBuf *ibuf = IMB_loadifffile(file, filename, IB_rect, NULL, filename);
377
378         close(file);
379
380         if (ibuf == NULL) {
381                 PyErr_Format(PyExc_ValueError, "load: Unable to recognize image format for file '%s'", filename);
382                 return NULL;
383         }
384
385         BLI_strncpy(ibuf->name, filename, sizeof(ibuf->name));
386
387         return Py_ImBuf_CreatePyObject(ibuf);
388 }
389
390 PyDoc_STRVAR(M_imbuf_write_doc,
391 ".. function:: write(image, filename)\n"
392 "\n"
393 "   Write an image.\n"
394 "\n"
395 "   :arg image: the image to write.\n"
396 "   :type image: :class:`ImBuf`\n"
397 "   :arg filename: the filename of the image.\n"
398 "   :type filename: string\n"
399 );
400 static PyObject *M_imbuf_write(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
401 {
402         Py_ImBuf *py_imb;
403         const char *filename = NULL;
404
405         static const char *_keywords[] = {"image", "filename", NULL};
406         static _PyArg_Parser _parser = {"O!|s:write", _keywords, 0};
407         if (!_PyArg_ParseTupleAndKeywordsFast(
408                     args, kw, &_parser,
409                     &Py_ImBuf_Type, &py_imb,
410                     &filename))
411         {
412                 return NULL;
413         }
414
415         if (filename == NULL) {
416                 filename = py_imb->ibuf->name;
417         }
418
419         bool ok = IMB_saveiff(py_imb->ibuf, filename, IB_rect);
420         if (ok == false) {
421                 PyErr_Format(PyExc_IOError, "write: Unable to write image file (%s) '%s'", strerror(errno), filename);
422                 return NULL;
423         }
424
425         Py_RETURN_NONE;
426 }
427
428 /** \} */
429
430 /* -------------------------------------------------------------------- */
431 /** \name Module Definition
432  * \{ */
433
434 static PyMethodDef IMB_methods[] = {
435         {"new", (PyCFunction) M_imbuf_new, METH_VARARGS | METH_KEYWORDS, M_imbuf_new_doc},
436         {"load", (PyCFunction) M_imbuf_load, METH_VARARGS | METH_KEYWORDS, M_imbuf_load_doc},
437         {"write", (PyCFunction) M_imbuf_write, METH_VARARGS | METH_KEYWORDS, M_imbuf_write_doc},
438         {NULL, NULL, 0, NULL},
439 };
440
441 PyDoc_STRVAR(IMB_doc,
442 "This module provides access to Blender's image manipulation API."
443 );
444 static struct PyModuleDef IMB_module_def = {
445         PyModuleDef_HEAD_INIT,
446         "imbuf",  /* m_name */
447         IMB_doc,  /* m_doc */
448         0,  /* m_size */
449         IMB_methods,  /* m_methods */
450         NULL,  /* m_reload */
451         NULL,  /* m_traverse */
452         NULL,  /* m_clear */
453         NULL,  /* m_free */
454 };
455
456 PyObject *BPyInit_imbuf(void)
457 {
458         PyObject *submodule;
459
460         submodule = PyModule_Create(&IMB_module_def);
461
462         PyType_Ready(&Py_ImBuf_Type);
463
464         return submodule;
465 }
466
467 /** \} */