Merge with -r 22620:23107.
[blender.git] / source / gameengine / VideoTexture / ImageBase.cpp
1 /* $Id$
2 -----------------------------------------------------------------------------
3 This source file is part of VideoTexture library
4
5 Copyright (c) 2007 The Zdeno Ash Miklas
6
7 This program is free software; you can redistribute it and/or modify it under
8 the terms of the GNU Lesser General Public License as published by the Free Software
9 Foundation; either version 2 of the License, or (at your option) any later
10 version.
11
12 This program is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License along with
17 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
18 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
19 http://www.gnu.org/copyleft/lesser.txt.
20 -----------------------------------------------------------------------------
21 */
22
23 #include "ImageBase.h"
24
25 #include <vector>
26 #include <string.h>
27
28 #include <PyObjectPlus.h>
29 #include <structmember.h>
30
31 #include "FilterBase.h"
32
33 #include "Exception.h"
34
35
36
37 // ImageBase class implementation
38
39 // constructor
40 ImageBase::ImageBase (bool staticSrc) : m_image(NULL), m_imgSize(0),
41 m_avail(false), m_scale(false), m_scaleChange(false), m_flip(false),
42 m_staticSources(staticSrc), m_pyfilter(NULL)
43 {
44         m_size[0] = m_size[1] = 0;
45 }
46
47
48 // destructor
49 ImageBase::~ImageBase (void)
50 {
51         // release image
52         delete [] m_image;
53 }
54
55
56 // release python objects
57 bool ImageBase::release (void)
58 {
59         // iterate sources
60         for (ImageSourceList::iterator it = m_sources.begin(); it != m_sources.end(); ++it)
61         {
62                 // release source object
63                 delete *it;
64                 *it = NULL;
65         }
66         // release filter object
67         Py_XDECREF(m_pyfilter);
68         m_pyfilter = NULL;
69         return true;
70 }
71
72
73 // get image
74 unsigned int * ImageBase::getImage (unsigned int texId)
75 {
76         // if image is not available
77         if (!m_avail)
78         {
79                 // if there are any sources
80                 if (!m_sources.empty())
81                 {
82                         // get images from sources
83                         for (ImageSourceList::iterator it = m_sources.begin(); it != m_sources.end(); ++it)
84                                 // get source image
85                                 (*it)->getImage();
86                         // init image
87                         init(m_sources[0]->getSize()[0], m_sources[0]->getSize()[1]);
88                 }
89                 // calculate new image
90                 calcImage(texId);
91         }
92         // if image is available, return it, otherwise NULL
93         return m_avail ? m_image : NULL;
94 }
95
96
97 // refresh image source
98 void ImageBase::refresh (void)
99 {
100         // invalidate this image
101         m_avail = false;
102         // refresh all sources
103         for (ImageSourceList::iterator it = m_sources.begin(); it != m_sources.end(); ++it)
104                 (*it)->refresh();
105 }
106
107
108 // get source object
109 PyImage * ImageBase::getSource (const char * id)
110 {
111         // find source
112         ImageSourceList::iterator src = findSource(id);
113         // return it, if found
114         return src != m_sources.end() ? (*src)->getSource() : NULL;
115 }
116
117
118 // set source object
119 bool ImageBase::setSource (const char * id, PyImage * source)
120 {
121         // find source
122         ImageSourceList::iterator src = findSource(id);
123         // check source loop
124         if (source != NULL && source->m_image->loopDetect(this))
125                 return false;
126         // if found, set new object
127         if (src != m_sources.end())
128                 // if new object is not empty or sources are static
129                 if (source != NULL || m_staticSources)
130                         // replace previous source
131                         (*src)->setSource(source);
132                 // otherwise delete source
133                 else
134                         m_sources.erase(src);
135         // if source is not found and adding is allowed
136         else
137                 if (!m_staticSources)
138                 {
139                         // create new source
140                         ImageSource * newSrc = newSource(id);
141                         newSrc->setSource(source);
142                         // if source was created, add it to source list
143                         if (newSrc != NULL) m_sources.push_back(newSrc);
144                 }
145                 // otherwise source wasn't set
146                 else 
147                         return false;
148         // source was set
149         return true;
150 }
151
152
153 // set pixel filter
154 void ImageBase::setFilter (PyFilter * filt)
155 {
156         // reference new filter
157         if (filt != NULL) Py_INCREF(filt);
158         // release previous filter
159         Py_XDECREF(m_pyfilter);
160         // set new filter
161         m_pyfilter = filt;
162 }
163
164
165 // initialize image data
166 void ImageBase::init (short width, short height)
167 {
168         // if image has to be scaled
169         if (m_scale)
170         {
171                 // recalc sizes of image
172                 width = calcSize(width);
173                 height = calcSize(height);
174         }
175         // if sizes differ
176         if (width != m_size[0] || height != m_size[1])
177         {
178                 // new buffer size
179                 unsigned int newSize = width * height;
180                 // if new buffer is larger than previous
181                 if (newSize > m_imgSize)
182                 {
183                         // set new buffer size
184                         m_imgSize = newSize;
185                         // release previous and create new buffer
186                         delete [] m_image;
187                         m_image = new unsigned int[m_imgSize];
188                 }
189                 // new image size
190                 m_size[0] = width;
191                 m_size[1] = height;
192                 // scale was processed
193                 m_scaleChange = false;
194         }
195 }
196
197
198 // find source
199 ImageSourceList::iterator ImageBase::findSource (const char * id)
200 {
201         // iterate sources
202         ImageSourceList::iterator it;
203         for (it = m_sources.begin(); it != m_sources.end(); ++it)
204                 // if id matches, return iterator
205                 if ((*it)->is(id)) return it;
206         // source not found
207         return it;
208 }
209
210
211 // check sources sizes
212 bool ImageBase::checkSourceSizes (void)
213 {
214         // reference size
215         short * refSize = NULL;
216         // iterate sources
217         for (ImageSourceList::iterator it = m_sources.begin(); it != m_sources.end(); ++it)
218         {
219                 // get size of current source
220                 short * curSize = (*it)->getSize();
221                 // if size is available and is not empty
222                 if (curSize[0] != 0 && curSize[1] != 0) {
223                         // if reference size is not set
224                         if (refSize == NULL) {
225                                 // set current size as reference
226                                 refSize = curSize;
227                 // otherwise check with current size
228                         } else if (curSize[0] != refSize[0] || curSize[1] != refSize[1]) {
229                                 // if they don't match, report it
230                                 return false;
231                         }
232                 }
233         }
234         // all sizes match
235         return true;
236 }
237
238
239 // compute nearest power of 2 value
240 short ImageBase::calcSize (short size)
241 {
242         // while there is more than 1 bit in size value
243         while ((size & (size - 1)) != 0)
244                 // clear last bit
245                 size = size & (size - 1);
246         // return result
247         return size;
248 }
249
250
251 // perform loop detection
252 bool ImageBase::loopDetect (ImageBase * img)
253 {
254         // if this object is the same as parameter, loop is detected
255         if (this == img) return true;
256         // check all sources
257         for (ImageSourceList::iterator it = m_sources.begin(); it != m_sources.end(); ++it)
258                 // if source detected loop, return this result
259                 if ((*it)->getSource() != NULL && (*it)->getSource()->m_image->loopDetect(img))
260                         return true;
261         // no loop detected
262         return false;
263 }
264
265
266 // ImageSource class implementation
267
268 // constructor
269 ImageSource::ImageSource (const char * id) : m_source(NULL), m_image(NULL)
270 {
271         // copy id
272         int idx;
273         for (idx = 0; id[idx] != '\0' && idx < SourceIdSize - 1; ++idx)
274                 m_id[idx] = id[idx];
275         m_id[idx] = '\0';
276 }
277
278 // destructor
279 ImageSource::~ImageSource (void)
280 {
281         // release source
282         setSource(NULL);
283 }
284
285
286 // compare id
287 bool ImageSource::is (const char * id)
288 {
289         for (char * myId = m_id; *myId != '\0'; ++myId, ++id)
290                 if (*myId != *id) return false;
291         return *id == '\0';
292 }
293
294
295 // set source object
296 void ImageSource::setSource (PyImage * source)
297 {
298         // reference new source
299         if (source != NULL) Py_INCREF(source);
300         // release previous source
301         Py_XDECREF(m_source);
302         // set new source
303         m_source = source;
304 }
305
306
307 // get image from source
308 unsigned int * ImageSource::getImage (void)
309 {
310         // if source is available
311         if (m_source != NULL)
312                 // get image from source
313                 m_image = m_source->m_image->getImage();
314         // otherwise reset buffer
315         else
316                 m_image = NULL;
317         // return image
318         return m_image;
319 }
320
321
322 // refresh source
323 void ImageSource::refresh (void)
324 {
325         // if source is available, refresh it
326         if (m_source != NULL) m_source->m_image->refresh();
327 }
328
329
330
331 // list of image types
332 PyTypeList pyImageTypes;
333
334
335
336 // functions for python interface
337
338 // object allocation
339 PyObject * Image_allocNew (PyTypeObject * type, PyObject * args, PyObject * kwds)
340 {
341         // allocate object
342         PyImage * self = reinterpret_cast<PyImage*>(type->tp_alloc(type, 0));
343         // initialize object structure
344         self->m_image = NULL;
345         // return allocated object
346         return reinterpret_cast<PyObject*>(self);
347 }
348
349 // object deallocation
350 void Image_dealloc (PyImage * self)
351 {
352         // release object attributes
353         if (self->m_image != NULL)
354         {
355                 // if release requires deleting of object, do it
356                 if (self->m_image->release())
357                         delete self->m_image;
358                 self->m_image = NULL;
359         }
360 }
361
362 // get image data
363 PyObject * Image_getImage (PyImage * self, void * closure)
364 {
365         try
366         {
367                 // get image
368                 unsigned int * image = self->m_image->getImage();
369                 return Py_BuildValue("s#", image, self->m_image->getBuffSize());
370         }
371         catch (Exception & exp)
372         {
373                 exp.report();
374         }
375         Py_RETURN_NONE;
376 }
377
378 // get image size
379 PyObject * Image_getSize (PyImage * self, void * closure)
380 {
381         return Py_BuildValue("(hh)", self->m_image->getSize()[0],
382                 self->m_image->getSize()[1]);
383 }
384
385 // refresh image
386 PyObject * Image_refresh (PyImage * self)
387 {
388         self->m_image->refresh();
389         Py_RETURN_NONE;
390 }
391
392 // get scale
393 PyObject * Image_getScale (PyImage * self, void * closure)
394 {
395         if (self->m_image != NULL && self->m_image->getScale()) Py_RETURN_TRUE;
396         else Py_RETURN_FALSE;
397 }
398
399 // set scale
400 int Image_setScale (PyImage * self, PyObject * value, void * closure)
401 {
402         // check parameter, report failure
403         if (value == NULL || !PyBool_Check(value))
404         {
405                 PyErr_SetString(PyExc_TypeError, "The value must be a bool");
406                 return -1;
407         }
408         // set scale
409         if (self->m_image != NULL) self->m_image->setScale(value == Py_True);
410         // success
411         return 0;
412 }
413
414 // get flip
415 PyObject * Image_getFlip (PyImage * self, void * closure)
416 {
417         if (self->m_image != NULL && self->m_image->getFlip()) Py_RETURN_TRUE;
418         else Py_RETURN_FALSE;
419 }
420
421 // set flip
422 int Image_setFlip (PyImage * self, PyObject * value, void * closure)
423 {
424         // check parameter, report failure
425         if (value == NULL || !PyBool_Check(value))
426         {
427                 PyErr_SetString(PyExc_TypeError, "The value must be a bool");
428                 return -1;
429         }
430         // set scale
431         if (self->m_image != NULL) self->m_image->setFlip(value == Py_True);
432         // success
433         return 0;
434 }
435
436
437 // get filter source object
438 PyObject * Image_getSource (PyImage * self, PyObject * args)
439 {
440         // get arguments
441         char * id;
442         if (!PyArg_ParseTuple(args, "s:getSource", &id))
443                 return NULL;
444         if (self->m_image != NULL)
445         {
446                 // get source object
447                 PyObject * src = reinterpret_cast<PyObject*>(self->m_image->getSource(id));
448                 // if source is available
449                 if (src != NULL)
450                 {
451                         // return source
452                         Py_INCREF(src);
453                         return src;
454                 }
455         }
456         // source was not found
457         Py_RETURN_NONE;
458 }
459
460
461 // set filter source object
462 PyObject * Image_setSource (PyImage * self, PyObject * args)
463 {
464         // get arguments
465         char * id;
466         PyObject * obj;
467         if (!PyArg_ParseTuple(args, "sO:setSource", &id, &obj))
468                 return NULL;
469         if (self->m_image != NULL)
470         {
471                 // check type of object
472                 if (pyImageTypes.in(obj->ob_type))
473                 {
474                         // convert to image struct
475                         PyImage * img = reinterpret_cast<PyImage*>(obj);
476                         // set source
477                         if (!self->m_image->setSource(id, img))
478                         {
479                                 // if not set, retport error
480                                 PyErr_SetString(PyExc_RuntimeError, "Invalid source or id");
481                                 return NULL;
482                         }
483                 }
484                 // else report error
485                 else
486                 {
487                         PyErr_SetString(PyExc_RuntimeError, "Invalid type of object");
488                         return NULL;
489                 }
490         }
491         // return none
492         Py_RETURN_NONE;
493 }
494
495
496 // get pixel filter object
497 PyObject * Image_getFilter (PyImage * self, void * closure)
498 {
499         // if image object is available
500         if (self->m_image != NULL)
501         {
502                 // pixel filter object
503                 PyObject * filt = reinterpret_cast<PyObject*>(self->m_image->getFilter());
504                 // if filter is present
505                 if (filt != NULL)
506                 {
507                         // return it
508                         Py_INCREF(filt);
509                         return filt;
510                 }
511         }
512         // otherwise return none
513         Py_RETURN_NONE;
514 }
515
516
517 // set pixel filter object
518 int Image_setFilter (PyImage * self, PyObject * value, void * closure)
519 {
520         // if image object is available
521         if (self->m_image != NULL)
522         {
523                 // check new value
524                 if (value == NULL || !pyFilterTypes.in(value->ob_type))
525                 {
526                         // report value error
527                         PyErr_SetString(PyExc_TypeError, "Invalid type of value");
528                         return -1;
529                 }
530                 // set new value
531                 self->m_image->setFilter(reinterpret_cast<PyFilter*>(value));
532         }
533         // return success
534         return 0;
535 }