86de214e2d342815be0cc037ae7c01724782aa54
[blender-staging.git] / source / gameengine / VideoTexture / ImageBase.cpp
1 /** \file gameengine/VideoTexture/ImageBase.cpp
2  *  \ingroup bgevideotex
3  */
4 /* $Id$
5 -----------------------------------------------------------------------------
6 This source file is part of VideoTexture library
7
8 Copyright (c) 2007 The Zdeno Ash Miklas
9
10 This program is free software; you can redistribute it and/or modify it under
11 the terms of the GNU Lesser General Public License as published by the Free Software
12 Foundation; either version 2 of the License, or (at your option) any later
13 version.
14
15 This program is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19 You should have received a copy of the GNU Lesser General Public License along with
20 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22 http://www.gnu.org/copyleft/lesser.txt.
23 -----------------------------------------------------------------------------
24 */
25
26 #include "ImageBase.h"
27 extern "C" {
28 #include "bgl.h"
29 }
30 #include "GL/glew.h"
31
32 #include <vector>
33 #include <string.h>
34
35 #include <PyObjectPlus.h>
36 #include <structmember.h>
37
38 #include "FilterBase.h"
39
40 #include "Exception.h"
41
42 #if (defined(WIN32) || defined(WIN64)) && !defined(FREE_WINDOWS)
43 #define strcasecmp      _stricmp
44 #endif
45
46 // ImageBase class implementation
47
48 // constructor
49 ImageBase::ImageBase (bool staticSrc) : m_image(NULL), m_imgSize(0),
50 m_avail(false), m_scale(false), m_scaleChange(false), m_flip(false),
51 m_staticSources(staticSrc), m_pyfilter(NULL)
52 {
53         m_size[0] = m_size[1] = 0;
54         m_exports = 0;
55 }
56
57
58 // destructor
59 ImageBase::~ImageBase (void)
60 {
61         // release image
62         if (m_image)
63                 delete [] m_image;
64 }
65
66
67 // release python objects
68 bool ImageBase::release (void)
69 {
70         // iterate sources
71         for (ImageSourceList::iterator it = m_sources.begin(); it != m_sources.end(); ++it)
72         {
73                 // release source object
74                 delete *it;
75                 *it = NULL;
76         }
77         // release filter object
78         Py_XDECREF(m_pyfilter);
79         m_pyfilter = NULL;
80         return true;
81 }
82
83
84 // get image
85 unsigned int * ImageBase::getImage (unsigned int texId, double ts)
86 {
87         // if image is not available
88         if (!m_avail)
89         {
90                 // if there are any sources
91                 if (!m_sources.empty())
92                 {
93                         // get images from sources
94                         for (ImageSourceList::iterator it = m_sources.begin(); it != m_sources.end(); ++it)
95                                 // get source image
96                                 (*it)->getImage(ts);
97                         // init image
98                         init(m_sources[0]->getSize()[0], m_sources[0]->getSize()[1]);
99                 }
100                 // calculate new image
101                 calcImage(texId, ts);
102         }
103         // if image is available, return it, otherwise NULL
104         return m_avail ? m_image : NULL;
105 }
106
107
108 // refresh image source
109 void ImageBase::refresh (void)
110 {
111         // invalidate this image
112         m_avail = false;
113         // refresh all sources
114         for (ImageSourceList::iterator it = m_sources.begin(); it != m_sources.end(); ++it)
115                 (*it)->refresh();
116 }
117
118
119 // get source object
120 PyImage * ImageBase::getSource (const char * id)
121 {
122         // find source
123         ImageSourceList::iterator src = findSource(id);
124         // return it, if found
125         return src != m_sources.end() ? (*src)->getSource() : NULL;
126 }
127
128
129 // set source object
130 bool ImageBase::setSource (const char * id, PyImage * source)
131 {
132         // find source
133         ImageSourceList::iterator src = findSource(id);
134         // check source loop
135         if (source != NULL && source->m_image->loopDetect(this))
136                 return false;
137         // if found, set new object
138         if (src != m_sources.end())
139                 // if new object is not empty or sources are static
140                 if (source != NULL || m_staticSources)
141                         // replace previous source
142                         (*src)->setSource(source);
143                 // otherwise delete source
144                 else
145                         m_sources.erase(src);
146         // if source is not found and adding is allowed
147         else
148                 if (!m_staticSources)
149                 {
150                         // create new source
151                         ImageSource * newSrc = newSource(id);
152                         newSrc->setSource(source);
153                         // if source was created, add it to source list
154                         if (newSrc != NULL) m_sources.push_back(newSrc);
155                 }
156                 // otherwise source wasn't set
157                 else 
158                         return false;
159         // source was set
160         return true;
161 }
162
163
164 // set pixel filter
165 void ImageBase::setFilter (PyFilter * filt)
166 {
167         // reference new filter
168         if (filt != NULL) Py_INCREF(filt);
169         // release previous filter
170         Py_XDECREF(m_pyfilter);
171         // set new filter
172         m_pyfilter = filt;
173 }
174
175 ExceptionID ImageHasExports;
176 ExceptionID InvalidColorChannel;
177
178 ExpDesc ImageHasExportsDesc (ImageHasExports, "Image has exported buffers, cannot resize");
179 ExpDesc InvalidColorChannelDesc (InvalidColorChannel, "Invalid or too many color channels specified. At most 4 values within R, G, B, A, 0, 1");
180
181 // initialize image data
182 void ImageBase::init (short width, short height)
183 {
184         // if image has to be scaled
185         if (m_scale)
186         {
187                 // recalc sizes of image
188                 width = calcSize(width);
189                 height = calcSize(height);
190         }
191         // if sizes differ
192         if (width != m_size[0] || height != m_size[1])
193         {
194                 if (m_exports > 0)
195                         THRWEXCP(ImageHasExports,S_OK);
196
197                 // new buffer size
198                 unsigned int newSize = width * height;
199                 // if new buffer is larger than previous
200                 if (newSize > m_imgSize)
201                 {
202                         // set new buffer size
203                         m_imgSize = newSize;
204                         // release previous and create new buffer
205                         if (m_image)
206                                 delete [] m_image;
207                         m_image = new unsigned int[m_imgSize];
208                 }
209                 // new image size
210                 m_size[0] = width;
211                 m_size[1] = height;
212                 // scale was processed
213                 m_scaleChange = false;
214         }
215 }
216
217
218 // find source
219 ImageSourceList::iterator ImageBase::findSource (const char * id)
220 {
221         // iterate sources
222         ImageSourceList::iterator it;
223         for (it = m_sources.begin(); it != m_sources.end(); ++it)
224                 // if id matches, return iterator
225                 if ((*it)->is(id)) return it;
226         // source not found
227         return it;
228 }
229
230
231 // check sources sizes
232 bool ImageBase::checkSourceSizes (void)
233 {
234         // reference size
235         short * refSize = NULL;
236         // iterate sources
237         for (ImageSourceList::iterator it = m_sources.begin(); it != m_sources.end(); ++it)
238         {
239                 // get size of current source
240                 short * curSize = (*it)->getSize();
241                 // if size is available and is not empty
242                 if (curSize[0] != 0 && curSize[1] != 0) {
243                         // if reference size is not set
244                         if (refSize == NULL) {
245                                 // set current size as reference
246                                 refSize = curSize;
247                 // otherwise check with current size
248                         } else if (curSize[0] != refSize[0] || curSize[1] != refSize[1]) {
249                                 // if they don't match, report it
250                                 return false;
251                         }
252                 }
253         }
254         // all sizes match
255         return true;
256 }
257
258
259 // compute nearest power of 2 value
260 short ImageBase::calcSize (short size)
261 {
262         // while there is more than 1 bit in size value
263         while ((size & (size - 1)) != 0)
264                 // clear last bit
265                 size = size & (size - 1);
266         // return result
267         return size;
268 }
269
270
271 // perform loop detection
272 bool ImageBase::loopDetect (ImageBase * img)
273 {
274         // if this object is the same as parameter, loop is detected
275         if (this == img) return true;
276         // check all sources
277         for (ImageSourceList::iterator it = m_sources.begin(); it != m_sources.end(); ++it)
278                 // if source detected loop, return this result
279                 if ((*it)->getSource() != NULL && (*it)->getSource()->m_image->loopDetect(img))
280                         return true;
281         // no loop detected
282         return false;
283 }
284
285
286 // ImageSource class implementation
287
288 // constructor
289 ImageSource::ImageSource (const char * id) : m_source(NULL), m_image(NULL)
290 {
291         // copy id
292         int idx;
293         for (idx = 0; id[idx] != '\0' && idx < SourceIdSize - 1; ++idx)
294                 m_id[idx] = id[idx];
295         m_id[idx] = '\0';
296 }
297
298 // destructor
299 ImageSource::~ImageSource (void)
300 {
301         // release source
302         setSource(NULL);
303 }
304
305
306 // compare id
307 bool ImageSource::is (const char * id)
308 {
309         for (char * myId = m_id; *myId != '\0'; ++myId, ++id)
310                 if (*myId != *id) return false;
311         return *id == '\0';
312 }
313
314
315 // set source object
316 void ImageSource::setSource (PyImage * source)
317 {
318         // reference new source
319         if (source != NULL) Py_INCREF(source);
320         // release previous source
321         Py_XDECREF(m_source);
322         // set new source
323         m_source = source;
324 }
325
326
327 // get image from source
328 unsigned int * ImageSource::getImage (double ts)
329 {
330         // if source is available
331         if (m_source != NULL)
332                 // get image from source
333                 m_image = m_source->m_image->getImage(0, ts);
334         // otherwise reset buffer
335         else
336                 m_image = NULL;
337         // return image
338         return m_image;
339 }
340
341
342 // refresh source
343 void ImageSource::refresh (void)
344 {
345         // if source is available, refresh it
346         if (m_source != NULL) m_source->m_image->refresh();
347 }
348
349
350
351 // list of image types
352 PyTypeList pyImageTypes;
353
354
355
356 // functions for python interface
357
358 // object allocation
359 PyObject * Image_allocNew (PyTypeObject * type, PyObject * args, PyObject * kwds)
360 {
361         // allocate object
362         PyImage * self = reinterpret_cast<PyImage*>(type->tp_alloc(type, 0));
363         // initialize object structure
364         self->m_image = NULL;
365         // return allocated object
366         return reinterpret_cast<PyObject*>(self);
367 }
368
369 // object deallocation
370 void Image_dealloc (PyImage * self)
371 {
372         // release object attributes
373         if (self->m_image != NULL)
374         {
375                 if (self->m_image->m_exports > 0)
376                 {
377                         PyErr_SetString(PyExc_SystemError,
378                                             "deallocated Image object has exported buffers");
379                         PyErr_Print();
380                 }
381                 // if release requires deleting of object, do it
382                 if (self->m_image->release())
383                         delete self->m_image;
384                 self->m_image = NULL;
385         }
386 }
387
388 // get image data
389 PyObject * Image_getImage (PyImage * self, char * mode)
390 {
391         try
392         {
393                 unsigned int * image = self->m_image->getImage();
394                 if (image) 
395                 {
396                         // build BGL buffer
397                         int dimensions = self->m_image->getBuffSize();
398                         Buffer * buffer;
399                         if (mode == NULL || !strcasecmp(mode, "RGBA"))
400                         {
401                                 buffer = BGL_MakeBuffer( GL_BYTE, 1, &dimensions, image);
402                         }
403                         else 
404                         {
405                                 int i, c, ncolor, pixels;
406                                 int offset[4];
407                                 unsigned char *s, *d;
408                                 // scan the mode to get the channels requested, no more than 4
409                                 for (i=ncolor=0; mode[i] != 0 && ncolor < 4; i++)
410                                 {
411                                         switch (toupper(mode[i]))
412                                         {
413                                         case 'R':
414                                                 offset[ncolor++] = 0;
415                                                 break;
416                                         case 'G':
417                                                 offset[ncolor++] = 1;
418                                                 break;
419                                         case 'B':
420                                                 offset[ncolor++] = 2;
421                                                 break;
422                                         case 'A':
423                                                 offset[ncolor++] = 3;
424                                                 break;
425                                         case '0':
426                                                 offset[ncolor++] = -1;
427                                                 break;
428                                         case '1':
429                                                 offset[ncolor++] = -2;
430                                                 break;
431                                         // if you add more color code, change the switch further down
432                                         default:
433                                                 THRWEXCP(InvalidColorChannel,S_OK);
434                                         }
435                                 }
436                                 if (mode[i] != 0) {
437                                         THRWEXCP(InvalidColorChannel,S_OK);
438                                 }
439                                 // first get the number of pixels
440                                 pixels = dimensions / 4;
441                                 // multiple by the number of channels, each is one byte
442                                 dimensions = pixels * ncolor;
443                                 // get an empty buffer
444                                 buffer = BGL_MakeBuffer( GL_BYTE, 1, &dimensions, NULL);
445                                 // and fill it
446                                 for (i=0, d=(unsigned char*)buffer->buf.asbyte, s=(unsigned char*)image; 
447                                          i<pixels; 
448                                          ++i, d+=ncolor, s+=4)
449                                 {
450                                         for (c=0; c<ncolor; c++)
451                                         {
452                                                 switch (offset[c])
453                                                 {
454                                                 case 0: d[c] = s[0]; break;
455                                                 case 1: d[c] = s[1]; break;
456                                                 case 2: d[c] = s[2]; break;
457                                                 case 3: d[c] = s[3]; break;
458                                                 case -1: d[c] = 0; break;
459                                                 case -2: d[c] = 0xFF; break;
460                                                 }
461                                         }
462                                 }
463                         }
464                         return (PyObject*)buffer;
465                 }
466         }
467         catch (Exception & exp)
468         {
469                 exp.report();
470                 return NULL;
471         }
472         Py_RETURN_NONE;
473 }
474
475 // get image size
476 PyObject * Image_getSize (PyImage * self, void * closure)
477 {
478         return Py_BuildValue("(hh)", self->m_image->getSize()[0],
479                 self->m_image->getSize()[1]);
480 }
481
482 // refresh image
483 PyObject * Image_refresh (PyImage * self)
484 {
485         self->m_image->refresh();
486         Py_RETURN_NONE;
487 }
488
489 // get scale
490 PyObject * Image_getScale (PyImage * self, void * closure)
491 {
492         if (self->m_image != NULL && self->m_image->getScale()) Py_RETURN_TRUE;
493         else Py_RETURN_FALSE;
494 }
495
496 // set scale
497 int Image_setScale (PyImage * self, PyObject * value, void * closure)
498 {
499         // check parameter, report failure
500         if (value == NULL || !PyBool_Check(value))
501         {
502                 PyErr_SetString(PyExc_TypeError, "The value must be a bool");
503                 return -1;
504         }
505         // set scale
506         if (self->m_image != NULL) self->m_image->setScale(value == Py_True);
507         // success
508         return 0;
509 }
510
511 // get flip
512 PyObject * Image_getFlip (PyImage * self, void * closure)
513 {
514         if (self->m_image != NULL && self->m_image->getFlip()) Py_RETURN_TRUE;
515         else Py_RETURN_FALSE;
516 }
517
518 // set flip
519 int Image_setFlip (PyImage * self, PyObject * value, void * closure)
520 {
521         // check parameter, report failure
522         if (value == NULL || !PyBool_Check(value))
523         {
524                 PyErr_SetString(PyExc_TypeError, "The value must be a bool");
525                 return -1;
526         }
527         // set scale
528         if (self->m_image != NULL) self->m_image->setFlip(value == Py_True);
529         // success
530         return 0;
531 }
532
533
534 // get filter source object
535 PyObject * Image_getSource (PyImage * self, PyObject * args)
536 {
537         // get arguments
538         char * id;
539         if (!PyArg_ParseTuple(args, "s:getSource", &id))
540                 return NULL;
541         if (self->m_image != NULL)
542         {
543                 // get source object
544                 PyObject * src = reinterpret_cast<PyObject*>(self->m_image->getSource(id));
545                 // if source is available
546                 if (src != NULL)
547                 {
548                         // return source
549                         Py_INCREF(src);
550                         return src;
551                 }
552         }
553         // source was not found
554         Py_RETURN_NONE;
555 }
556
557
558 // set filter source object
559 PyObject * Image_setSource (PyImage * self, PyObject * args)
560 {
561         // get arguments
562         char * id;
563         PyObject * obj;
564         if (!PyArg_ParseTuple(args, "sO:setSource", &id, &obj))
565                 return NULL;
566         if (self->m_image != NULL)
567         {
568                 // check type of object
569                 if (pyImageTypes.in(obj->ob_type))
570                 {
571                         // convert to image struct
572                         PyImage * img = reinterpret_cast<PyImage*>(obj);
573                         // set source
574                         if (!self->m_image->setSource(id, img))
575                         {
576                                 // if not set, retport error
577                                 PyErr_SetString(PyExc_RuntimeError, "Invalid source or id");
578                                 return NULL;
579                         }
580                 }
581                 // else report error
582                 else
583                 {
584                         PyErr_SetString(PyExc_RuntimeError, "Invalid type of object");
585                         return NULL;
586                 }
587         }
588         // return none
589         Py_RETURN_NONE;
590 }
591
592
593 // get pixel filter object
594 PyObject * Image_getFilter (PyImage * self, void * closure)
595 {
596         // if image object is available
597         if (self->m_image != NULL)
598         {
599                 // pixel filter object
600                 PyObject * filt = reinterpret_cast<PyObject*>(self->m_image->getFilter());
601                 // if filter is present
602                 if (filt != NULL)
603                 {
604                         // return it
605                         Py_INCREF(filt);
606                         return filt;
607                 }
608         }
609         // otherwise return none
610         Py_RETURN_NONE;
611 }
612
613
614 // set pixel filter object
615 int Image_setFilter (PyImage * self, PyObject * value, void * closure)
616 {
617         // if image object is available
618         if (self->m_image != NULL)
619         {
620                 // check new value
621                 if (value == NULL || !pyFilterTypes.in(value->ob_type))
622                 {
623                         // report value error
624                         PyErr_SetString(PyExc_TypeError, "Invalid type of value");
625                         return -1;
626                 }
627                 // set new value
628                 self->m_image->setFilter(reinterpret_cast<PyFilter*>(value));
629         }
630         // return success
631         return 0;
632 }
633 PyObject * Image_valid(PyImage * self, void * closure)
634 {
635         if (self->m_image->isImageAvailable())
636         {
637                 Py_RETURN_TRUE;
638         }
639         else
640         {
641                 Py_RETURN_FALSE;
642         }
643 }
644
645 int Image_getbuffer(PyImage *self, Py_buffer *view, int flags)
646 {
647         unsigned int * image;
648         int ret;
649
650         try
651         {
652                 // can throw in case of resize
653                 image = self->m_image->getImage();
654         }
655         catch (Exception & exp)
656         {
657                 // cannot return -1, this creates a crash in Python, for now we will just return an empty buffer
658                 exp.report();
659                 //return -1;
660                 goto error;
661         }
662
663         if (!image)
664         {
665                 // same remark, see above
666                 //PyErr_SetString(PyExc_BufferError, "Image buffer is not available");
667                 //return -1;
668                 goto error;
669         }
670         if (view == NULL)
671         {
672                 self->m_image->m_exports++;
673                 return 0;
674         }
675         ret = PyBuffer_FillInfo(view, (PyObject*)self, image, self->m_image->getBuffSize(), 0, flags);
676         if (ret >= 0)
677                 self->m_image->m_exports++;
678         return ret;
679
680 error:
681         // Return a empty buffer to avoid a crash in Python 3.1
682         // The bug is fixed in Python SVN 77916, as soon as the python revision used by Blender is
683         // updated, you can simply return -1 and set the error
684         static char* buf = (char *)"";
685         ret = PyBuffer_FillInfo(view, (PyObject*)self, buf, 0, 0, flags);
686         if (ret >= 0)
687                 self->m_image->m_exports++;
688         return ret;
689         
690 }
691
692 void Image_releaseBuffer(PyImage *self, Py_buffer *buffer)
693 {
694         self->m_image->m_exports--;
695 }
696
697 PyBufferProcs imageBufferProcs = 
698 {
699         (getbufferproc)Image_getbuffer,
700         (releasebufferproc)Image_releaseBuffer
701 };
702