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