blender/source/gameengine/VideoTexture/ImageBase.h

350 lines
9.1 KiB
C++

/* $Id$
-----------------------------------------------------------------------------
This source file is part of blendTex library
Copyright (c) 2007 The Zdeno Ash Miklas
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
#if !defined IMAGEBASE_H
#define IMAGEBASE_H
#include "Common.h"
#include <vector>
#include <PyObjectPlus.h>
#include "PyTypeList.h"
#include "FilterBase.h"
// forward declarations
struct PyImage;
class ImageSource;
/// type for list of image sources
typedef std::vector<ImageSource*> ImageSourceList;
/// base class for image filters
class ImageBase
{
public:
/// constructor
ImageBase (bool staticSrc = false);
/// destructor
virtual ~ImageBase (void);
/// release contained objects, if returns true, object should be deleted
virtual bool release (void);
/// get image
unsigned int * getImage (unsigned int texId = 0);
/// get image size
short * getSize (void) { return m_size; }
/// get image buffer size
unsigned long getBuffSize (void)
{ return m_size[0] * m_size[1] * sizeof(unsigned int); }
/// refresh image - invalidate its current content
virtual void refresh (void);
/// get scale
bool getScale (void) { return m_scale; }
/// set scale
void setScale (bool scale) { m_scale = scale; m_scaleChange = true; }
/// get vertical flip
bool getFlip (void) { return m_flip; }
/// set vertical flip
void setFlip (bool flip) { m_flip = flip; }
/// get source object
PyImage * getSource (const char * id);
/// set source object, return true, if source was set
bool setSource (const char * id, PyImage * source);
/// get pixel filter
PyFilter * getFilter (void) { return m_pyfilter; }
/// set pixel filter
void setFilter (PyFilter * filt);
/// calculate size (nearest power of 2)
static short calcSize (short size);
protected:
/// image buffer
unsigned int * m_image;
/// image buffer size
unsigned int m_imgSize;
/// image size
short m_size[2];
/// image is available
bool m_avail;
/// scale image to power 2 sizes
bool m_scale;
/// scale was changed
bool m_scaleChange;
/// flip image vertically
bool m_flip;
/// source image list
ImageSourceList m_sources;
/// flag for disabling addition and deletion of sources
bool m_staticSources;
/// pixel filter
PyFilter * m_pyfilter;
/// initialize image data
void init (short width, short height);
/// find source
ImageSourceList::iterator findSource (const char * id);
/// create new source
virtual ImageSource * newSource (const char * id) { return NULL; }
/// check source sizes
bool checkSourceSizes (void);
/// calculate image from sources and set its availability
virtual void calcImage (unsigned int texId) {}
/// perform loop detection
bool loopDetect (ImageBase * img);
/// template for image conversion
template<class FLT, class SRC> void convImage (FLT & filter, SRC srcBuff,
short * srcSize)
{
// destination buffer
unsigned int * dstBuff = m_image;
// pixel size from filter
unsigned int pixSize = filter.firstPixelSize();
// if no scaling is needed
if (srcSize[0] == m_size[0] && srcSize[1] == m_size[1])
// if flipping isn't required
if (!m_flip)
// copy bitmap
for (short y = 0; y < m_size[1]; ++y)
for (short x = 0; x < m_size[0]; ++x, ++dstBuff, srcBuff += pixSize)
// copy pixel
*dstBuff = filter.convert(srcBuff, x, y, srcSize, pixSize);
// otherwise flip image top to bottom
else
{
// go to last row of image
srcBuff += srcSize[0] * (srcSize[1] - 1) * pixSize;
// copy bitmap
for (short y = m_size[1] - 1; y >= 0; --y, srcBuff -= 2 * srcSize[0] * pixSize)
for (short x = 0; x < m_size[0]; ++x, ++dstBuff, srcBuff += pixSize)
// copy pixel
*dstBuff = filter.convert(srcBuff, x, y, srcSize, pixSize);
}
// else scale picture (nearest neighbour)
else
{
// interpolation accumulator
int accHeight = srcSize[1] >> 1;
// if flipping is required
if (m_flip)
// go to last row of image
srcBuff += srcSize[0] * (srcSize[1] - 1) * pixSize;
// process image rows
for (int y = 0; y < srcSize[1]; ++y)
{
// increase height accum
accHeight += m_size[1];
// if pixel row has to be drawn
if (accHeight >= srcSize[1])
{
// decrease accum
accHeight -= srcSize[1];
// width accum
int accWidth = srcSize[0] >> 1;
// process row
for (int x = 0; x < srcSize[0]; ++x)
{
// increase width accum
accWidth += m_size[0];
// if pixel has to be drawn
if (accWidth >= srcSize[0])
{
// decrease accum
accWidth -= srcSize[0];
// convert pixel
*dstBuff = filter.convert(srcBuff, x, m_flip ? srcSize[1] - y - 1 : y,
srcSize, pixSize);
// next pixel
++dstBuff;
}
// shift source pointer
srcBuff += pixSize;
}
}
// if pixel row will not be drawn
else
// move source pointer to next row
srcBuff += pixSize * srcSize[0];
// if y flipping is required
if (m_flip)
// go to previous row of image
srcBuff -= 2 * pixSize * srcSize[0];
}
}
}
// template for specific filter preprocessing
template <class F, class SRC> void filterImage (F & filt, SRC srcBuff, short * srcSize)
{
// find first filter in chain
FilterBase * firstFilter = NULL;
if (m_pyfilter != NULL) firstFilter = m_pyfilter->m_filter->findFirst();
// if first filter is available
if (firstFilter != NULL)
{
// python wrapper for filter
PyFilter pyFilt;
pyFilt.m_filter = &filt;
// set specified filter as first in chain
firstFilter->setPrevious(&pyFilt, false);
// convert video image
convImage(*(m_pyfilter->m_filter), srcBuff, srcSize);
// delete added filter
firstFilter->setPrevious(NULL, false);
}
// otherwise use given filter for conversion
else convImage(filt, srcBuff, srcSize);
// source was processed
m_avail = true;
}
};
// python structure for image filter
struct PyImage
{
PyObject_HEAD
// source object
ImageBase * m_image;
};
// size of id
const int SourceIdSize = 32;
/// class for source of image
class ImageSource
{
public:
/// constructor
ImageSource (const char * id);
/// destructor
virtual ~ImageSource (void);
/// get id
const char * getId (void) { return m_id; }
/// compare id to argument
bool is (const char * id);
/// get source object
PyImage * getSource (void) { return m_source; }
/// set source object
void setSource (PyImage * source);
/// get image from source
unsigned int * getImage (void);
/// get buffered image
unsigned int * getImageBuf (void) { return m_image; }
/// refresh source
void refresh (void);
/// get image size
short * getSize (void)
{
static short defSize [] = {0, 0};
return m_source != NULL ? m_source->m_image->getSize() : defSize;
}
protected:
/// id of source
char m_id [SourceIdSize];
/// pointer to source structure
PyImage * m_source;
/// buffered image from source
unsigned int * m_image;
private:
/// default constructor is forbidden
ImageSource (void) {}
};
// list of python image types
extern PyTypeList pyImageTypes;
// functions for python interface
// object initialization
template <class T> static int Image_init (PyObject * pySelf, PyObject * args, PyObject * kwds)
{
PyImage * self = reinterpret_cast<PyImage*>(pySelf);
// create source object
if (self->m_image != NULL) delete self->m_image;
self->m_image = new T();
// initialization succeded
return 0;
}
// object allocation
PyObject * Image_allocNew (PyTypeObject * type, PyObject * args, PyObject * kwds);
// object deallocation
void Image_dealloc (PyImage * self);
// get image data
PyObject * Image_getImage (PyImage * self, void * closure);
// get image size
PyObject * Image_getSize (PyImage * self, void * closure);
// refresh image - invalidate current content
PyObject * Image_refresh (PyImage * self);
// get scale
PyObject * Image_getScale (PyImage * self, void * closure);
// set scale
int Image_setScale (PyImage * self, PyObject * value, void * closure);
// get flip
PyObject * Image_getFlip (PyImage * self, void * closure);
// set flip
int Image_setFlip (PyImage * self, PyObject * value, void * closure);
// get filter source object
PyObject * Image_getSource (PyImage * self, PyObject * args);
// set filter source object
PyObject * Image_setSource (PyImage * self, PyObject * args);
// get pixel filter object
PyObject * Image_getFilter (PyImage * self, void * closure);
// set pixel filter object
int Image_setFilter (PyImage * self, PyObject * value, void * closure);
#endif