svn merge ^/trunk/blender -r41226:41227 .
[blender.git] / source / gameengine / VideoTexture / ImageBase.h
1 -----------------------------------------------------------------------------
2 This source file is part of blendTex library
3
4 Copyright (c) 2007 The Zdeno Ash Miklas
5
6 This program is free software; you can redistribute it and/or modify it under
7 the terms of the GNU Lesser General Public License as published by the Free Software
8 Foundation; either version 2 of the License, or (at your option) any later
9 version.
10
11 This program is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along with
16 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
17 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
18 http://www.gnu.org/copyleft/lesser.txt.
19 -----------------------------------------------------------------------------
20 */
21
22 /** \file ImageBase.h
23  *  \ingroup bgevideotex
24  */
25  
26 #if !defined IMAGEBASE_H
27 #define IMAGEBASE_H
28
29 #include "Common.h"
30
31 #include <vector>
32 #include <PyObjectPlus.h>
33
34 #include "PyTypeList.h"
35
36 #include "FilterBase.h"
37
38
39 // forward declarations
40 struct PyImage;
41 class ImageSource;
42
43
44 /// type for list of image sources
45 typedef std::vector<ImageSource*> ImageSourceList;
46
47
48 /// base class for image filters
49 class ImageBase
50 {
51 public:
52         /// constructor
53         ImageBase (bool staticSrc = false);
54         /// destructor
55         virtual ~ImageBase (void);
56         /// release contained objects, if returns true, object should be deleted
57         virtual bool release (void);
58
59         /// is an image available
60         bool isImageAvailable(void)
61         { return m_avail; }
62         /// get image
63         unsigned int * getImage (unsigned int texId = 0, double timestamp=-1.0);
64         /// get image size
65         short * getSize (void) { return m_size; }
66         /// get image buffer size
67         unsigned long getBuffSize (void)
68         { return m_size[0] * m_size[1] * sizeof(unsigned int); }
69         /// refresh image - invalidate its current content
70         virtual void refresh (void);
71
72         /// get scale
73         bool getScale (void) { return m_scale; }
74         /// set scale
75         void setScale (bool scale) { m_scale = scale; m_scaleChange = true; }
76         /// get vertical flip
77         bool getFlip (void) { return m_flip; }
78         /// set vertical flip
79         void setFlip (bool flip) { m_flip = flip; }
80
81         /// get source object
82         PyImage * getSource (const char * id);
83         /// set source object, return true, if source was set
84         bool setSource (const char * id, PyImage * source);
85
86         /// get pixel filter
87         PyFilter * getFilter (void) { return m_pyfilter; }
88         /// set pixel filter
89         void setFilter (PyFilter * filt);
90
91         /// calculate size (nearest power of 2)
92         static short calcSize (short size);
93
94         /// number of buffer pointing to m_image, public because not handled by this class
95         int m_exports;
96
97 protected:
98         /// image buffer
99         unsigned int * m_image;
100         /// image buffer size
101         unsigned int m_imgSize;
102         /// image size
103         short m_size[2];
104         /// image is available
105         bool m_avail;
106
107         /// scale image to power 2 sizes
108         bool m_scale;
109         /// scale was changed
110         bool m_scaleChange;
111         /// flip image vertically
112         bool m_flip;
113
114         /// source image list
115         ImageSourceList m_sources;
116         /// flag for disabling addition and deletion of sources
117         bool m_staticSources;
118
119         /// pixel filter
120         PyFilter * m_pyfilter;
121
122         /// initialize image data
123         void init (short width, short height);
124
125         /// find source
126         ImageSourceList::iterator findSource (const char * id);
127
128         /// create new source
129         virtual ImageSource * newSource (const char * id) { return NULL; }
130
131         /// check source sizes
132         bool checkSourceSizes (void);
133
134         /// calculate image from sources and set its availability
135         virtual void calcImage (unsigned int texId, double ts) {}
136
137         /// perform loop detection
138         bool loopDetect (ImageBase * img);
139
140         /// template for image conversion
141         template<class FLT, class SRC> void convImage (FLT & filter, SRC srcBuff,
142                 short * srcSize)
143         {
144                 // destination buffer
145                 unsigned int * dstBuff = m_image;
146                 // pixel size from filter
147                 unsigned int pixSize = filter.firstPixelSize();
148                 // if no scaling is needed
149                 if (srcSize[0] == m_size[0] && srcSize[1] == m_size[1])
150                         // if flipping isn't required
151                         if (!m_flip)
152                                 // copy bitmap
153                                 for (short y = 0; y < m_size[1]; ++y)
154                                         for (short x = 0; x < m_size[0]; ++x, ++dstBuff, srcBuff += pixSize)
155                                                 // copy pixel
156                                                 *dstBuff = filter.convert(srcBuff, x, y, srcSize, pixSize);
157                 // otherwise flip image top to bottom
158                         else
159                         {
160                                 // go to last row of image
161                                 srcBuff += srcSize[0] * (srcSize[1] - 1) * pixSize;
162                                 // copy bitmap
163                                 for (short y = m_size[1] - 1; y >= 0; --y, srcBuff -= 2 * srcSize[0] * pixSize)
164                                         for (short x = 0; x < m_size[0]; ++x, ++dstBuff, srcBuff += pixSize)
165                                                 // copy pixel
166                                                 *dstBuff = filter.convert(srcBuff, x, y, srcSize, pixSize);
167                         }
168                         // else scale picture (nearest neighbour)
169                 else
170                 {
171                         // interpolation accumulator
172                         int accHeight = srcSize[1] >> 1;
173                         // if flipping is required
174                         if (m_flip)
175                                 // go to last row of image
176                                 srcBuff += srcSize[0] * (srcSize[1] - 1) * pixSize;
177                         // process image rows
178                         for (int y = 0; y < srcSize[1]; ++y)
179                         {
180                                 // increase height accum
181                                 accHeight += m_size[1];
182                                 // if pixel row has to be drawn
183                                 if (accHeight >= srcSize[1])
184                                 {
185                                         // decrease accum
186                                         accHeight -= srcSize[1];
187                                         // width accum
188                                         int accWidth = srcSize[0] >> 1;
189                                         // process row
190                                         for (int x = 0; x < srcSize[0]; ++x)
191                                         {
192                                                 // increase width accum
193                                                 accWidth += m_size[0];
194                                                 // if pixel has to be drawn
195                                                 if (accWidth >= srcSize[0])
196                                                 {
197                                                         // decrease accum
198                                                         accWidth -= srcSize[0];
199                                                         // convert pixel
200                                                         *dstBuff = filter.convert(srcBuff, x, m_flip ? srcSize[1] - y - 1 : y,
201                                                                 srcSize, pixSize);
202                                                         // next pixel
203                                                         ++dstBuff;
204                                                 }
205                                                 // shift source pointer
206                                                 srcBuff += pixSize;
207                                         }
208                                 }
209                                 // if pixel row will not be drawn
210                                 else
211                                         // move source pointer to next row
212                                         srcBuff += pixSize * srcSize[0];
213                                 // if y flipping is required
214                                 if (m_flip)
215                                         // go to previous row of image
216                                         srcBuff -= 2 * pixSize * srcSize[0];
217                         }
218                 }
219         }
220
221         // template for specific filter preprocessing
222         template <class F, class SRC> void filterImage (F & filt, SRC srcBuff, short * srcSize)
223         {
224                 // find first filter in chain
225                 FilterBase * firstFilter = NULL;
226                 if (m_pyfilter != NULL) firstFilter = m_pyfilter->m_filter->findFirst();
227                 // if first filter is available
228                 if (firstFilter != NULL)
229                 {
230                         // python wrapper for filter
231                         PyFilter pyFilt;
232                         pyFilt.m_filter = &filt;
233                         // set specified filter as first in chain
234                         firstFilter->setPrevious(&pyFilt, false);
235                         // convert video image
236                         convImage(*(m_pyfilter->m_filter), srcBuff, srcSize);
237                         // delete added filter
238                         firstFilter->setPrevious(NULL, false);
239                 }
240                 // otherwise use given filter for conversion
241                 else convImage(filt, srcBuff, srcSize);
242                 // source was processed
243                 m_avail = true;
244         }
245 };
246
247
248 // python structure for image filter
249 struct PyImage
250 {
251         PyObject_HEAD
252         // source object
253         ImageBase * m_image;
254 };
255
256
257 // size of id
258 const int SourceIdSize = 32;
259
260
261 /// class for source of image
262 class ImageSource
263 {
264 public:
265         /// constructor
266         ImageSource (const char * id);
267         /// destructor
268         virtual ~ImageSource (void);
269
270         /// get id
271         const char * getId (void) { return m_id; }
272         /// compare id to argument
273         bool is (const char * id);
274
275         /// get source object
276         PyImage * getSource (void) { return m_source; }
277         /// set source object
278         void setSource (PyImage * source);
279
280         /// get image from source
281         unsigned int * getImage (double ts=-1.0);
282         /// get buffered image
283         unsigned int * getImageBuf (void) { return m_image; }
284         /// refresh source
285         void refresh (void);
286
287         /// get image size
288         short * getSize (void)
289         { 
290                 static short defSize [] = {0, 0};
291                 return m_source != NULL ? m_source->m_image->getSize() : defSize;
292         }
293
294 protected:
295         /// id of source
296         char m_id [SourceIdSize];
297         /// pointer to source structure
298         PyImage * m_source;
299         /// buffered image from source
300         unsigned int * m_image;
301
302 private:
303         /// default constructor is forbidden
304         ImageSource (void) {}
305 };
306
307 // list of python image types
308 extern PyTypeList pyImageTypes;
309
310
311 // functions for python interface
312
313 // object initialization
314 template <class T> static int Image_init (PyObject * pySelf, PyObject * args, PyObject * kwds)
315 {
316         PyImage * self = reinterpret_cast<PyImage*>(pySelf);
317         // create source object
318         if (self->m_image != NULL) delete self->m_image;
319         self->m_image = new T();
320         // initialization succeded
321         return 0;
322 }
323
324 // object allocation
325 PyObject * Image_allocNew (PyTypeObject * type, PyObject * args, PyObject * kwds);
326 // object deallocation
327 void Image_dealloc (PyImage * self);
328
329 // get image data
330 PyObject * Image_getImage (PyImage * self, char * mode);
331 // get image size
332 PyObject * Image_getSize (PyImage * self, void * closure);
333 // refresh image - invalidate current content
334 PyObject * Image_refresh (PyImage * self);
335
336 // get scale
337 PyObject * Image_getScale (PyImage * self, void * closure);
338 // set scale
339 int Image_setScale (PyImage * self, PyObject * value, void * closure);
340 // get flip
341 PyObject * Image_getFlip (PyImage * self, void * closure);
342 // set flip
343 int Image_setFlip (PyImage * self, PyObject * value, void * closure);
344
345 // get filter source object
346 PyObject * Image_getSource (PyImage * self, PyObject * args);
347 // set filter source object
348 PyObject * Image_setSource (PyImage * self, PyObject * args);
349
350 // get pixel filter object
351 PyObject * Image_getFilter (PyImage * self, void * closure);
352 // set pixel filter object
353 int Image_setFilter (PyImage * self, PyObject * value, void * closure);
354 // check if a buffer can be extracted
355 PyObject * Image_valid(PyImage * self, void * closure);
356 // for buffer access to PyImage objects
357 extern PyBufferProcs imageBufferProcs;
358
359 #endif