Undo revision 23130 which was a merge with 2.5, a messy one because I did something...
[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         // all sizes match
233         return true;
234 }
235
236
237 // compute nearest power of 2 value
238 short ImageBase::calcSize (short size)
239 {
240         // while there is more than 1 bit in size value
241         while ((size & (size - 1)) != 0)
242                 // clear last bit
243                 size = size & (size - 1);
244         // return result
245         return size;
246 }
247
248
249 // perform loop detection
250 bool ImageBase::loopDetect (ImageBase * img)
251 {
252         // if this object is the same as parameter, loop is detected
253         if (this == img) return true;
254         // check all sources
255         for (ImageSourceList::iterator it = m_sources.begin(); it != m_sources.end(); ++it)
256                 // if source detected loop, return this result
257                 if ((*it)->getSource() != NULL && (*it)->getSource()->m_image->loopDetect(img))
258                         return true;
259         // no loop detected
260         return false;
261 }
262
263
264 // ImageSource class implementation
265
266 // constructor
267 ImageSource::ImageSource (const char * id) : m_source(NULL), m_image(NULL)
268 {
269         // copy id
270         int idx;
271         for (idx = 0; id[idx] != '\0' && idx < SourceIdSize - 1; ++idx)
272                 m_id[idx] = id[idx];
273         m_id[idx] = '\0';
274 }
275
276 // destructor
277 ImageSource::~ImageSource (void)
278 {
279         // release source
280         setSource(NULL);
281 }
282
283
284 // compare id
285 bool ImageSource::is (const char * id)
286 {
287         for (char * myId = m_id; *myId != '\0'; ++myId, ++id)
288                 if (*myId != *id) return false;
289         return *id == '\0';
290 }
291
292
293 // set source object
294 void ImageSource::setSource (PyImage * source)
295 {
296         // reference new source
297         if (source != NULL) Py_INCREF(source);
298         // release previous source
299         Py_XDECREF(m_source);
300         // set new source
301         m_source = source;
302 }
303
304
305 // get image from source
306 unsigned int * ImageSource::getImage (void)
307 {
308         // if source is available
309         if (m_source != NULL)
310                 // get image from source
311                 m_image = m_source->m_image->getImage();
312         // otherwise reset buffer
313         else
314                 m_image = NULL;
315         // return image
316         return m_image;
317 }
318
319
320 // refresh source
321 void ImageSource::refresh (void)
322 {
323         // if source is available, refresh it
324         if (m_source != NULL) m_source->m_image->refresh();
325 }
326
327
328
329 // list of image types
330 PyTypeList pyImageTypes;
331
332
333
334 // functions for python interface
335
336 // object allocation
337 PyObject * Image_allocNew (PyTypeObject * type, PyObject * args, PyObject * kwds)
338 {
339         // allocate object
340         PyImage * self = reinterpret_cast<PyImage*>(type->tp_alloc(type, 0));
341         // initialize object structure
342         self->m_image = NULL;
343         // return allocated object
344         return reinterpret_cast<PyObject*>(self);
345 }
346
347 // object deallocation
348 void Image_dealloc (PyImage * self)
349 {
350         // release object attributes
351         if (self->m_image != NULL)
352         {
353                 // if release requires deleting of object, do it
354                 if (self->m_image->release())
355                         delete self->m_image;
356                 self->m_image = NULL;
357         }
358 }
359
360 // get image data
361 PyObject * Image_getImage (PyImage * self, void * closure)
362 {
363         try
364         {
365                 // get image
366                 unsigned int * image = self->m_image->getImage();
367                 return Py_BuildValue("s#", image, self->m_image->getBuffSize());
368         }
369         catch (Exception & exp)
370         {
371                 exp.report();
372         }
373         Py_RETURN_NONE;
374 }
375
376 // get image size
377 PyObject * Image_getSize (PyImage * self, void * closure)
378 {
379         return Py_BuildValue("(hh)", self->m_image->getSize()[0],
380                 self->m_image->getSize()[1]);
381 }
382
383 // refresh image
384 PyObject * Image_refresh (PyImage * self)
385 {
386         self->m_image->refresh();
387         Py_RETURN_NONE;
388 }
389
390 // get scale
391 PyObject * Image_getScale (PyImage * self, void * closure)
392 {
393         if (self->m_image != NULL && self->m_image->getScale()) Py_RETURN_TRUE;
394         else Py_RETURN_FALSE;
395 }
396
397 // set scale
398 int Image_setScale (PyImage * self, PyObject * value, void * closure)
399 {
400         // check parameter, report failure
401         if (value == NULL || !PyBool_Check(value))
402         {
403                 PyErr_SetString(PyExc_TypeError, "The value must be a bool");
404                 return -1;
405         }
406         // set scale
407         if (self->m_image != NULL) self->m_image->setScale(value == Py_True);
408         // success
409         return 0;
410 }
411
412 // get flip
413 PyObject * Image_getFlip (PyImage * self, void * closure)
414 {
415         if (self->m_image != NULL && self->m_image->getFlip()) Py_RETURN_TRUE;
416         else Py_RETURN_FALSE;
417 }
418
419 // set flip
420 int Image_setFlip (PyImage * self, PyObject * value, void * closure)
421 {
422         // check parameter, report failure
423         if (value == NULL || !PyBool_Check(value))
424         {
425                 PyErr_SetString(PyExc_TypeError, "The value must be a bool");
426                 return -1;
427         }
428         // set scale
429         if (self->m_image != NULL) self->m_image->setFlip(value == Py_True);
430         // success
431         return 0;
432 }
433
434
435 // get filter source object
436 PyObject * Image_getSource (PyImage * self, PyObject * args)
437 {
438         // get arguments
439         char * id;
440         if (!PyArg_ParseTuple(args, "s:getSource", &id))
441                 return NULL;
442         if (self->m_image != NULL)
443         {
444                 // get source object
445                 PyObject * src = reinterpret_cast<PyObject*>(self->m_image->getSource(id));
446                 // if source is available
447                 if (src != NULL)
448                 {
449                         // return source
450                         Py_INCREF(src);
451                         return src;
452                 }
453         }
454         // source was not found
455         Py_RETURN_NONE;
456 }
457
458
459 // set filter source object
460 PyObject * Image_setSource (PyImage * self, PyObject * args)
461 {
462         // get arguments
463         char * id;
464         PyObject * obj;
465         if (!PyArg_ParseTuple(args, "sO:setSource", &id, &obj))
466                 return NULL;
467         if (self->m_image != NULL)
468         {
469                 // check type of object
470                 if (pyImageTypes.in(obj->ob_type))
471                 {
472                         // convert to image struct
473                         PyImage * img = reinterpret_cast<PyImage*>(obj);
474                         // set source
475                         if (!self->m_image->setSource(id, img))
476                         {
477                                 // if not set, retport error
478                                 PyErr_SetString(PyExc_RuntimeError, "Invalid source or id");
479                                 return NULL;
480                         }
481                 }
482                 // else report error
483                 else
484                 {
485                         PyErr_SetString(PyExc_RuntimeError, "Invalid type of object");
486                         return NULL;
487                 }
488         }
489         // return none
490         Py_RETURN_NONE;
491 }
492
493
494 // get pixel filter object
495 PyObject * Image_getFilter (PyImage * self, void * closure)
496 {
497         // if image object is available
498         if (self->m_image != NULL)
499         {
500                 // pixel filter object
501                 PyObject * filt = reinterpret_cast<PyObject*>(self->m_image->getFilter());
502                 // if filter is present
503                 if (filt != NULL)
504                 {
505                         // return it
506                         Py_INCREF(filt);
507                         return filt;
508                 }
509         }
510         // otherwise return none
511         Py_RETURN_NONE;
512 }
513
514
515 // set pixel filter object
516 int Image_setFilter (PyImage * self, PyObject * value, void * closure)
517 {
518         // if image object is available
519         if (self->m_image != NULL)
520         {
521                 // check new value
522                 if (value == NULL || !pyFilterTypes.in(value->ob_type))
523                 {
524                         // report value error
525                         PyErr_SetString(PyExc_TypeError, "Invalid type of value");
526                         return -1;
527                 }
528                 // set new value
529                 self->m_image->setFilter(reinterpret_cast<PyFilter*>(value));
530         }
531         // return success
532         return 0;
533 }