VideoTexture module.

The only compilation system that works for sure is the MSVC project files. I've tried my best to
update the other compilation system but I count on the community to check and fix them.
 
This is Zdeno Miklas video texture plugin ported to trunk. 
The original plugin API is maintained (can be found here http://home.scarlet.be/~tsi46445/blender/blendVideoTex.html)
EXCEPT for the following:

The module name is changed to VideoTexture (instead of blendVideoTex).

A new (and only) video source is now available: VideoFFmpeg()
You must pass 1 to 4 arguments when you create it (you can use named arguments):

VideoFFmpeg(file) : play a video file
VideoFFmpeg(file, capture, rate, width, height) : start a live video capture

file:
In the first form, file is a video file name, relative to startup directory.
It can also be a URL, FFmpeg will happily stream a video from a network source.
In the second form, file is empty or is a hint for the format of the video capture.
In Windows, file is ignored and should be empty or not specified.
In Linux, ffmpeg supports two types of device: VideoForLinux and DV1394. 
The user specifies the type of device with the file parameter:
   [<device_type>][:<standard>]
   <device_type> : 'v4l' for VideoForLinux, 'dv1394' for DV1394; default to 'v4l'
   <standard>    : 'pal', 'secam' or 'ntsc', default to 'ntsc'
The driver name is constructed automatically from the device types:
   v4l   : /dev/video<capture>
   dv1394: /dev/dv1394/<capture>
If you have different driver name, you can specify the driver name explicitely 
instead of device type. Examples of valid file parameter:
   /dev/v4l/video0:pal
   /dev/ieee1394/1:ntsc
   dv1394:ntsc
   v4l:pal
   :secam

capture: 
Defines the index number of the capture source, starting from 0. The first capture device is always 0.
The VideoTexutre modules knows that you want to start a live video capture when you set this parameter to a number >= 0. Setting this parameter < 0 indicates a video file playback. Default value is -1.

rate: 
the capture frame rate, by default 25 frames/sec

width: 
height: 
Width and height of the video capture in pixel, default value 0.
In Windows you must specify these values and they must fit with the capture device capability. 
For example, if you have a webcam that can capture at 160x120, 320x240 or 640x480, 
you must specify one of these couple of values or the opening of the video source will fail.
In Linux, default values are provided by the VideoForLinux driver if you don't specify width and height.

Simple example
**************
1. Texture definition script:

import VideoTexture

contr = GameLogic.getCurrentController()
obj = contr.getOwner()
if not hasattr(GameLogic, 'video'):
	matID = VideoTexture.materialID(obj, 'MAVideoMat')
	GameLogic.video = VideoTexture.Texture(obj, matID)
	GameLogic.vidSrc = VideoTexture.VideoFFmpeg('trailer_400p.ogg')
	# Streaming is also possible:
	#GameLogic.vidSrc = VideoTexture.VideoFFmpeg('http://10.32.1.10/trailer_400p.ogg')
	GameLogic.vidSrc.repeat = -1
	# If the video dimensions are not a power of 2, scaling must be done before
	# sending the texture to the GPU. This is done by default with gluScaleImage()
	# but you can also use a faster, but less precise, scaling by setting scale
	# to True. Best approach is to convert the video offline and set the dimensions right.
	GameLogic.vidSrc.scale = True
	# FFmpeg always delivers the video image upside down, so flipping is enabled automatically
	#GameLogic.vidSrc.flip = True

if contr.getSensors()[0].isPositive():
	GameLogic.video.source = GameLogic.vidSrc
	GameLogic.vidSrc.play()


2. Texture refresh script:

obj = GameLogic.getCurrentController().getOwner()
if hasattr(GameLogic, 'video') != 0:
  GameLogic.video.refresh(True)

You can download this demo here: 
http://home.scarlet.be/~tsi46445/blender/VideoTextureDemo.blend
http://home.scarlet.be/~tsi46445/blender/trailer_400p.ogg
This commit is contained in:
Benoit Bolsee 2008-10-31 22:35:52 +00:00
parent 77b4c66cc3
commit a8c4eef326
40 changed files with 6745 additions and 2 deletions

@ -17,6 +17,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "blender", "blender.vcproj",
{138DD16C-CC78-4F6C-A898-C8DA68D89067} = {138DD16C-CC78-4F6C-A898-C8DA68D89067}
{415BFD6E-64CF-422B-AF88-C07F040A7292} = {415BFD6E-64CF-422B-AF88-C07F040A7292}
{106AE171-0083-41D6-A949-20DB0E8DC251} = {106AE171-0083-41D6-A949-20DB0E8DC251}
{670EC17A-0548-4BBF-A27B-636C7C188139} = {670EC17A-0548-4BBF-A27B-636C7C188139}
{4C3AB78A-52CA-4276-A041-39776E52D8C8} = {4C3AB78A-52CA-4276-A041-39776E52D8C8}
{6B801390-5F95-4F07-81A7-97FBA046AACC} = {6B801390-5F95-4F07-81A7-97FBA046AACC}
{CAE37E91-6570-43AC-A4B4-7A37A4B0FC94} = {CAE37E91-6570-43AC-A4B4-7A37A4B0FC94}
@ -239,6 +240,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BL_gpu", "gpu\BL_gpu.vcproj
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TEX_Video", "..\gameengine\videotexture\TEX_Video.vcproj", "{670EC17A-0548-4BBF-A27B-636C7C188139}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfiguration) = preSolution
3D Plugin Debug = 3D Plugin Debug
@ -815,6 +820,18 @@ Global
{138DD16C-CC78-4F6C-A898-C8DA68D89067}.Debug.Build.0 = BlenderPlayer Debug|Win32
{138DD16C-CC78-4F6C-A898-C8DA68D89067}.Release.ActiveCfg = BlenderPlayer Release|Win32
{138DD16C-CC78-4F6C-A898-C8DA68D89067}.Release.Build.0 = BlenderPlayer Release|Win32
{670EC17A-0548-4BBF-A27B-636C7C188139}.3D Plugin Debug.ActiveCfg = Debug|Win32
{670EC17A-0548-4BBF-A27B-636C7C188139}.3D Plugin Release.ActiveCfg = Release|Win32
{670EC17A-0548-4BBF-A27B-636C7C188139}.Blender Debug.ActiveCfg = Debug|Win32
{670EC17A-0548-4BBF-A27B-636C7C188139}.Blender Debug.Build.0 = Debug|Win32
{670EC17A-0548-4BBF-A27B-636C7C188139}.Blender Release.ActiveCfg = Release|Win32
{670EC17A-0548-4BBF-A27B-636C7C188139}.Blender Release.Build.0 = Release|Win32
{670EC17A-0548-4BBF-A27B-636C7C188139}.BlenderPlayer Debug.ActiveCfg = Debug|Win32
{670EC17A-0548-4BBF-A27B-636C7C188139}.BlenderPlayer Debug.Build.0 = Debug|Win32
{670EC17A-0548-4BBF-A27B-636C7C188139}.BlenderPlayer Release.ActiveCfg = Release|Win32
{670EC17A-0548-4BBF-A27B-636C7C188139}.BlenderPlayer Release.Build.0 = Release|Win32
{670EC17A-0548-4BBF-A27B-636C7C188139}.Debug.ActiveCfg = Debug|Win32
{670EC17A-0548-4BBF-A27B-636C7C188139}.Release.ActiveCfg = Release|Win32
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
EndGlobalSection

@ -364,7 +364,7 @@ extern "C" void StartKetsjiShell(struct ScrArea *area,
initGameKeys();
initPythonConstraintBinding();
initMathutils();
//initVideoTexture();
initVideoTexture();
if (sceneconverter)
{

@ -40,6 +40,7 @@ SUBDIRS(
SceneGraph
Physics/Bullet
Physics/Sumo
VideoTexture
)
IF(WITH_PLAYER)

@ -15,7 +15,8 @@ SConscript(['BlenderRoutines/SConscript',
'Rasterizer/RAS_OpenGLRasterizer/SConscript',
'SceneGraph/SConscript',
'Physics/Bullet/SConscript',
'Physics/Sumo/SConscript'
'Physics/Sumo/SConscript',
'VideoTexture/SConscript'
])
if env['WITH_BF_PLAYER']:

@ -0,0 +1,75 @@
/* $Id$
-----------------------------------------------------------------------------
This source file is part of VideoTexture library
Copyright (c) 2006 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 BLENDTYPE_H
#define BLENDTYPE_H
/// class allows check type of blender python object and access its contained object
template <class PyObj> class BlendType
{
public:
/// constructor
BlendType (char * name) : m_name(name) {}
/// check blender type and return pointer to contained object or NULL (if type is not valid)
PyObj * checkType (PyObject * obj)
{
// if pointer to type isn't set
if (m_objType == NULL)
{
// compare names of type
if (strcmp(obj->ob_type->tp_name, m_name) == 0)
// if name of type match, save pointer to type
m_objType = obj->ob_type;
else
// if names of type don't match, return NULL
return NULL;
}
// if pointer to type is set and don't match to type of provided object, return NULL
else if (obj->ob_type != m_objType)
return NULL;
// return pointer to object
return (PyObj*)obj;
}
/// parse arguments to get object
PyObj * parseArg (PyObject * args)
{
// parse arguments
PyObject * obj;
if (PyArg_ParseTuple(args, "O", &obj))
// if successfully parsed, return pointer to object
return checkType(obj);
// otherwise return NULL
return NULL;
}
protected:
/// name of Python type
char * m_name;
/// pointer to Python type
PyTypeObject * m_objType;
};
#endif

@ -0,0 +1,60 @@
# $Id$
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU 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 General Public License for more details.
#
# You should have received a copy of the GNU 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.
#
# The Original Code is Copyright (C) 2006, Blender Foundation
# All rights reserved.
#
# The Original Code is: all of this file.
#
# Contributor(s): Jacques Beaurain.
#
# ***** END GPL LICENSE BLOCK *****
FILE(GLOB SRC *.cpp)
SET(INC
.
../../../source/gameengine/Ketsji
../../../source/gameengine/Expressions
../../../source/gameengine/GameLogic
../../../source/gameengine/SceneGraph
../../../source/gameengine/Rasterizer
../../../source/gameengine/Rasterizer/RAS_OpenGLRasterizer
../../../source/gameengine/BlenderRoutines
../../../source/blender/include
../../../source/blender/blenlib
../../../source/blender/blenkernel
../../../source/blender/makesdna
../../../source/blender/imbuf
../../../source/blender/python
../../../source/blender/gpu
../../../source/kernel/gen_system
../../../intern/string
../../../intern/moto/include
../../../intern/guardedalloc
../../../intern/SoundSystem
../../../extern/glew/include
${PYTHON_INC}
)
IF(WITH_FFMPEG)
SET(INC ${INC} ${FFMPEG_INC})
ADD_DEFINITIONS(-DWITH_FFMPEG)
ENDIF(WITH_FFMPEG)
BLENDERLIB(bf_videotex "${SRC}" "${INC}")
#env.BlenderLib ( 'bf_videotex', sources, Split(incs), [], libtype=['game','player'], priority=[25, 72], compileflags = cflags )

@ -0,0 +1,55 @@
/* $Id$
-----------------------------------------------------------------------------
This source file is part of VideoTexture library
Copyright (c) 2006 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 WIN32
#define WINDOWS_LEAN_AND_MEAN
#endif
#if !defined NULL
#define NULL 0
#endif
#if !defined HRESULT
#define HRESULT long
#endif
#if !defined DWORD
#define DWORD unsigned long
#endif
#if !defined S_OK
#define S_OK ((HRESULT)0L)
#endif
#if !defined BYTE
#define BYTE unsigned char
#endif
#if !defined WIN32
#define Sleep(time) sleep(time)
#endif
#if !defined FAILED
#define FAILED(Status) ((HRESULT)(Status)<0)
#endif
#include <iostream>

@ -0,0 +1,198 @@
/* $Id$
-----------------------------------------------------------------------------
This source file is part of VideoTexture library
Copyright (c) 2006 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.
-----------------------------------------------------------------------------
*/
#include <strstream>
#include <fstream>
#include <Python.h>
#include "Exception.h"
// exception identificators
ExceptionID ErrGeneral, ErrNotFound;
// exception descriptions
ExpDesc errGenerDesc (ErrGeneral, "General Error");
ExpDesc errNFoundDesc (ErrNotFound, "Error description not found");
// implementation of ExpDesc
// constructor
ExpDesc::ExpDesc (ExceptionID & exp, char * desc, RESULT hres)
: m_expID(exp), m_hRslt(hres), m_description(desc)
{
m_expDescs.push_back(this);
}
// destructor
ExpDesc::~ExpDesc (void) {}
// list of descriptions
std::vector<ExpDesc*> ExpDesc::m_expDescs;
// class Exception
// last exception description
std::string Exception::m_lastError;
// log file name
char * Exception::m_logFile = NULL;
// basic constructor
Exception::Exception ()
{
// default values
m_expID = &ErrNotFound;
m_hRslt = S_OK;
m_line = 0;
}
// destructor
Exception::~Exception () throw() { }
// copy constructor
Exception::Exception (const Exception & xpt)
{ copy (xpt); }
// assignment operator
Exception & Exception::operator= (const Exception & xpt)
{ copy (xpt); return *this; }
// get exception description
const char * Exception::what()
{
// set exception description
setXptDesc();
// return c string
return m_desc.c_str();
}
// debug version - with file and line of exception
Exception::Exception (ExceptionID & expID, RESULT rslt, char * fil, int lin)
: m_expID (&expID), m_hRslt (rslt)
{
// set file and line
if (strlen(fil) > 0 || lin > 0)
setFileLine (fil, lin);
}
// set file and line
void Exception::setFileLine (char * fil, int lin)
{
if (fil != NULL) m_fileName = fil;
m_line = lin;
}
// report exception
void Exception::report(void)
{
// set exception description
setXptDesc();
// set python error
PyErr_SetString(PyExc_RuntimeError, what());
// if log file is set
if (m_logFile != NULL)
{
// write description to log
std::ofstream logf (m_logFile, std::ios_base::app);
logf << m_fileName << ':' << m_line << ':' << m_desc << std::endl;
logf.flush();
logf.close();
}
}
// set exception description
void Exception::setXptDesc (void)
{
// if description is not set
if (m_desc.size() == 0)
{
// start of search -1
// found description "NotFound" 0
// found description without matching result 1
// found description with matching result 2
int best = -1;
// find exception description
for (std::vector<ExpDesc*>::iterator it = ExpDesc::m_expDescs.begin(); it != ExpDesc::m_expDescs.end(); ++it)
{
// use "NotFound", if there is not better
if (best < 0 && (*it)->isExp(&ErrNotFound) > 0)
{
(*it)->loadDesc(m_desc);
best = 0;
}
// match exception
int nBest = (*it)->isExp(m_expID, m_hRslt);
// if exception is matching better
if (nBest > 0 && best < nBest)
{
// set description
(*it)->loadDesc(m_desc);
best = nBest;
// if matching exactly, finish search
if (best == 2) break;
}
}
// add result code
// length of result code
const size_t rsltSize = 10;
// delimit description
const char delimRslt[] = ": ";
// set text of description
char rsltTxt[rsltSize];
std::ostrstream os(rsltTxt, rsltSize);
os << std::hex << m_hRslt << delimRslt;
// copy result to description
m_desc.insert(0, rsltTxt, rsltSize);
// copy exception description to last exception string
m_lastError = m_desc;
}
}
// copy exception data
void Exception::copy (const Exception & xpt)
{
// standard data
m_expID = xpt.m_expID;
m_hRslt = xpt.m_hRslt;
m_desc = xpt.m_desc;
// debug data
m_fileName = xpt.m_fileName;
m_line = xpt.m_line;
}

@ -0,0 +1,195 @@
/* $Id$
-----------------------------------------------------------------------------
This source file is part of VideoTexture library
Copyright (c) 2006 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 EXCEPTION_H
#define EXCEPTION_H
#include <exception>
#include <vector>
#include <string>
#include "Common.h"
#define CHCKHRSLTV(fnc,val,err) \
{ \
HRESULT macroHRslt = (fnc); \
if (macroHRslt != val) \
throw Exception (err, macroHRslt, __FILE__, __LINE__); \
}
#define THRWEXCP(err,hRslt) throw Exception (err, hRslt, __FILE__, __LINE__);
#if defined WIN32
#define CHCKHRSLT(fnc,err) \
{ \
HRESULT macroHRslt = (fnc); \
if (FAILED(macroHRslt)) \
throw Exception (err, macroHRslt, __FILE__, __LINE__); \
}
#else
#define CHCKHRSLT(fnc,err) CHCKHRSLTV(fnc,S_OK,err)
#endif
// forward declarations
class ExceptionID;
class Exception;
// exception identificators
extern ExceptionID ErrGeneral, ErrNotFound;
// result type
typedef long RESULT;
// class ExceptionID for exception identification
class ExceptionID
{
public:
// constructor a destructor
ExceptionID (void) {}
~ExceptionID (void) {}
private:
// not allowed
ExceptionID (const ExceptionID & obj) throw() {}
ExceptionID & operator= (const ExceptionID & obj) throw() { return *this; }
};
// class ExpDesc for exception description
class ExpDesc
{
public:
// constructor a destructor
ExpDesc (ExceptionID & exp, char * desc, RESULT hres = S_OK);
~ExpDesc (void);
// comparision function
// returns 0, if exception identification don't match at all
// returns 1, if only exception identification is matching
// returns 2, if both exception identification and result are matching
int isExp (ExceptionID * exp, RESULT hres = S_OK) throw()
{
// check exception identification
if (&m_expID == exp)
{
// check result value
if (m_hRslt == hres) return 2;
// only identification match
if (m_hRslt == S_OK) return 1;
}
// no match
return 0;
}
// get exception description
void loadDesc (std::string & desc) throw()
{
desc = m_description;
}
// list of exception descriptions
static std::vector<ExpDesc*> m_expDescs;
private:
// exception ID
ExceptionID & m_expID;
// result
RESULT m_hRslt;
// description
char * m_description;
// not allowed
ExpDesc (const ExpDesc & obj) : m_expID (ErrNotFound) {}
ExpDesc & operator= (const ExpDesc & obj) { return *this; }
};
// class Exception
class Exception : public std::exception
{
public:
// constructor
Exception ();
// destructor
virtual ~Exception () throw();
// copy constructor
Exception (const Exception & xpt);
// assignment operator
Exception & operator= (const Exception & xpt);
// get exception description
virtual const char * what(void);
// debug version of constructor
Exception (ExceptionID & expID, RESULT rslt, char * fil, int lin);
// set source file and line of exception
void setFileLine (char * fil, int lin);
// get description in string
std::string & getDesc (void) throw() { return m_desc; }
// report exception
virtual void report (void);
// get exception id
ExceptionID * getID (void) throw() { return m_expID; }
/// last exception description
static std::string m_lastError;
/// log file name
static char * m_logFile;
protected:
// exception identification
ExceptionID * m_expID;
// RESULT code
RESULT m_hRslt;
// exception description
std::string m_desc;
// set exception description
virtual void setXptDesc (void);
// copy exception
void copy (const Exception & xpt);
// file name where exception was thrown
std::string m_fileName;
// line number in file
int m_line;
};
#endif

@ -0,0 +1,150 @@
/* $Id$
-----------------------------------------------------------------------------
This source file is part of VideoTexture 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.
-----------------------------------------------------------------------------
*/
#include "FilterBase.h"
#include <Python.h>
#include <structmember.h>
// FilterBase class implementation
// constructor
FilterBase::FilterBase (void) : m_previous(NULL) {}
// destructor
FilterBase::~FilterBase (void)
{
// release Python objects, if not released yet
release();
}
// release python objects
void FilterBase::release (void)
{
// release previous filter object
setPrevious(NULL);
}
// set new previous filter
void FilterBase::setPrevious (PyFilter * filt, bool useRefCnt)
{
// if reference counting has to be used
if (useRefCnt)
{
// reference new filter
if (filt != NULL) Py_INCREF(filt);
// release old filter
Py_XDECREF(m_previous);
}
// set new previous filter
m_previous = filt;
}
// find first filter
FilterBase * FilterBase::findFirst (void)
{
// find first filter in chain
FilterBase * frst;
for (frst = this; frst->m_previous != NULL; frst = frst->m_previous->m_filter);
// set first filter
return frst;
}
// list offilter types
PyTypeList pyFilterTypes;
// functions for python interface
// object allocation
PyObject * Filter_allocNew (PyTypeObject * type, PyObject * args, PyObject * kwds)
{
// allocate object
PyFilter * self = reinterpret_cast<PyFilter*>(type->tp_alloc(type, 0));
// initialize object structure
self->m_filter = NULL;
// return allocated object
return reinterpret_cast<PyObject*>(self);
}
// object deallocation
void Filter_dealloc (PyFilter * self)
{
// release object attributes
if (self->m_filter != NULL)
{
self->m_filter->release();
delete self->m_filter;
self->m_filter = NULL;
}
}
// get previous pixel filter object
PyObject * Filter_getPrevious (PyFilter * self, void * closure)
{
// if filter object is available
if (self->m_filter != NULL)
{
// pixel filter object
PyObject * filt = reinterpret_cast<PyObject*>(self->m_filter->getPrevious());
// if filter is present
if (filt != NULL)
{
// return it
Py_INCREF(filt);
return filt;
}
}
// otherwise return none
Py_RETURN_NONE;
}
// set previous pixel filter object
int Filter_setPrevious (PyFilter * self, PyObject * value, void * closure)
{
// if filter object is available
if (self->m_filter != NULL)
{
// check new value
if (value == NULL || !pyFilterTypes.in(value->ob_type))
{
// report value error
PyErr_SetString(PyExc_TypeError, "Invalid type of value");
return -1;
}
// set new value
self->m_filter->setPrevious(reinterpret_cast<PyFilter*>(value));
}
// return success
return 0;
}

@ -0,0 +1,132 @@
/* $Id$
-----------------------------------------------------------------------------
This source file is part of VideoTexture 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 FILTERBASE_H
#define FILTERBASE_H
#include "Common.h"
#include <Python.h>
#include "PyTypeList.h"
// forward declaration
class FilterBase;
// python structure for filter
struct PyFilter
{
PyObject_HEAD
// source object
FilterBase * m_filter;
};
/// base class for pixel filters
class FilterBase
{
public:
/// constructor
FilterBase (void);
/// destructor
virtual ~FilterBase (void);
// release python objects
virtual void release (void);
/// convert pixel
template <class SRC> unsigned int convert (SRC src, short x, short y,
short * size, unsigned int pixSize)
{
return filter(src, x, y, size, pixSize,
convertPrevious(src, x, y, size, pixSize));
}
/// get previous filter
PyFilter * getPrevious (void) { return m_previous; }
/// set previous filter
void setPrevious (PyFilter * filt, bool useRefCnt = true);
/// find first filter in chain
FilterBase * findFirst (void);
/// get first filter's source pixel size
unsigned int firstPixelSize (void) { return findFirst()->getPixelSize(); }
protected:
/// previous pixel filter
PyFilter * m_previous;
/// filter pixel, source byte buffer
virtual unsigned int filter (unsigned char * src, short x, short y,
short * size, unsigned int pixSize, unsigned int val = 0)
{ return val; }
/// filter pixel, source int buffer
virtual unsigned int filter (unsigned int * src, short x, short y,
short * size, unsigned int pixSize, unsigned int val = 0)
{ return val; }
/// get source pixel size
virtual unsigned int getPixelSize (void) { return 1; }
/// get converted pixel from previous filters
template <class SRC> unsigned int convertPrevious (SRC src, short x, short y,
short * size, unsigned int pixSize)
{
// if previous filter doesn't exists, return source pixel
if (m_previous == NULL) return *src;
// otherwise return converted pixel
return m_previous->m_filter->convert(src, x, y, size, pixSize);
}
};
// list of python filter types
extern PyTypeList pyFilterTypes;
// functions for python interface
// object initialization
template <class T> static int Filter_init (PyObject * pySelf, PyObject * args, PyObject * kwds)
{
PyFilter * self = reinterpret_cast<PyFilter*>(pySelf);
// create filter object
if (self->m_filter != NULL) delete self->m_filter;
self->m_filter = new T();
// initialization succeded
return 0;
}
// object allocation
PyObject * Filter_allocNew (PyTypeObject * type, PyObject * args, PyObject * kwds);
// object deallocation
void Filter_dealloc (PyFilter * self);
// get previous pixel filter object
PyObject * Filter_getPrevious (PyFilter * self, void * closure);
// set previous pixel filter object
int Filter_setPrevious (PyFilter * self, PyObject * value, void * closure);
#endif

@ -0,0 +1,178 @@
/* $Id$
-----------------------------------------------------------------------------
This source file is part of VideoTexture 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.
-----------------------------------------------------------------------------
*/
#include <Python.h>
#include <structmember.h>
#include "FilterBlueScreen.h"
#include "FilterBase.h"
#include "PyTypeList.h"
// implementation FilterBlueScreen
// constructor
FilterBlueScreen::FilterBlueScreen (void)
{
// set color to blue
setColor(0, 0, 255);
// set limits
setLimits(64, 64);
}
// set color
void FilterBlueScreen::setColor (unsigned char red, unsigned char green, unsigned char blue)
{
m_color[0] = red;
m_color[1] = green;
m_color[2] = blue;
}
// set limits for color variation
void FilterBlueScreen::setLimits (unsigned short minLimit, unsigned short maxLimit)
{
m_limits[0] = minLimit;
m_limits[1] = maxLimit > minLimit ? maxLimit : minLimit;
// calculate square values
for (short idx = 0; idx < 2; ++idx)
m_squareLimits[idx] = m_limits[idx] * m_limits[idx];
// limits distance
m_limitDist = m_squareLimits[1] - m_squareLimits[0];
}
// cast Filter pointer to FilterBlueScreen
inline FilterBlueScreen * getFilter (PyFilter * self)
{ return static_cast<FilterBlueScreen*>(self->m_filter); }
// python methods and get/sets
// get color
static PyObject * getColor (PyFilter * self, void * closure)
{
return Py_BuildValue("[BBB]", getFilter(self)->getColor()[0],
getFilter(self)->getColor()[1], getFilter(self)->getColor()[2]);
}
// set color
static int setColor (PyFilter * self, PyObject * value, void * closure)
{
// check validity of parameter
if (value == NULL || !PySequence_Check(value) || PySequence_Length(value) != 3
|| !PyInt_Check(PySequence_Fast_GET_ITEM(value, 0))
|| !PyInt_Check(PySequence_Fast_GET_ITEM(value, 1))
|| !PyInt_Check(PySequence_Fast_GET_ITEM(value, 2)))
{
PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 3 ints");
return -1;
}
// set color
getFilter(self)->setColor((unsigned char)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 0))),
(unsigned char)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 1))),
(unsigned char)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 2))));
// success
return 0;
}
// get limits
static PyObject * getLimits (PyFilter * self, void * closure)
{
return Py_BuildValue("[II]", getFilter(self)->getLimits()[0],
getFilter(self)->getLimits()[1]);
}
// set limit
static int setLimits (PyFilter * self, PyObject * value, void * closure)
{
// check validity of parameter
if (value == NULL || !PySequence_Check(value) || PySequence_Length(value) != 2
|| !PyInt_Check(PySequence_Fast_GET_ITEM(value, 0))
|| !PyInt_Check(PySequence_Fast_GET_ITEM(value, 1)))
{
PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 2 ints");
return -1;
}
// set limits
getFilter(self)->setLimits((unsigned short)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 0))),
(unsigned short)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 1))));
// success
return 0;
}
// attributes structure
static PyGetSetDef filterBSGetSets[] =
{
{"color", (getter)getColor, (setter)setColor, "blue screen color", NULL},
{"limits", (getter)getLimits, (setter)setLimits, "blue screen color limits", NULL},
// attributes from FilterBase class
{"previous", (getter)Filter_getPrevious, (setter)Filter_setPrevious, "previous pixel filter", NULL},
{NULL}
};
// define python type
PyTypeObject FilterBlueScreenType =
{
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"VideoTexture.FilterBlueScreen", /*tp_name*/
sizeof(PyFilter), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor)Filter_dealloc,/*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/
"Filter for Blue Screen objects", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
NULL, /* tp_methods */
0, /* tp_members */
filterBSGetSets, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)Filter_init<FilterBlueScreen>, /* tp_init */
0, /* tp_alloc */
Filter_allocNew, /* tp_new */
};

@ -0,0 +1,98 @@
/* $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 FILTERBLUESCREEN_H
#define FILTERBLUESCREEN_H
#include "Common.h"
#include "FilterBase.h"
/// pixel filter for blue screen
class FilterBlueScreen : public FilterBase
{
public:
/// constructor
FilterBlueScreen (void);
/// destructor
virtual ~FilterBlueScreen (void) {}
/// get color
unsigned char * getColor (void) { return m_color; }
/// set color
void setColor (unsigned char red, unsigned char green, unsigned char blue);
/// get limits for color variation
unsigned short * getLimits (void) { return m_limits; }
/// set limits for color variation
void setLimits (unsigned short minLimit, unsigned short maxLimit);
protected:
/// blue screen color (red component first)
unsigned char m_color[3];
/// limits for color variation - first defines, where ends fully transparent
/// color, second defines, where begins fully opaque color
unsigned short m_limits[2];
/// squared limits for color variation
unsigned int m_squareLimits[2];
/// distance between squared limits
unsigned int m_limitDist;
/// filter pixel template, source int buffer
template <class SRC> unsigned int tFilter (SRC src, short x, short y,
short * size, unsigned int pixSize, unsigned int val)
{
// calculate differences
int difRed = int((val >> 16) & 0xFF) - int(m_color[0]);
int difGreen = int((val >> 8) & 0xFF) - int(m_color[1]);
int difBlue = int(val & 0xFF) - int(m_color[2]);
// calc distance from "blue screen" color
unsigned int dist = (unsigned int)(difRed * difRed + difGreen * difGreen
+ difBlue * difBlue);
// condition for fully transparent color
if (m_squareLimits[0] >= dist)
// return color with zero alpha
//return 0xFF000000;
return val & 0x00FFFFFF;
// condition for fully opaque color
else if (m_squareLimits[1] <= dist)
// return normal colour
return val | 0xFF000000;
// otherwise calc alpha
else
return (val & 0x00FFFFFF) | ((((dist - m_squareLimits[0]) << 8)
/ m_limitDist) << 24);
}
/// virtual filtering function for byte source
virtual unsigned int filter (unsigned char * src, short x, short y,
short * size, unsigned int pixSize, unsigned int val = 0)
{ return tFilter(src, x, y, size, pixSize, val); }
/// virtual filtering function for unsigned int source
virtual unsigned int filter (unsigned int * src, short x, short y,
short * size, unsigned int pixSize, unsigned int val = 0)
{ return tFilter(src, x, y, size, pixSize, val); }
};
#endif

@ -0,0 +1,350 @@
/* $Id$
-----------------------------------------------------------------------------
This source file is part of VideoTexture 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.
-----------------------------------------------------------------------------
*/
#include <Python.h>
#include <structmember.h>
#include "FilterColor.h"
#include "FilterBase.h"
#include "PyTypeList.h"
// implementation FilterGray
// attributes structure
static PyGetSetDef filterGrayGetSets[] =
{ // attributes from FilterBase class
{"previous", (getter)Filter_getPrevious, (setter)Filter_setPrevious, "previous pixel filter", NULL},
{NULL}
};
// define python type
PyTypeObject FilterGrayType =
{
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"VideoTexture.FilterGray", /*tp_name*/
sizeof(PyFilter), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor)Filter_dealloc,/*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/
"Filter for gray scale effect", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
NULL, /* tp_methods */
0, /* tp_members */
filterGrayGetSets, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)Filter_init<FilterGray>, /* tp_init */
0, /* tp_alloc */
Filter_allocNew, /* tp_new */
};
// implementation FilterColor
// constructor
FilterColor::FilterColor (void)
{
// reset color matrix to identity
for (int r = 0; r < 4; ++r)
for (int c = 0; c < 5; ++c)
m_matrix[r][c] = (r == c) ? 256 : 0;
}
// set color matrix
void FilterColor::setMatrix (ColorMatrix & mat)
{
// copy matrix
for (int r = 0; r < 4; ++r)
for (int c = 0; c < 5; ++c)
m_matrix[r][c] = mat[r][c];
}
// cast Filter pointer to FilterColor
inline FilterColor * getFilterColor (PyFilter * self)
{ return static_cast<FilterColor*>(self->m_filter); }
// python methods and get/sets
// get color matrix
static PyObject * getMatrix (PyFilter * self, void * closure)
{
ColorMatrix & mat = getFilterColor(self)->getMatrix();
return Py_BuildValue("((hhhhh)(hhhhh)(hhhhh)(hhhhh))",
mat[0][0], mat[0][1], mat[0][2], mat[0][3], mat[0][4],
mat[1][0], mat[1][1], mat[1][2], mat[1][3], mat[1][4],
mat[2][0], mat[2][1], mat[2][2], mat[2][3], mat[2][4],
mat[3][0], mat[3][1], mat[3][2], mat[3][3], mat[3][4]);
}
// set color matrix
static int setMatrix (PyFilter * self, PyObject * value, void * closure)
{
// matrix to store items
ColorMatrix mat;
// check validity of parameter
bool valid = value != NULL && PySequence_Check(value)
&& PySequence_Length(value) == 4;
// check rows
for (int r = 0; valid && r < 4; ++r)
{
// get row object
PyObject * row = PySequence_Fast_GET_ITEM(value, r);
// check sequence
valid = PySequence_Check(row) && PySequence_Length(row) == 5;
// check items
for (int c = 0; valid && c < 5; ++c)
{
// item must be int
valid = PyInt_Check(PySequence_Fast_GET_ITEM(row, c));
// if it is valid, save it in matrix
if (valid)
mat[r][c] = short(PyInt_AsLong(PySequence_Fast_GET_ITEM(row, c)));
}
}
// if parameter is not valid, report error
if (!valid)
{
PyErr_SetString(PyExc_TypeError, "The value must be a matrix [4][5] of ints");
return -1;
}
// set color matrix
getFilterColor(self)->setMatrix(mat);
// success
return 0;
}
// attributes structure
static PyGetSetDef filterColorGetSets[] =
{
{"matrix", (getter)getMatrix, (setter)setMatrix, "matrix [4][5] for color calculation", NULL},
// attributes from FilterBase class
{"previous", (getter)Filter_getPrevious, (setter)Filter_setPrevious, "previous pixel filter", NULL},
{NULL}
};
// define python type
PyTypeObject FilterColorType =
{
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"VideoTexture.FilterColor", /*tp_name*/
sizeof(PyFilter), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor)Filter_dealloc,/*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/
"Filter for color calculations", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
NULL, /* tp_methods */
0, /* tp_members */
filterColorGetSets, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)Filter_init<FilterColor>, /* tp_init */
0, /* tp_alloc */
Filter_allocNew, /* tp_new */
};
// implementation FilterLevel
// constructor
FilterLevel::FilterLevel (void)
{
// reset color levels
for (int r = 0; r < 4; ++r)
{
levels[r][0] = 0;
levels[r][1] = 0xFF << (r << 3);
levels[r][2] = 0xFF;
}
}
// set color levels
void FilterLevel::setLevels (ColorLevel & lev)
{
// copy levels
for (int r = 0; r < 4; ++r)
{
for (int c = 0; c < 2; ++c)
levels[r][c] = lev[r][c] << (r << 3);
levels[r][2] = lev[r][0] < lev[r][1] ? lev[r][1] - lev[r][0] : 1;
}
}
// cast Filter pointer to FilterLevel
inline FilterLevel * getFilterLevel (PyFilter * self)
{ return static_cast<FilterLevel*>(self->m_filter); }
// python methods and get/sets
// get color levels
static PyObject * getLevels (PyFilter * self, void * closure)
{
ColorLevel & lev = getFilterLevel(self)->getLevels();
return Py_BuildValue("((kk)(kk)(kk)(kk))",
lev[0][0], lev[0][1], lev[1][0] >> 8, lev[1][1] >> 8,
lev[2][0] >> 16, lev[2][1] >> 16, lev[3][0] >> 24, lev[3][1] >> 24);
}
// set color levels
static int setLevels (PyFilter * self, PyObject * value, void * closure)
{
// matrix to store items
ColorLevel lev;
// check validity of parameter
bool valid = value != NULL && PySequence_Check(value)
&& PySequence_Length(value) == 4;
// check rows
for (int r = 0; valid && r < 4; ++r)
{
// get row object
PyObject * row = PySequence_Fast_GET_ITEM(value, r);
// check sequence
valid = PySequence_Check(row) && PySequence_Length(row) == 2;
// check items
for (int c = 0; valid && c < 2; ++c)
{
// item must be int
valid = PyInt_Check(PySequence_Fast_GET_ITEM(row, c));
// if it is valid, save it in matrix
if (valid)
lev[r][c] = (unsigned long)(PyInt_AsLong(PySequence_Fast_GET_ITEM(row, c)));
}
}
// if parameter is not valid, report error
if (!valid)
{
PyErr_SetString(PyExc_TypeError, "The value must be a matrix [4][2] of ints");
return -1;
}
// set color matrix
getFilterLevel(self)->setLevels(lev);
// success
return 0;
}
// attributes structure
static PyGetSetDef filterLevelGetSets[] =
{
{"levels", (getter)getLevels, (setter)setLevels, "levels matrix [4] (min, max)", NULL},
// attributes from FilterBase class
{"previous", (getter)Filter_getPrevious, (setter)Filter_setPrevious, "previous pixel filter", NULL},
{NULL}
};
// define python type
PyTypeObject FilterLevelType =
{
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"VideoTexture.FilterLevel", /*tp_name*/
sizeof(PyFilter), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor)Filter_dealloc,/*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/
"Filter for levels calculations", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
NULL, /* tp_methods */
0, /* tp_members */
filterLevelGetSets, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)Filter_init<FilterLevel>, /* tp_init */
0, /* tp_alloc */
Filter_allocNew, /* tp_new */
};

@ -0,0 +1,164 @@
/* $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 FILTERCOLOR_H
#define FILTERCOLOR_H
#include "Common.h"
#include "FilterBase.h"
/// pixel filter for gray scale
class FilterGray : public FilterBase
{
public:
/// constructor
FilterGray (void) {}
/// destructor
virtual ~FilterGray (void) {}
protected:
/// filter pixel template, source int buffer
template <class SRC> unsigned int tFilter (SRC src, short x, short y,
short * size, unsigned int pixSize, unsigned int val)
{
// calculate gray value
unsigned int gray = (28 * ((val >> 16) & 0xFF) + 151 * ((val >> 8) & 0xFF)
+ 77 * (val & 0xFF)) & 0xFF00;
// return gray scale value
return (val & 0xFF000000) | gray << 8 | gray | gray >> 8;
}
/// virtual filtering function for byte source
virtual unsigned int filter (unsigned char * src, short x, short y,
short * size, unsigned int pixSize, unsigned int val = 0)
{ return tFilter(src, x, y, size, pixSize, val); }
/// virtual filtering function for unsigned int source
virtual unsigned int filter (unsigned int * src, short x, short y,
short * size, unsigned int pixSize, unsigned int val = 0)
{ return tFilter(src, x, y, size, pixSize, val); }
};
/// type for color matrix
typedef short ColorMatrix[4][5];
/// pixel filter for color calculation
class FilterColor : public FilterBase
{
public:
/// constructor
FilterColor (void);
/// destructor
virtual ~FilterColor (void) {}
/// get color matrix
ColorMatrix & getMatrix (void) { return m_matrix; }
/// set color matrix
void setMatrix (ColorMatrix & mat);
protected:
/// color calculation matrix
ColorMatrix m_matrix;
/// calculate one color component
unsigned int calcColor (unsigned int val, short idx)
{
return (((m_matrix[idx][0] * (val & 0xFF) + m_matrix[idx][1] * ((val >> 8) & 0xFF)
+ m_matrix[idx][2] * ((val >> 16) & 0xFF) + m_matrix[idx][3] * ((val >> 24) & 0xFF)
+ m_matrix[idx][4]) >> 8) & 0xFF) << (idx << 3);
}
/// filter pixel template, source int buffer
template <class SRC> unsigned int tFilter (SRC src, short x, short y,
short * size, unsigned int pixSize, unsigned int val)
{
// return calculated color
return calcColor(val, 0) | calcColor(val, 1) | calcColor(val, 2)
| calcColor(val, 3);
}
/// virtual filtering function for byte source
virtual unsigned int filter (unsigned char * src, short x, short y,
short * size, unsigned int pixSize, unsigned int val = 0)
{ return tFilter(src, x, y, size, pixSize, val); }
/// virtual filtering function for unsigned int source
virtual unsigned int filter (unsigned int * src, short x, short y,
short * size, unsigned int pixSize, unsigned int val = 0)
{ return tFilter(src, x, y, size, pixSize, val); }
};
/// type for color levels
typedef unsigned long ColorLevel[4][3];
/// pixel filter for color calculation
class FilterLevel : public FilterBase
{
public:
/// constructor
FilterLevel (void);
/// destructor
virtual ~FilterLevel (void) {}
/// get color matrix
ColorLevel & getLevels (void) { return levels; }
/// set color matrix
void setLevels (ColorLevel & lev);
protected:
/// color calculation matrix
ColorLevel levels;
/// calculate one color component
unsigned int calcColor (unsigned int val, short idx)
{
unsigned int col = val & (0xFF << (idx << 3));
if (col <= levels[idx][0]) col = 0;
else if (col >= levels[idx][1]) col = 0xFF << (idx << 3);
else if (idx < 3) col = (((col - levels[idx][0]) << 8) / levels[idx][2]) & (0xFF << (idx << 3));
else col = (((col - levels[idx][0]) / levels[idx][2]) << 8) & (0xFF << (idx << 3));
return col;
}
/// filter pixel template, source int buffer
template <class SRC> unsigned int tFilter (SRC src, short x, short y,
short * size, unsigned int pixSize, unsigned int val)
{
// return calculated color
return calcColor(val, 0) | calcColor(val, 1) | calcColor(val, 2)
| calcColor(val, 3);
}
/// virtual filtering function for byte source
virtual unsigned int filter (unsigned char * src, short x, short y,
short * size, unsigned int pixSize, unsigned int val = 0)
{ return tFilter(src, x, y, size, pixSize, val); }
/// virtual filtering function for unsigned int source
virtual unsigned int filter (unsigned int * src, short x, short y,
short * size, unsigned int pixSize, unsigned int val = 0)
{ return tFilter(src, x, y, size, pixSize, val); }
};
#endif

@ -0,0 +1,162 @@
/* $Id$
-----------------------------------------------------------------------------
This source file is part of VideoTexture 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.
-----------------------------------------------------------------------------
*/
#include <Python.h>
#include <structmember.h>
#include "FilterNormal.h"
#include "FilterBase.h"
#include "PyTypeList.h"
// implementation FilterNormal
// constructor
FilterNormal::FilterNormal (void) : m_colShift(0)
{
// set default depth
setDepth(4);
}
// set color shift
void FilterNormal::setColor (unsigned short colIdx)
{
// check validity of index
if (colIdx < 3)
// set color shift
m_colShift = colIdx << 3;
}
// set depth
void FilterNormal::setDepth (float depth)
{
m_depth = depth;
m_depthScale = depth / depthScaleKoef;
}
// cast Filter pointer to FilterNormal
inline FilterNormal * getFilter (PyFilter * self)
{ return static_cast<FilterNormal*>(self->m_filter); }
// python methods and get/sets
// get index of color used to calculate normal
static PyObject * getColor (PyFilter * self, void * closure)
{
return Py_BuildValue("H", getFilter(self)->getColor());
}
// set index of color used to calculate normal
static int setColor (PyFilter * self, PyObject * value, void * closure)
{
// check validity of parameter
if (value == NULL || !PyInt_Check(value))
{
PyErr_SetString(PyExc_TypeError, "The value must be a int");
return -1;
}
// set color index
getFilter(self)->setColor((unsigned short)(PyInt_AsLong(value)));
// success
return 0;
}
// get depth
static PyObject * getDepth (PyFilter * self, void * closure)
{
return Py_BuildValue("f", getFilter(self)->getDepth());
}
// set depth
static int setDepth (PyFilter * self, PyObject * value, void * closure)
{
// check validity of parameter
if (value == NULL || !PyFloat_Check(value))
{
PyErr_SetString(PyExc_TypeError, "The value must be a float");
return -1;
}
// set depth
getFilter(self)->setDepth(float(PyFloat_AsDouble(value)));
// success
return 0;
}
// attributes structure
static PyGetSetDef filterNormalGetSets[] =
{
{"colorIdx", (getter)getColor, (setter)setColor, "index of color used to calculate normal (0 - red, 1 - green, 2 - blue)", NULL},
{"depth", (getter)getDepth, (setter)setDepth, "depth of relief", NULL},
// attributes from FilterBase class
{"previous", (getter)Filter_getPrevious, (setter)Filter_setPrevious, "previous pixel filter", NULL},
{NULL}
};
// define python type
PyTypeObject FilterNormalType =
{
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"VideoTexture.FilterNormal", /*tp_name*/
sizeof(PyFilter), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor)Filter_dealloc,/*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/
"Filter for Blue Screen objects", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
NULL, /* tp_methods */
0, /* tp_members */
filterNormalGetSets, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)Filter_init<FilterNormal>, /* tp_init */
0, /* tp_alloc */
Filter_allocNew, /* tp_new */
};

@ -0,0 +1,98 @@
/* $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 FILTERNORMAL_H
#define FILTERNORMAL_H
#include "Common.h"
#include "FilterBase.h"
// scale constants for normals
const float depthScaleKoef = 255.0;
const float normScaleKoef = float(depthScaleKoef / 2.0);
/// pixel filter for normal mapping
class FilterNormal : public FilterBase
{
public:
/// constructor
FilterNormal (void);
/// destructor
virtual ~FilterNormal (void) {}
/// get index of color used to calculate normals
unsigned short getColor (void) { return m_colShift >> 3; }
/// set index of color used to calculate normals
void setColor (unsigned short colIdx);
/// get depth
float getDepth (void) { return m_depth; }
/// set depth
void setDepth (float depth);
protected:
/// depth of normal relief
float m_depth;
/// scale to calculate normals
float m_depthScale;
/// shift to used color component
unsigned short m_colShift;
/// filter pixel, source int buffer
template <class SRC> unsigned int tFilter (SRC * src, short x, short y,
short * size, unsigned int pixSize, unsigned int val = 0)
{
// get value of required color
int actPix = int((val >> m_colShift) & 0xFF);
// get upper and left pixel from actual pixel
int upPix = y > 0 ? int((convertPrevious(src - pixSize * size[0], x, y - 1,
size, pixSize) >> m_colShift) & 0xFF) : actPix;
int leftPix = x > 0 ? int((convertPrevious(src - pixSize, x - 1, y, size, pixSize)
>> m_colShift) & 0xFF) : actPix;
// height differences (from blue color)
float dx = (actPix - leftPix) * m_depthScale;
float dy = (actPix - upPix) * m_depthScale;
// normalize vector
float dz = float(normScaleKoef / sqrt(dx * dx + dy * dy + 1.0));
dx = dx * dz + normScaleKoef;
dy = dy * dz + normScaleKoef;
dz += normScaleKoef;
// return normal vector converted to color
return 0xFF000000 | int(dz) << 16 | int(dy) << 8 | int(dx);
}
/// filter pixel, source byte buffer
virtual unsigned int filter (unsigned char * src, short x, short y,
short * size, unsigned int pixSize, unsigned int val = 0)
{ return tFilter(src, x, y, size, pixSize, val); }
/// filter pixel, source int buffer
virtual unsigned int filter (unsigned int * src, short x, short y,
short * size, unsigned int pixSize, unsigned int val = 0)
{ return tFilter(src, x, y, size, pixSize, val); }
};
#endif

@ -0,0 +1,125 @@
/* $Id$
-----------------------------------------------------------------------------
This source file is part of VideoTexture 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.
-----------------------------------------------------------------------------
*/
// implementation
#include <Python.h>
#include <structmember.h>
#include "FilterSource.h"
#include "FilterBase.h"
#include "PyTypeList.h"
// FilterRGB24
// define python type
PyTypeObject FilterRGB24Type =
{
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"VideoTexture.FilterRGB24", /*tp_name*/
sizeof(PyFilter), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor)Filter_dealloc,/*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/
"Source filter RGB24 objects", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
NULL, /* tp_methods */
0, /* tp_members */
NULL, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)Filter_init<FilterRGB24>, /* tp_init */
0, /* tp_alloc */
Filter_allocNew, /* tp_new */
};
// FilterBGR24
// define python type
PyTypeObject FilterBGR24Type =
{
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"VideoTexture.FilterBGR24", /*tp_name*/
sizeof(PyFilter), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor)Filter_dealloc,/*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/
"Source filter BGR24 objects", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
NULL, /* tp_methods */
0, /* tp_members */
NULL, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)Filter_init<FilterBGR24>, /* tp_init */
0, /* tp_alloc */
Filter_allocNew, /* tp_new */
};

@ -0,0 +1,233 @@
/* $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 FILTERSOURCE_H
#define FILTERSOURCE_H
#include "Common.h"
#include "FilterBase.h"
/// class for RGB24 conversion
class FilterRGB24 : public FilterBase
{
public:
/// constructor
FilterRGB24 (void) {}
/// destructor
virtual ~FilterRGB24 (void) {}
/// get source pixel size
virtual unsigned int getPixelSize (void) { return 3; }
protected:
/// filter pixel, source byte buffer
virtual unsigned int filter (unsigned char * src, short x, short y,
short * size, unsigned int pixSize, unsigned int val)
{ return 0xFF000000 | src[0] << 16 | src[1] << 8 | src[2]; }
};
/// class for BGR24 conversion
class FilterBGR24 : public FilterBase
{
public:
/// constructor
FilterBGR24 (void) {}
/// destructor
virtual ~FilterBGR24 (void) {}
/// get source pixel size
virtual unsigned int getPixelSize (void) { return 3; }
protected:
/// filter pixel, source byte buffer
virtual unsigned int filter (unsigned char * src, short x, short y,
short * size, unsigned int pixSize, unsigned int val)
{ return 0xFF000000 | src[2] << 16 | src[1] << 8 | src[0]; }
};
/// class for YV12 conversion
class FilterYV12 : public FilterBase
{
public:
/// constructor
FilterYV12 (void) {}
/// destructor
virtual ~FilterYV12 (void) {}
/// get source pixel size
virtual unsigned int getPixelSize (void) { return 1; }
/// set pointers to color buffers
void setBuffs (unsigned char * buff, short * size)
{
unsigned int buffSize = size[0] * size[1];
m_buffV = buff + buffSize;
m_buffU = m_buffV + (buffSize >> 2);
m_pitchUV = size[0] >> 1;
}
protected:
/// begin of V buffer
unsigned char * m_buffV;
/// begin of U buffer
unsigned char * m_buffU;
/// pitch for V & U buffers
short m_pitchUV;
/// interpolation function
int interpol (int a, int b, int c, int d)
{ return (9 * (b + c) - a - d + 8) >> 4; }
/// common horizontal interpolation
int interpolH (unsigned char * src)
{ return interpol(*(src-1), *src, *(src+1), *(src+2)); }
/// common vertical interpolation
int interpolV (unsigned char * src)
{ return interpol(*(src-m_pitchUV), *src, *(src+m_pitchUV), *(src+2*m_pitchUV)); }
/// common joined vertical and horizontal interpolation
int interpolVH (unsigned char * src)
{
return interpol(interpolV(src-1), interpolV(src), interpolV(src+1),
interpolV(src+2));
}
/// is pixel on edge
bool isEdge (short x, short y, short * size)
{ return x <= 1 || x >= size[0] - 4 || y <= 1 || y >= size[1] - 4; }
/// get the first parameter on the low edge
unsigned char * interParA (unsigned char * src, short x, short size, short shift)
{ return x > 1 ? src - shift : src; }
/// get the third parameter on the high edge
unsigned char * interParC (unsigned char * src, short x, short size, short shift)
{ return x < size - 2 ? src + shift : src; }
/// get the fourth parameter on the high edge
unsigned char * interParD (unsigned char * src, short x, short size, short shift)
{ return x < size - 4 ? src + 2 * shift : x < size - 2 ? src + shift : src; }
/// horizontal interpolation on edges
int interpolEH (unsigned char * src, short x, short size)
{
return interpol(*interParA(src, x, size, 1), *src,
*interParC(src, x, size, 1), *interParD(src, x, size, 1));
}
/// vertical interpolation on edges
int interpolEV (unsigned char * src, short y, short size)
{
return interpol(*interParA(src, y, size, m_pitchUV), *src,
*interParC(src, y, size, m_pitchUV), *interParD(src, y, size, m_pitchUV));
}
/// joined vertical and horizontal interpolation on edges
int interpolEVH (unsigned char * src, short x, short y, short * size)
{
return interpol(interpolEV(interParA(src, x, size[0], 1), y, size[1]),
interpolEV(src, y, size[1]), interpolEV(interParC(src, x, size[0], 1), y, size[1]),
interpolEV(interParD(src, x, size[0], 1), y, size[1]));
}
/// filter pixel, source byte buffer
virtual unsigned int filter (unsigned char * src, short x, short y,
short * size, unsigned int pixSize, unsigned int val)
{
// V & U offset
long offset = (x >> 1) + m_pitchUV * (y >> 1);
// get modified YUV -> CDE: C = Y - 16; D = U - 128; E = V - 128
int c = *src - 16;
int d = m_buffU[offset] - 128;
int e = m_buffV[offset] - 128;
// if horizontal interpolation is needed
if ((x & 1) == 1)
// if vertical interpolation is needed too
if ((y & 1) == 1)
// if this pixel is on the edge
if (isEdge(x, y, size))
{
// get U & V from edge
d = interpolEVH(m_buffU + offset, x, y, size) - 128;
e = interpolEVH(m_buffV + offset, x, y, size) - 128;
}
// otherwise get U & V from inner range
else
{
d = interpolVH(m_buffU + offset) - 128;
e = interpolVH(m_buffV + offset) - 128;
}
// otherwise use horizontal interpolation only
else
// if this pixel is on the edge
if (isEdge(x, y, size))
{
// get U & V from edge
d = interpolEH(m_buffU + offset, x, size[0]) - 128;
e = interpolEH(m_buffV + offset, x, size[0]) - 128;
}
// otherwise get U & V from inner range
else
{
d = interpolH(m_buffU + offset) - 128;
e = interpolH(m_buffV + offset) - 128;
}
// otherwise if only vertical interpolation is needed
else if ((y & 1) == 1)
// if this pixel is on the edge
if (isEdge(x, y, size))
{
// get U & V from edge
d = interpolEV(m_buffU + offset, y, size[1]) - 128;
e = interpolEV(m_buffV + offset, y, size[1]) - 128;
}
// otherwise get U & V from inner range
else
{
d = interpolV(m_buffU + offset) - 128;
e = interpolV(m_buffV + offset) - 128;
}
// convert to RGB
// R = clip(( 298 * C + 409 * E + 128) >> 8)
// G = clip(( 298 * C - 100 * D - 208 * E + 128) >> 8)
// B = clip(( 298 * C + 516 * D + 128) >> 8)
int red = (298 * c + 409 * e + 128) >> 8;
if (red >= 0x100) red = 0xFF;
else if (red < 0) red = 0;
int green = 298 * c - 100 * d - 208 * e;
if (green > 0x10000) green = 0xFF00;
else if (green < 0) green = 0;
int blue = (298 * c + 516 * d + 128) << 8;
if (blue > 0x1000000) blue = 0xFF0000;
else if (blue < 0) blue = 0;
// return result
return 0xFF000000 | blue & 0xFF0000 | green & 0xFF00
| red & 0xFF;
}
};
#endif

@ -0,0 +1,529 @@
/* $Id$
-----------------------------------------------------------------------------
This source file is part of VideoTexture 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.
-----------------------------------------------------------------------------
*/
#include "ImageBase.h"
#include <vector>
#include <string.h>
#include <Python.h>
#include <structmember.h>
#include "FilterBase.h"
#include "Exception.h"
// ImageBase class implementation
// constructor
ImageBase::ImageBase (bool staticSrc) : m_image(NULL), m_imgSize(0),
m_avail(false), m_scale(false), m_scaleChange(false), m_flip(false),
m_staticSources(staticSrc), m_pyfilter(NULL)
{
m_size[0] = m_size[1] = 0;
}
// destructor
ImageBase::~ImageBase (void)
{
// release image
delete [] m_image;
}
// release python objects
bool ImageBase::release (void)
{
// iterate sources
for (ImageSourceList::iterator it = m_sources.begin(); it != m_sources.end(); ++it)
{
// release source object
delete *it;
*it = NULL;
}
// release filter object
Py_XDECREF(m_pyfilter);
m_pyfilter = NULL;
return true;
}
// get image
unsigned int * ImageBase::getImage (unsigned int texId)
{
// if image is not available
if (!m_avail)
{
// if there are any sources
if (!m_sources.empty())
{
// get images from sources
for (ImageSourceList::iterator it = m_sources.begin(); it != m_sources.end(); ++it)
// get source image
(*it)->getImage();
// init image
init(m_sources[0]->getSize()[0], m_sources[0]->getSize()[1]);
}
// calculate new image
calcImage(texId);
}
// if image is available, return it, otherwise NULL
return m_avail ? m_image : NULL;
}
// refresh image source
void ImageBase::refresh (void)
{
// invalidate this image
m_avail = false;
// refresh all sources
for (ImageSourceList::iterator it = m_sources.begin(); it != m_sources.end(); ++it)
(*it)->refresh();
}
// get source object
PyImage * ImageBase::getSource (const char * id)
{
// find source
ImageSourceList::iterator src = findSource(id);
// return it, if found
return src != m_sources.end() ? (*src)->getSource() : NULL;
}
// set source object
bool ImageBase::setSource (const char * id, PyImage * source)
{
// find source
ImageSourceList::iterator src = findSource(id);
// check source loop
if (source != NULL && source->m_image->loopDetect(this))
return false;
// if found, set new object
if (src != m_sources.end())
// if new object is not empty or sources are static
if (source != NULL || m_staticSources)
// replace previous source
(*src)->setSource(source);
// otherwise delete source
else
m_sources.erase(src);
// if source is not found and adding is allowed
else
if (!m_staticSources)
{
// create new source
ImageSource * newSrc = newSource(id);
newSrc->setSource(source);
// if source was created, add it to source list
if (newSrc != NULL) m_sources.push_back(newSrc);
}
// otherwise source wasn't set
else
return false;
// source was set
return true;
}
// set pixel filter
void ImageBase::setFilter (PyFilter * filt)
{
// reference new filter
if (filt != NULL) Py_INCREF(filt);
// release previous filter
Py_XDECREF(m_pyfilter);
// set new filter
m_pyfilter = filt;
}
// initialize image data
void ImageBase::init (short width, short height)
{
// if image has to be scaled
if (m_scale)
{
// recalc sizes of image
width = calcSize(width);
height = calcSize(height);
}
// if sizes differ
if (width != m_size[0] || height != m_size[1])
{
// new buffer size
unsigned int newSize = width * height;
// if new buffer is larger than previous
if (newSize > m_imgSize)
{
// set new buffer size
m_imgSize = newSize;
// release previous and create new buffer
delete [] m_image;
m_image = new unsigned int[m_imgSize];
}
// new image size
m_size[0] = width;
m_size[1] = height;
// scale was processed
m_scaleChange = false;
}
}
// find source
ImageSourceList::iterator ImageBase::findSource (const char * id)
{
// iterate sources
ImageSourceList::iterator it;
for (it = m_sources.begin(); it != m_sources.end(); ++it)
// if id matches, return iterator
if ((*it)->is(id)) return it;
// source not found
return it;
}
// check sources sizes
bool ImageBase::checkSourceSizes (void)
{
// reference size
short * refSize = NULL;
// iterate sources
for (ImageSourceList::iterator it = m_sources.begin(); it != m_sources.end(); ++it)
{
// get size of current source
short * curSize = (*it)->getSize();
// if size is available and is not empty
if (curSize[0] != 0 && curSize[1] != 0)
// if reference size is not set
if (refSize == NULL)
// set current size as reference
refSize = curSize;
// otherwise check with current size
else if (curSize[0] != refSize[0] || curSize[1] != refSize[1])
// if they don't match, report it
return false;
}
// all sizes match
return true;
}
// compute nearest power of 2 value
short ImageBase::calcSize (short size)
{
// while there is more than 1 bit in size value
while ((size & (size - 1)) != 0)
// clear last bit
size = size & (size - 1);
// return result
return size;
}
// perform loop detection
bool ImageBase::loopDetect (ImageBase * img)
{
// if this object is the same as parameter, loop is detected
if (this == img) return true;
// check all sources
for (ImageSourceList::iterator it = m_sources.begin(); it != m_sources.end(); ++it)
// if source detected loop, return this result
if ((*it)->getSource() != NULL && (*it)->getSource()->m_image->loopDetect(img))
return true;
// no loop detected
return false;
}
// ImageSource class implementation
// constructor
ImageSource::ImageSource (const char * id) : m_source(NULL), m_image(NULL)
{
// copy id
int idx;
for (idx = 0; id[idx] != '\0' && idx < SourceIdSize - 1; ++idx)
m_id[idx] = id[idx];
m_id[idx] = '\0';
}
// destructor
ImageSource::~ImageSource (void)
{
// release source
setSource(NULL);
}
// compare id
bool ImageSource::is (const char * id)
{
for (char * myId = m_id; *myId != '\0'; ++myId, ++id)
if (*myId != *id) return false;
return *id == '\0';
}
// set source object
void ImageSource::setSource (PyImage * source)
{
// reference new source
if (source != NULL) Py_INCREF(source);
// release previous source
Py_XDECREF(m_source);
// set new source
m_source = source;
}
// get image from source
unsigned int * ImageSource::getImage (void)
{
// if source is available
if (m_source != NULL)
// get image from source
m_image = m_source->m_image->getImage();
// otherwise reset buffer
else
m_image = NULL;
// return image
return m_image;
}
// refresh source
void ImageSource::refresh (void)
{
// if source is available, refresh it
if (m_source != NULL) m_source->m_image->refresh();
}
// list of image types
PyTypeList pyImageTypes;
// functions for python interface
// object allocation
PyObject * Image_allocNew (PyTypeObject * type, PyObject * args, PyObject * kwds)
{
// allocate object
PyImage * self = reinterpret_cast<PyImage*>(type->tp_alloc(type, 0));
// initialize object structure
self->m_image = NULL;
// return allocated object
return reinterpret_cast<PyObject*>(self);
}
// object deallocation
void Image_dealloc (PyImage * self)
{
// release object attributes
if (self->m_image != NULL)
{
// if release requires deleting of object, do it
if (self->m_image->release())
delete self->m_image;
self->m_image = NULL;
}
}
// get image data
PyObject * Image_getImage (PyImage * self, void * closure)
{
try
{
// get image
unsigned int * image = self->m_image->getImage();
return Py_BuildValue("s#", image, self->m_image->getBuffSize());
}
catch (Exception & exp)
{
exp.report();
}
Py_RETURN_NONE;
}
// get image size
PyObject * Image_getSize (PyImage * self, void * closure)
{
return Py_BuildValue("(hh)", self->m_image->getSize()[0],
self->m_image->getSize()[1]);
}
// refresh image
PyObject * Image_refresh (PyImage * self)
{
self->m_image->refresh();
Py_RETURN_NONE;
}
// get scale
PyObject * Image_getScale (PyImage * self, void * closure)
{
if (self->m_image != NULL && self->m_image->getScale()) Py_RETURN_TRUE;
else Py_RETURN_FALSE;
}
// set scale
int Image_setScale (PyImage * self, PyObject * value, void * closure)
{
// check parameter, report failure
if (value == NULL || !PyBool_Check(value))
{
PyErr_SetString(PyExc_TypeError, "The value must be a bool");
return -1;
}
// set scale
if (self->m_image != NULL) self->m_image->setScale(value == Py_True);
// success
return 0;
}
// get flip
PyObject * Image_getFlip (PyImage * self, void * closure)
{
if (self->m_image != NULL && self->m_image->getFlip()) Py_RETURN_TRUE;
else Py_RETURN_FALSE;
}
// set flip
int Image_setFlip (PyImage * self, PyObject * value, void * closure)
{
// check parameter, report failure
if (value == NULL || !PyBool_Check(value))
{
PyErr_SetString(PyExc_TypeError, "The value must be a bool");
return -1;
}
// set scale
if (self->m_image != NULL) self->m_image->setFlip(value == Py_True);
// success
return 0;
}
// get filter source object
PyObject * Image_getSource (PyImage * self, PyObject * args)
{
// get arguments
char * id;
if (self->m_image != NULL && PyArg_ParseTuple(args, "s", &id))
{
// get source object
PyObject * src = reinterpret_cast<PyObject*>(self->m_image->getSource(id));
// if source is available
if (src != NULL)
{
// return source
Py_INCREF(src);
return src;
}
}
// source was not found
Py_RETURN_NONE;
}
// set filter source object
PyObject * Image_setSource (PyImage * self, PyObject * args)
{
// get arguments
char * id;
PyObject * obj;
if (self->m_image != NULL && PyArg_ParseTuple(args, "sO", &id, &obj))
{
// check type of object
if (pyImageTypes.in(obj->ob_type))
{
// convert to image struct
PyImage * img = reinterpret_cast<PyImage*>(obj);
// set source
if (!self->m_image->setSource(id, img))
{
// if not set, retport error
PyErr_SetString(PyExc_RuntimeError, "Invalid source or id");
return NULL;
}
}
// else report error
else
{
PyErr_SetString(PyExc_RuntimeError, "Invalid type of object");
return NULL;
}
}
// return none
Py_RETURN_NONE;
}
// get pixel filter object
PyObject * Image_getFilter (PyImage * self, void * closure)
{
// if image object is available
if (self->m_image != NULL)
{
// pixel filter object
PyObject * filt = reinterpret_cast<PyObject*>(self->m_image->getFilter());
// if filter is present
if (filt != NULL)
{
// return it
Py_INCREF(filt);
return filt;
}
}
// otherwise return none
Py_RETURN_NONE;
}
// set pixel filter object
int Image_setFilter (PyImage * self, PyObject * value, void * closure)
{
// if image object is available
if (self->m_image != NULL)
{
// check new value
if (value == NULL || !pyFilterTypes.in(value->ob_type))
{
// report value error
PyErr_SetString(PyExc_TypeError, "Invalid type of value");
return -1;
}
// set new value
self->m_image->setFilter(reinterpret_cast<PyFilter*>(value));
}
// return success
return 0;
}

@ -0,0 +1,349 @@
/* $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 <Python.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

@ -0,0 +1,166 @@
/* $Id$
-----------------------------------------------------------------------------
This source file is part of VideoTexture 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.
-----------------------------------------------------------------------------
*/
// implementation
#include <Python.h>
#include <structmember.h>
#include "ImageBuff.h"
#include "ImageBase.h"
#include "FilterSource.h"
// default filter
FilterBGR24 defFilter;
// load image from buffer
void ImageBuff::load (unsigned char * img, short width, short height)
{
// initialize image buffer
init(width, height);
// original size
short orgSize[2] = {width, height};
// is filter available
if (m_pyfilter != NULL)
// use it to process image
convImage(*(m_pyfilter->m_filter), img, orgSize);
else
// otherwise use default filter
convImage(defFilter, img, orgSize);
// image is available
m_avail = true;
}
// cast Image pointer to ImageBuff
inline ImageBuff * getImageBuff (PyImage * self)
{ return static_cast<ImageBuff*>(self->m_image); }
// python methods
// load image
static PyObject * load (PyImage * self, PyObject * args)
{
// parameters: string image buffer, its size, width, height
unsigned char * buff;
unsigned int buffSize;
short width;
short height;
// parse parameters
if (!PyArg_ParseTuple(args, "s#hh", &buff, &buffSize, &width, &height))
{
// report error
PyErr_SetString(PyExc_TypeError, "Parameters are not correct");
return NULL;
}
// else check buffer size
else
{
// calc proper buffer size
unsigned int propSize = width * height;
// use pixel size from filter
if (self->m_image->getFilter() != NULL)
propSize *= self->m_image->getFilter()->m_filter->firstPixelSize();
else
propSize *= defFilter.firstPixelSize();
// check if buffer size is correct
if (propSize != buffSize)
{
// if not, report error
PyErr_SetString(PyExc_TypeError, "Buffer hasn't correct size");
return NULL;
}
else
// if correct, load image
getImageBuff(self)->load(buff, width, height);
}
Py_RETURN_NONE;
}
// methods structure
static PyMethodDef imageBuffMethods[] =
{
{"load", (PyCFunction)load, METH_VARARGS, "Load image from buffer"},
{NULL}
};
// attributes structure
static PyGetSetDef imageBuffGetSets[] =
{ // attributes from ImageBase class
{"image", (getter)Image_getImage, NULL, "image data", NULL},
{"size", (getter)Image_getSize, NULL, "image size", NULL},
{"scale", (getter)Image_getScale, (setter)Image_setScale, "fast scale of image (near neighbour)", NULL},
{"flip", (getter)Image_getFlip, (setter)Image_setFlip, "flip image vertically", NULL},
{"filter", (getter)Image_getFilter, (setter)Image_setFilter, "pixel filter", NULL},
{NULL}
};
// define python type
PyTypeObject ImageBuffType =
{
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"VideoTexture.ImageBuff", /*tp_name*/
sizeof(PyImage), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor)Image_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/
"Image source from image buffer", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
imageBuffMethods, /* tp_methods */
0, /* tp_members */
imageBuffGetSets, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)Image_init<ImageBuff>, /* tp_init */
0, /* tp_alloc */
Image_allocNew, /* tp_new */
};

@ -0,0 +1,51 @@
/* $Id$
-----------------------------------------------------------------------------
This source file is part of VideoTexture 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 IMAGEBUFF_H
#define IMAGEBUFF_H
#include "Common.h"
#include "ImageBase.h"
/// class for image buffer
class ImageBuff : public ImageBase
{
public:
/// constructor
ImageBuff (void) : ImageBase(true) {}
/// destructor
virtual ~ImageBuff (void) {}
/// load image from buffer
void load (unsigned char * img, short width, short height);
/// refresh image - do nothing
virtual void refresh (void) {}
};
#endif

@ -0,0 +1,205 @@
/* $Id$
-----------------------------------------------------------------------------
This source file is part of VideoTexture 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.
-----------------------------------------------------------------------------
*/
// implementation
#include <Python.h>
#include <structmember.h>
#include "ImageMix.h"
#include "ImageBase.h"
#include "Exception.h"
// cast ImageSource pointer to ImageSourceMix
inline ImageSourceMix * getImageSourceMix (ImageSource * src)
{ return static_cast<ImageSourceMix*>(src); }
// get weight
short ImageMix::getWeight (const char * id)
{
// find source
ImageSourceList::iterator src = findSource(id);
// if found, return its weight
return src != m_sources.end() ? getImageSourceMix(*src)->getWeight() : 0;
}
// set weight
bool ImageMix::setWeight (const char * id, short weight)
{
// find source
ImageSourceList::iterator src = findSource(id);
// if source isn't found, report it
if (src == m_sources.end()) return false;
// set its weight
getImageSourceMix(*src)->setWeight(weight);
return true;
}
static ExceptionID ImageSizesNotMatch;
static ExpDesc ImageSizesNotMatchDesc (ImageSizesNotMatch, "Image sizes of sources are different");
// calculate image from sources and set its availability
void ImageMix::calcImage (unsigned int texId)
{
// check source sizes
if (!checkSourceSizes()) THRWEXCP(ImageSizesNotMatch, S_OK);
// set offsets to image buffers
for (ImageSourceList::iterator it = m_sources.begin(); it != m_sources.end(); ++it)
// if image buffer is available
if ((*it)->getImageBuf() != NULL)
// set its offset
getImageSourceMix(*it)->setOffset(m_sources[0]->getImageBuf());
// otherwise don't calculate image
else
return;
// if there is only single source
if (m_sources.size() == 1)
{
// use single filter
FilterBase mixFilt;
// fiter and convert image
filterImage(mixFilt, m_sources[0]->getImageBuf(), m_sources[0]->getSize());
}
// otherwise use mix filter to merge source images
else
{
FilterImageMix mixFilt (m_sources);
// fiter and convert image
filterImage(mixFilt, m_sources[0]->getImageBuf(), m_sources[0]->getSize());
}
}
// cast Image pointer to ImageMix
inline ImageMix * getImageMix (PyImage * self)
{ return static_cast<ImageMix*>(self->m_image); }
// python methods
// get source weight
PyObject * getWeight (PyImage * self, PyObject * args)
{
// weight
short weight = 0;
// get arguments
char * id;
if (self->m_image != NULL && PyArg_ParseTuple(args, "s", &id))
// get weight
weight = getImageMix(self)->getWeight(id);
// return weight
return Py_BuildValue("h", weight);
}
// set source weight
PyObject * setWeight (PyImage * self, PyObject * args)
{
// get arguments
char * id;
short weight = 0;
if (self->m_image != NULL && PyArg_ParseTuple(args, "sh", &id, &weight))
// set weight
if (!getImageMix(self)->setWeight(id, weight))
{
// if not set, report error
PyErr_SetString(PyExc_RuntimeError, "Invalid id of source");;
return NULL;
}
// return none
Py_RETURN_NONE;
}
// methods structure
static PyMethodDef imageMixMethods[] =
{
{"getSource", (PyCFunction)Image_getSource, METH_VARARGS, "get image source"},
{"setSource", (PyCFunction)Image_setSource, METH_VARARGS, "set image source"},
{"getWeight", (PyCFunction)getWeight, METH_VARARGS, "get image source weight"},
{"setWeight", (PyCFunction)setWeight, METH_VARARGS, "set image source weight"},
// methods from ImageBase class
{"refresh", (PyCFunction)Image_refresh, METH_NOARGS, "Refresh image - invalidate its current content"},
{NULL}
};
// attributes structure
static PyGetSetDef imageMixGetSets[] =
{ // attributes from ImageBase class
{"image", (getter)Image_getImage, NULL, "image data", NULL},
{"size", (getter)Image_getSize, NULL, "image size", NULL},
{"scale", (getter)Image_getScale, (setter)Image_setScale, "fast scale of image (near neighbour)", NULL},
{"flip", (getter)Image_getFlip, (setter)Image_setFlip, "flip image vertically", NULL},
{"filter", (getter)Image_getFilter, (setter)Image_setFilter, "pixel filter", NULL},
{NULL}
};
// define python type
PyTypeObject ImageMixType =
{
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"VideoTexture.ImageMix", /*tp_name*/
sizeof(PyImage), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor)Image_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/
"Image mixer", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
imageMixMethods, /* tp_methods */
0, /* tp_members */
imageMixGetSets, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)Image_init<ImageMix>, /* tp_init */
0, /* tp_alloc */
Image_allocNew, /* tp_new */
};

@ -0,0 +1,123 @@
/* $Id$
-----------------------------------------------------------------------------
This source file is part of VideoTexture 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 IMAGEMIX_H
#define IMAGEMIX_H
#include "Common.h"
#include "ImageBase.h"
#include "FilterBase.h"
/// class for source mixing
class ImageSourceMix : public ImageSource
{
public:
/// constructor
ImageSourceMix (const char * id) : ImageSource(id), m_weight(0x100) {}
/// destructor
virtual ~ImageSourceMix (void) {}
/// get offset
long long getOffset (void) { return m_offset; }
/// set offset
void setOffset (unsigned int * firstImg) { m_offset = m_image - firstImg; }
/// get weight
short getWeight (void) { return m_weight; }
/// set weight
void setWeight (short weight) { m_weight = weight; }
protected:
/// buffer offset to the first source buffer
long long m_offset;
/// source weight
short m_weight;
};
/// class for image mixer
class ImageMix : public ImageBase
{
public:
/// constructor
ImageMix (void) : ImageBase(false) {}
/// destructor
virtual ~ImageMix (void) {}
/// get weight
short getWeight (const char * id);
/// set weight
bool setWeight (const char * id, short weight);
protected:
/// create new source
virtual ImageSource * newSource (const char * id) { return new ImageSourceMix(id); }
/// calculate image from sources and set its availability
virtual void calcImage (unsigned int texId);
};
/// pixel filter for image mixer
class FilterImageMix : public FilterBase
{
public:
/// constructor
FilterImageMix (ImageSourceList & sources) : m_sources(sources) {}
/// destructor
virtual ~FilterImageMix (void) {}
protected:
/// source list
ImageSourceList & m_sources;
/// filter pixel, source int buffer
virtual unsigned int filter (unsigned int * src, short x, short y,
short * size, unsigned int pixSize, unsigned int val = 0)
{
// resulting pixel color
int color[] = {0, 0, 0, 0};
// iterate sources
for (ImageSourceList::iterator it = m_sources.begin(); it != m_sources.end(); ++it)
{
// get pointer to mixer source
ImageSourceMix * mixSrc = static_cast<ImageSourceMix*>(*it);
// add weighted source pixel to result
color[0] += mixSrc->getWeight() * (src[mixSrc->getOffset()] & 0xFF);
color[1] += mixSrc->getWeight() * ((src[mixSrc->getOffset()] >> 8) & 0xFF);
color[2] += mixSrc->getWeight() * ((src[mixSrc->getOffset()] >> 16) & 0xFF);
color[3] += mixSrc->getWeight() * ((src[mixSrc->getOffset()] >> 24) & 0xFF);
}
// return resulting color
return ((color[0] >> 8) & 0xFF) | (color[1] & 0xFF00)
| ((color[2] << 8) & 0xFF0000) | ((color[3] << 16) & 0xFF000000);
}
};
#endif

@ -0,0 +1,261 @@
/* $Id$
-----------------------------------------------------------------------------
This source file is part of VideoTexture 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.
-----------------------------------------------------------------------------
*/
// implementation
#include <Python.h>
#include <structmember.h>
#include <KX_BlenderCanvas.h>
#include <KX_BlenderRenderTools.h>
#include <RAS_IRasterizer.h>
#include <RAS_OpenGLRasterizer.h>
#include <KX_WorldInfo.h>
#include <KX_Light.h>
#include "ImageRender.h"
#include "ImageBase.h"
#include "BlendType.h"
#include "Exception.h"
// constructor
ImageRender::ImageRender (KX_Scene * scene, KX_Camera * camera) : m_scene(scene),
m_camera(camera)
{
// create screen area
m_area.winrct.xmin = m_upLeft[0];
m_area.winrct.ymin = m_upLeft[1];
m_area.winx = m_size[0];
m_area.winy = m_size[1];
// create canvas
m_canvas = new KX_BlenderCanvas(&m_area);
// create render tools
m_rendertools = new KX_BlenderRenderTools();
// create rasterizer
m_rasterizer = new RAS_OpenGLRasterizer(m_canvas);
m_rasterizer->Init();
// initialize background colour
setBackground(0, 0, 255);
// refresh lights
refreshLights();
}
// destructor
ImageRender::~ImageRender (void)
{
// release allocated objects
delete m_rasterizer;
delete m_rendertools;
delete m_canvas;
}
// set background color
void ImageRender::setBackground (unsigned char red, unsigned char green, unsigned char blue)
{
m_background[0] = red;
m_background[1] = green;
m_background[2] = blue;
m_rasterizer->SetBackColor(m_background[0], m_background[1], m_background[2], 1.0);
}
// capture image from viewport
void ImageRender::calcImage (unsigned int texId)
{
// setup camera
bool cameraPasive = !m_camera->GetViewport();
// render scene
Render();
// reset camera
if (cameraPasive) m_camera->EnableViewport(false);
// get image from viewport
ImageViewport::calcImage(texId);
}
// refresh lights
void ImageRender::refreshLights (void)
{
// clear lights list
//m_rendertools->RemoveAllLights();
// set lights
//for (int idx = 0; idx < scene->GetLightList()->GetCount(); ++idx)
// m_rendertools->AddLight(((KX_LightObject*)(scene->GetLightList()->GetValue(idx)))->GetLightData());
}
// cast Image pointer to ImageRender
inline ImageRender * getImageRender (PyImage * self)
{ return static_cast<ImageRender*>(self->m_image); }
// python methods
// Blender Scene type
BlendType<KX_Scene> sceneType ("KX_Scene");
// Blender Camera type
BlendType<KX_Camera> cameraType ("KX_Camera");
static ExceptionID SceneInvalid, CameraInvalid;
static ExpDesc SceneInvalidDesc (SceneInvalid, "Scene object is invalid");
static ExpDesc CameraInvalidDesc (CameraInvalid, "Camera object is invalid");
// object initialization
static int ImageRender_init (PyObject * pySelf, PyObject * args, PyObject * kwds)
{
// parameters - scene object
PyObject * scene;
// camera object
PyObject * camera;
// parameter keywords
static char *kwlist[] = {"sceneObj", "cameraObj", NULL};
// get parameters
if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist, &scene, &camera))
return -1;
try
{
// get scene pointer
KX_Scene * scenePtr (NULL);
if (scene != NULL) scenePtr = sceneType.checkType(scene);
// throw exception if scene is not available
if (scenePtr == NULL) THRWEXCP(SceneInvalid, S_OK);
// get camera pointer
KX_Camera * cameraPtr (NULL);
if (camera != NULL) cameraPtr = cameraType.checkType(camera);
// throw exception if camera is not available
if (cameraPtr == NULL) THRWEXCP(CameraInvalid, S_OK);
// get pointer to image structure
PyImage * self = reinterpret_cast<PyImage*>(pySelf);
// create source object
if (self->m_image != NULL) delete self->m_image;
self->m_image = new ImageRender(scenePtr, cameraPtr);
}
catch (Exception & exp)
{
exp.report();
return -1;
}
// initialization succeded
return 0;
}
// get background color
PyObject * getBackground (PyImage * self, void * closure)
{
return Py_BuildValue("[BBB]", getImageRender(self)->getBackground()[0],
getImageRender(self)->getBackground()[1], getImageRender(self)->getBackground()[2]);
}
// set color
static int setBackground (PyImage * self, PyObject * value, void * closure)
{
// check validity of parameter
if (value == NULL || !PySequence_Check(value) || PySequence_Length(value) != 3
|| !PyInt_Check(PySequence_Fast_GET_ITEM(value, 0))
|| !PyInt_Check(PySequence_Fast_GET_ITEM(value, 1))
|| !PyInt_Check(PySequence_Fast_GET_ITEM(value, 2)))
{
PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 3 ints");
return -1;
}
// set background color
getImageRender(self)->setBackground((unsigned char)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 0))),
(unsigned char)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 1))),
(unsigned char)(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 2))));
// success
return 0;
}
// methods structure
static PyMethodDef imageRenderMethods[] =
{ // methods from ImageBase class
{"refresh", (PyCFunction)Image_refresh, METH_NOARGS, "Refresh image - invalidate its current content"},
{NULL}
};
// attributes structure
static PyGetSetDef imageRenderGetSets[] =
{
{"background", (getter)getBackground, (setter)setBackground, "background color", NULL},
// attributes from ImageBase class
{"image", (getter)Image_getImage, NULL, "image data", NULL},
{"size", (getter)Image_getSize, NULL, "image size", NULL},
{"scale", (getter)Image_getScale, (setter)Image_setScale, "fast scale of image (near neighbour)", NULL},
{"flip", (getter)Image_getFlip, (setter)Image_setFlip, "flip image vertically", NULL},
{"filter", (getter)Image_getFilter, (setter)Image_setFilter, "pixel filter", NULL},
{NULL}
};
// define python type
PyTypeObject ImageRenderType =
{
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"VideoTexture.ImageRender", /*tp_name*/
sizeof(PyImage), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor)Image_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/
"Image source from render", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
imageRenderMethods, /* tp_methods */
0, /* tp_members */
imageRenderGetSets, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)ImageRender_init, /* tp_init */
0, /* tp_alloc */
Image_allocNew, /* tp_new */
};

@ -0,0 +1,90 @@
/* $Id$
-----------------------------------------------------------------------------
This source file is part of VideoTexture 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 IMAGERENDER_H
#define IMAGERENDER_H
#include "Common.h"
#include <KX_Scene.h>
#include <KX_Camera.h>
#include <DNA_screen_types.h>
#include <RAS_ICanvas.h>
#include <RAS_IRasterizer.h>
#include <RAS_IRenderTools.h>
#include "ImageViewport.h"
/// class for render 3d scene
class ImageRender : public ImageViewport
{
public:
/// constructor
ImageRender (KX_Scene * scene, KX_Camera * camera);
/// destructor
virtual ~ImageRender (void);
/// get background color
unsigned char * getBackground (void) { return m_background; }
/// set background color
void setBackground (unsigned char red, unsigned char green, unsigned char blue);
protected:
/// rendered scene
KX_Scene * m_scene;
/// camera for render
KX_Camera * m_camera;
/// screen area for rendering
ScrArea m_area;
/// rendering device
RAS_ICanvas * m_canvas;
/// rasterizer
RAS_IRasterizer * m_rasterizer;
/// render tools
RAS_IRenderTools * m_rendertools;
/// background colour
unsigned char m_background[3];
/// render 3d scene to image
virtual void calcImage (unsigned int texId);
/// refresh lights
void refreshLights (void);
/// methods from KX_KetsjiEngine
bool BeginFrame();
void EndFrame();
void Render();
void SetupRenderFrame(KX_Scene *scene, KX_Camera* cam);
void RenderFrame(KX_Scene* scene, KX_Camera* cam);
void SetBackGround(KX_WorldInfo* wi);
void SetWorldSettings(KX_WorldInfo* wi);
};
#endif

@ -0,0 +1,298 @@
/* $Id$
-----------------------------------------------------------------------------
This source file is part of VideoTexture 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.
-----------------------------------------------------------------------------
*/
// implementation
#include <Python.h>
#include <structmember.h>
#include "ImageViewport.h"
#include <BIF_gl.h>
#include "Texture.h"
#include "ImageBase.h"
#include "FilterSource.h"
// constructor
ImageViewport::ImageViewport (void) : m_texInit(false)
{
// get viewport rectangle
glGetIntegerv(GL_VIEWPORT, m_viewport);
// create buffer for viewport image
m_viewportImage = new BYTE [3 * getViewportSize()[0] * getViewportSize()[1]];
// set attributes
setWhole(false);
}
// destructor
ImageViewport::~ImageViewport (void)
{ delete m_viewportImage; }
// use whole viewport to capture image
void ImageViewport::setWhole (bool whole)
{
// set whole
m_whole = whole;
// set capture size to viewport size, if whole,
// otherwise place area in the middle of viewport
for (int idx = 0; idx < 2; ++idx)
{
// capture size
m_capSize[idx] = whole ? short(getViewportSize()[idx])
: calcSize(short(getViewportSize()[idx]));
// position
m_position[idx] = whole ? 0 : (getViewportSize()[idx] - m_capSize[idx]) >> 1;
}
// init image
init(m_capSize[0], m_capSize[1]);
// set capture position
setPosition();
}
void ImageViewport::setCaptureSize (short * size)
{
m_whole = false;
if (size == NULL)
size = m_capSize;
for (int idx = 0; idx < 2; ++idx)
{
if (size[idx] < 1)
m_capSize[idx] = 1;
else if (size[idx] > getViewportSize()[idx])
m_capSize[idx] = getViewportSize()[idx];
else
m_capSize[idx] = size[idx];
}
init(m_capSize[0], m_capSize[1]);
// set capture position
setPosition();
}
// set position of capture rectangle
void ImageViewport::setPosition (int * pos)
{
// if new position is not provided, use existing position
if (pos == NULL) pos = m_position;
// save position
for (int idx = 0; idx < 2; ++idx)
m_position[idx] = pos[idx] < 0 ? 0 : pos[idx] >= getViewportSize()[idx]
- m_capSize[idx] ? getViewportSize()[idx] - m_capSize[idx] : pos[idx];
// recalc up left corner
for (int idx = 0; idx < 2; ++idx)
m_upLeft[idx] = m_position[idx] + m_viewport[idx];
}
// capture image from viewport
void ImageViewport::calcImage (unsigned int texId)
{
// if scale was changed
if (m_scaleChange)
// reset image
init(m_capSize[0], m_capSize[1]);
// if texture wasn't initialized
if (!m_texInit)
{
// initialize it
loadTexture(texId, m_image, m_size);
m_texInit = true;
}
// if texture can be directly created
if (texId != 0 && m_pyfilter == NULL && m_capSize[0] == calcSize(m_capSize[0])
&& m_capSize[1] == calcSize(m_capSize[1]) && !m_flip)
{
// just copy current viewport to texture
glBindTexture(GL_TEXTURE_2D, texId);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_upLeft[0], m_upLeft[1], m_capSize[0], m_capSize[1]);
// image is not available
m_avail = false;
}
// otherwise copy viewport to buffer, if image is not available
else if (!m_avail)
{
// get frame buffer data
glReadPixels(m_upLeft[0], m_upLeft[1], m_capSize[0], m_capSize[1], GL_RGB,
GL_UNSIGNED_BYTE, m_viewportImage);
// filter loaded data
FilterBGR24 filt;
filterImage(filt, m_viewportImage, m_capSize);
}
}
// cast Image pointer to ImageViewport
inline ImageViewport * getImageViewport (PyImage * self)
{ return static_cast<ImageViewport*>(self->m_image); }
// python methods
// get whole
static PyObject * ImageViewport_getWhole (PyImage * self, void * closure)
{
if (self->m_image != NULL && getImageViewport(self)->getWhole()) Py_RETURN_TRUE;
else Py_RETURN_FALSE;
}
// set whole
static int ImageViewport_setWhole (PyImage * self, PyObject * value, void * closure)
{
// check parameter, report failure
if (value == NULL || !PyBool_Check(value))
{
PyErr_SetString(PyExc_TypeError, "The value must be a bool");
return -1;
}
// set whole
if (self->m_image != NULL) getImageViewport(self)->setWhole(value == Py_True);
// success
return 0;
}
// get position
static PyObject * ImageViewport_getPosition (PyImage * self, void * closure)
{
return Py_BuildValue("(ii)", getImageViewport(self)->getPosition()[0],
getImageViewport(self)->getPosition()[1]);
}
// set position
static int ImageViewport_setPosition (PyImage * self, PyObject * value, void * closure)
{
// check validity of parameter
if (value == NULL || !PySequence_Check(value) || PySequence_Length(value) != 2
|| !PyInt_Check(PySequence_Fast_GET_ITEM(value, 0))
|| !PyInt_Check(PySequence_Fast_GET_ITEM(value, 1)))
{
PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 2 ints");
return -1;
}
// set position
int pos [] = {
int(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 0))),
int(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 1)))
};
getImageViewport(self)->setPosition(pos);
// success
return 0;
}
// get capture size
static PyObject * ImageViewport_getCaptureSize (PyImage * self, void * closure)
{
return Py_BuildValue("(ii)", getImageViewport(self)->getCaptureSize()[0],
getImageViewport(self)->getCaptureSize()[1]);
}
// set capture size
static int ImageViewport_setCaptureSize (PyImage * self, PyObject * value, void * closure)
{
// check validity of parameter
if (value == NULL || !PySequence_Check(value) || PySequence_Length(value) != 2
|| !PyInt_Check(PySequence_Fast_GET_ITEM(value, 0))
|| !PyInt_Check(PySequence_Fast_GET_ITEM(value, 1)))
{
PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 2 ints");
return -1;
}
// set capture size
short size [] = {
short(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 0))),
short(PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 1)))
};
getImageViewport(self)->setCaptureSize(size);
// success
return 0;
}
// methods structure
static PyMethodDef imageViewportMethods[] =
{ // methods from ImageBase class
{"refresh", (PyCFunction)Image_refresh, METH_NOARGS, "Refresh image - invalidate its current content"},
{NULL}
};
// attributes structure
static PyGetSetDef imageViewportGetSets[] =
{
{"whole", (getter)ImageViewport_getWhole, (setter)ImageViewport_setWhole, "use whole viewport to capture", NULL},
{"position", (getter)ImageViewport_getPosition, (setter)ImageViewport_setPosition, "upper left corner of captured area", NULL},
{"capsize", (getter)ImageViewport_getCaptureSize, (setter)ImageViewport_setCaptureSize, "size of viewport area being captured", NULL},
// attributes from ImageBase class
{"image", (getter)Image_getImage, NULL, "image data", NULL},
{"size", (getter)Image_getSize, NULL, "image size", NULL},
{"scale", (getter)Image_getScale, (setter)Image_setScale, "fast scale of image (near neighbour)", NULL},
{"flip", (getter)Image_getFlip, (setter)Image_setFlip, "flip image vertically", NULL},
{"filter", (getter)Image_getFilter, (setter)Image_setFilter, "pixel filter", NULL},
{NULL}
};
// define python type
PyTypeObject ImageViewportType =
{
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"VideoTexture.ImageViewport", /*tp_name*/
sizeof(PyImage), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor)Image_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/
"Image source from viewport", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
imageViewportMethods, /* tp_methods */
0, /* tp_members */
imageViewportGetSets, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)Image_init<ImageViewport>, /* tp_init */
0, /* tp_alloc */
Image_allocNew, /* tp_new */
};

@ -0,0 +1,84 @@
/* $Id$
-----------------------------------------------------------------------------
This source file is part of VideoTexture 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 IMAGEVIEWPORT_H
#define IMAGEVIEWPORT_H
#include "Common.h"
#include "ImageBase.h"
/// class for viewport access
class ImageViewport : public ImageBase
{
public:
/// constructor
ImageViewport (void);
/// destructor
virtual ~ImageViewport (void);
/// is whole buffer used
bool getWhole (void) { return m_whole; }
/// set whole buffer use
void setWhole (bool whole);
/// get capture size in viewport
short * getCaptureSize (void) { return m_capSize; }
/// set capture size in viewport
void setCaptureSize (short * size = NULL);
/// get position in viewport
int * getPosition (void) { return m_position; }
/// set position in viewport
void setPosition (int * pos = NULL);
protected:
/// frame buffer rectangle
int m_viewport[4];
/// size of captured area
short m_capSize[2];
/// use whole viewport
bool m_whole;
/// position of capture rectangle in viewport
int m_position[2];
/// upper left point for capturing
int m_upLeft[2];
/// buffer to copy viewport
BYTE * m_viewportImage;
/// texture is initialized
bool m_texInit;
/// capture image from viewport
virtual void calcImage (unsigned int texId);
/// get viewport size
int * getViewportSize (void) { return m_viewport + 2; }
};
#endif

@ -0,0 +1,65 @@
#
# $Id$
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU 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 General Public License for more details.
#
# You should have received a copy of the GNU 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.
#
# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
# All rights reserved.
#
# The Original Code is: all of this file.
#
# Contributor(s): none yet.
#
# ***** END GPL LICENSE BLOCK *****
#
#
LIBNAME = videotex
DIR = $(OCGDIR)/gameengine/$(LIBNAME)
SOURCEDIR = source/gameengine/VideoTexture
include nan_compile.mk
CCFLAGS += $(LEVEL_1_CPP_WARNINGS)
CPPFLAGS += $(OGL_CPPFLAGS)
CPPFLAGS += -I$(NAN_GLEW)/include
CPPFLAGS += -I$(OPENGL_HEADERS)
CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
CPPFLAGS += -I../../blender/python
CPPFLAGS += -I$(NAN_STRING)/include
CPPFLAGS += -I$(NAN_SOUNDSYSTEM)/include
CPPFLAGS += -I$(NAN_MOTO)/include
CPPFLAGS += -I../Rasterizer/RAS_OpenGLRasterizer
CPPFLAGS += -I../Rasterizer -I../GameLogic -I../SceneGraph
CPPFLAGS += -I../BlenderRoutines -I../Expressions -I../Ketsji
CPPFLAGS += -I../../kernel/gen_system
CPPFLAGS += -I.
CPPFLAGS += -I../../blender/blenkernel
CPPFLAGS += -I../../blender/blenlib
CPPFLAGS += -I../../blender/include
CPPFLAGS += -I../../blender/makesdna
CPPFLAGS += -I../../blender/imbuf
CPPFLAGS += -I../../blender/gpu
CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
ifeq ($(WITH_FFMPEG),true)
CPPFLAGS += -DWITH_FFMPEG
CPPFLAGS += $(NAN_FFMPEGCFLAGS)
endif

@ -0,0 +1,83 @@
/* $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.
-----------------------------------------------------------------------------
*/
#include "PyTypeList.h"
#include <memory>
#include <vector>
#include <Python.h>
/// check, if type is in list
bool PyTypeList::in (PyTypeObject * type)
{
// if list exists
if (m_list.get() != NULL)
// iterate items in list
for (PyTypeListType::iterator it = m_list->begin(); it != m_list->end(); ++it)
// if item is found, return with success
if ((*it)->getType() == type) return true;
// otherwise return not found
return false;
}
/// add type to list
void PyTypeList::add (PyTypeObject * type, const char * name)
{
PyTypeListItem * typeItem;
// if list doesn't exist, create it
if (m_list.get() == NULL)
m_list.reset(new PyTypeListType());
if (!in(type))
// add new item to list
m_list->push_back(new PyTypeListItem(type, name));
}
/// prepare types
bool PyTypeList::ready (void)
{
// if list exists
if (m_list.get() != NULL)
// iterate items in list
for (PyTypeListType::iterator it = m_list->begin(); it != m_list->end(); ++it)
// if preparation failed, report it
if (PyType_Ready((*it)->getType()) < 0) return false;
// success
return true;
}
/// register types to module
void PyTypeList::reg (PyObject * module)
{
// if list exists
if (m_list.get() != NULL)
// iterate items in list
for (PyTypeListType::iterator it = m_list->begin(); it != m_list->end(); ++it)
{
// increase ref count
Py_INCREF((*it)->getType());
// add type to module
PyModule_AddObject(module, (*it)->getName(), (PyObject*)(*it)->getType());
}
}

@ -0,0 +1,85 @@
/* $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 PYTYPELIST_H
#define PYTYPELIST_H
#include "Common.h"
#include <memory>
#include <vector>
#include <Python.h>
// forward declaration
class PyTypeListItem;
// type for list of types
typedef std::vector<PyTypeListItem*> PyTypeListType;
/// class to store list of python types
class PyTypeList
{
public:
/// check, if type is in list
bool in (PyTypeObject * type);
/// add type to list
void add (PyTypeObject * type, const char * name);
/// prepare types
bool ready (void);
/// register types to module
void reg (PyObject * module);
protected:
/// pointer to list of types
std::auto_ptr<PyTypeListType> m_list;
};
/// class for item of python type list
class PyTypeListItem
{
public:
/// constructor adds type into list
PyTypeListItem (PyTypeObject * type, const char * name)
: m_type(type), m_name(name)
{ }
/// does type match
PyTypeObject * getType (void) { return m_type; }
/// get name of type
const char * getName (void) { return m_name; }
protected:
/// pointer to type object
PyTypeObject * m_type;
/// name of type
const char * m_name;
};
#endif

@ -0,0 +1,32 @@
#!/usr/bin/python
import sys
Import ('env')
sources = env.Glob('*.cpp')
incs = '. #source/gameengine/Ketsji #source/gameengine/Expressions'
incs += ' #source/gameengine/GameLogic #source/gameengine/SceneGraph #source/gameengine/Rasterizer'
incs += ' #source/gameengine/Rasterizer/RAS_OpenGLRasterizer'
incs += ' #source/gameengine/BlenderRoutines'
incs += ' #source/blender/include #source/blender/blenlib #source/blender/blenkernel'
incs += ' #source/blender/makesdna #source/blender/imbuf #source/blender/python'
incs += ' #source/blender/gpu #source/kernel/gen_system #intern/string #intern/moto/include'
incs += ' #intern/guardedalloc #intern/SoundSystem'
incs += ' #extern/glew/include'
cflags = []
defs = ''
if env['OURPLATFORM'] == 'win32-vc':
cflags.append('/GR')
cflags.append('/Ox')
defs += ' __STDC_CONSTANT_MACROS'
incs += ' ' + env['BF_PYTHON_INC']
#incs += ' ' + env['BF_OPENGL_INC']
if env['WITH_BF_FFMPEG']:
defs += ' WITH_FFMPEG'
incs += ' ' + env['BF_FFMPEG_INC']
env.BlenderLib ( 'bf_videotex', sources, Split(incs), Split(defs), libtype=['game','player'], priority=[25, 72], compileflags = cflags )

@ -0,0 +1,463 @@
/* $Id$
-----------------------------------------------------------------------------
This source file is part of VideoTexture 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.
-----------------------------------------------------------------------------
*/
// implementation
#include <Python.h>
#include <structmember.h>
#include <KX_GameObject.h>
#include <RAS_MeshObject.h>
#include <DNA_mesh_types.h>
#include <DNA_meshdata_types.h>
#include <DNA_image_types.h>
#include <IMB_imbuf_types.h>
#include <BDR_drawmesh.h>
#include <KX_PolygonMaterial.h>
#include <MEM_guardedalloc.h>
#include <KX_BlenderMaterial.h>
#include <BL_Texture.h>
#include "KX_KetsjiEngine.h"
#include "KX_PythonInit.h"
#include "Texture.h"
#include "ImageBase.h"
#include "Exception.h"
#include <memory.h>
#include <BIF_gl.h>
// macro for exception handling and logging
#define CATCH_EXCP catch (Exception & exp) \
{ exp.report(); }
// are Blender materials used
bool blendMats = false;
// Blender GameObject type
BlendType<KX_GameObject> gameObjectType ("KX_GameObject");
// load texture
void loadTexture (unsigned int texId, unsigned int * texture, short * size,
bool mipmap)
{
// load texture for rendering
glBindTexture(GL_TEXTURE_2D, texId);
if (mipmap)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, size[0], size[1], GL_RGBA, GL_UNSIGNED_BYTE, texture);
}
else
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, size[0], size[1], 0, GL_RGBA, GL_UNSIGNED_BYTE, texture);
}
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}
// get pointer to material
RAS_IPolyMaterial * getMaterial (PyObject *obj, short matID)
{
// if object is available
if (obj != NULL)
{
// get pointer to texture image
KX_GameObject * gameObj = gameObjectType.checkType(obj);
if (gameObj != NULL && gameObj->GetMeshCount() > 0)
{
// get material from mesh
RAS_MeshObject * mesh = gameObj->GetMesh(0);
RAS_MeshMaterial *meshMat = mesh->GetMeshMaterial(matID);
if (meshMat->m_bucket != NULL)
// return pointer to polygon or blender material
return meshMat->m_bucket->GetPolyMaterial();
}
}
// otherwise material was not found
return NULL;
}
// get material ID
short getMaterialID (PyObject * obj, char * name)
{
// search for material
for (short matID = 0;; ++matID)
{
// get material
RAS_IPolyMaterial * mat = getMaterial(obj, matID);
// if material is not available, report that no material was found
if (mat == NULL) break;
// if material name matches
if (strcmp(mat->GetMaterialName().ReadPtr(), name) == 0)
// matID is found
return matID;
}
// material was not found
return -1;
}
// Texture object allocation
PyObject * Texture_new (PyTypeObject *type, PyObject *args, PyObject *kwds)
{
// allocate object
Texture * self = reinterpret_cast<Texture*>(type->tp_alloc(type, 0));
// initialize object structure
self->m_actTex = 0;
self->m_orgSaved = false;
self->m_imgTexture = NULL;
self->m_matTexture = NULL;
self->m_mipmap = false;
self->m_scaledImg = NULL;
self->m_scaledImgSize = 0;
self->m_source = NULL;
self->m_lastClock = 0.0;
// return allocated object
return reinterpret_cast<PyObject*>(self);
}
// forward declaration
PyObject * Texture_close(Texture * self);
int Texture_setSource (Texture * self, PyObject * value, void * closure);
// Texture object deallocation
void Texture_dealloc (Texture * self)
{
// release renderer
Py_XDECREF(self->m_source);
// close texture
Texture_close(self);
// release scaled image buffer
delete [] self->m_scaledImg;
// release object
self->ob_type->tp_free((PyObject*)self);
}
static ExceptionID MaterialNotAvail;
static ExpDesc MaterialNotAvailDesc (MaterialNotAvail, "Texture material is not available");
// Texture object initialization
int Texture_init (Texture *self, PyObject *args, PyObject *kwds)
{
// parameters - game object with video texture
PyObject * obj = NULL;
// material ID
short matID = 0;
// texture ID
short texID = 0;
// texture object with shared texture ID
Texture * texObj = NULL;
static char *kwlist[] = {"gameObj", "materialID", "textureID", "textureObj", NULL};
// get parameters
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|hhO!", kwlist, &obj, &matID,
&texID, &TextureType, &texObj))
return -1;
// if parameters are available
if (obj != NULL)
{
// process polygon material or blender material
try
{
// get pointer to texture image
RAS_IPolyMaterial * mat = getMaterial(obj, matID);
if (mat != NULL)
{
// is it blender material or polygon material
blendMats = (mat->GetFlag() & RAS_BLENDERMAT) != 0;
if (blendMats)
// get blender material texture
self->m_matTexture = static_cast<KX_BlenderMaterial*>(mat)->getTex(texID);
else
{
// get texture pointer from polygon material
MTFace * tface = static_cast<KX_PolygonMaterial*>(mat)->GetMTFace();
self->m_imgTexture = (Image*)tface->tpage;
}
}
// check if texture is available, if not, initialization failed
if (self->m_imgTexture == NULL && self->m_matTexture == NULL)
// throw exception if initialization failed
THRWEXCP(MaterialNotAvail, S_OK);
// if texture object is provided
if (texObj != NULL)
{
// copy texture code
self->m_actTex = texObj->m_actTex;
self->m_mipmap = texObj->m_mipmap;
if (texObj->m_source != NULL)
Texture_setSource(self, reinterpret_cast<PyObject*>(texObj->m_source), NULL);
}
else
// otherwise generate texture code
glGenTextures(1, (GLuint*)&self->m_actTex);
}
catch (Exception & exp)
{
exp.report();
return -1;
}
}
// initialization succeded
return 0;
}
// close added texture
PyObject * Texture_close(Texture * self)
{
// restore texture
if (self->m_orgSaved)
{
self->m_orgSaved = false;
// restore original texture code
if (blendMats)
self->m_matTexture->swapTexture(self->m_orgTex);
else
self->m_imgTexture->bindcode = self->m_orgTex;
// drop actual texture
if (self->m_actTex != 0)
{
glDeleteTextures(1, (GLuint *)&self->m_actTex);
self->m_actTex = 0;
}
}
Py_RETURN_NONE;
}
// refresh texture
PyObject * Texture_refresh (Texture * self, PyObject * args)
{
// get parameter - refresh source
PyObject * param;
if (!PyArg_ParseTuple(args, "O", &param) || !PyBool_Check(param))
{
// report error
PyErr_SetString(PyExc_TypeError, "The value must be a bool");
return NULL;
}
// some trick here: we are in the business of loading a texture,
// no use to do it if we are still in the same rendering frame.
// We find this out by looking at the engine current clock time
KX_KetsjiEngine* engine = KX_GetActiveEngine();
if (engine->GetClockTime() != self->m_lastClock)
{
self->m_lastClock = engine->GetClockTime();
// set source refresh
bool refreshSource = (param == Py_True);
// try to proces texture from source
try
{
// if source is available
if (self->m_source != NULL)
{
// check texture code
if (!self->m_orgSaved)
{
self->m_orgSaved = true;
// save original image code
if (blendMats)
self->m_orgTex = self->m_matTexture->swapTexture(self->m_actTex);
else
{
self->m_orgTex = self->m_imgTexture->bindcode;
self->m_imgTexture->bindcode = self->m_actTex;
}
}
// get texture
unsigned int * texture = self->m_source->m_image->getImage(self->m_actTex);
// if texture is available
if (texture != NULL)
{
// get texture size
short * orgSize = self->m_source->m_image->getSize();
// calc scaled sizes
short size[] = {ImageBase::calcSize(orgSize[0]), ImageBase::calcSize(orgSize[1])};
// scale texture if needed
if (size[0] != orgSize[0] || size[1] != orgSize[1])
{
// if scaled image buffer is smaller than needed
if (self->m_scaledImgSize < (unsigned int)(size[0] * size[1]))
{
// new size
self->m_scaledImgSize = size[0] * size[1];
// allocate scaling image
delete [] self->m_scaledImg;
self->m_scaledImg = new unsigned int[self->m_scaledImgSize];
}
// scale texture
gluScaleImage(GL_RGBA, orgSize[0], orgSize[1], GL_UNSIGNED_BYTE, texture,
size[0], size[1], GL_UNSIGNED_BYTE, self->m_scaledImg);
// use scaled image instead original
texture = self->m_scaledImg;
}
// load texture for rendering
loadTexture (self->m_actTex, texture, size, self->m_mipmap);
// refresh texture source, if required
if (refreshSource) self->m_source->m_image->refresh();
}
}
}
CATCH_EXCP;
}
Py_RETURN_NONE;
}
// get mipmap value
PyObject * Texture_getMipmap (Texture * self, void * closure)
{
// return true if flag is set, otherwise false
if (self->m_mipmap) Py_RETURN_TRUE;
else Py_RETURN_FALSE;
}
// set mipmap value
int Texture_setMipmap (Texture * self, PyObject * value, void * closure)
{
// check parameter, report failure
if (value == NULL || !PyBool_Check(value))
{
PyErr_SetString(PyExc_TypeError, "The value must be a bool");
return -1;
}
// set mipmap
self->m_mipmap = value == Py_True;
// success
return 0;
}
// get source object
PyObject * Texture_getSource (Texture * self, PyObject * value, void * closure)
{
// if source exists
if (self->m_source != NULL)
{
Py_INCREF(self->m_source);
return reinterpret_cast<PyObject*>(self->m_source);
}
// otherwise return None
Py_RETURN_NONE;
}
// set source object
int Texture_setSource (Texture * self, PyObject * value, void * closure)
{
// check new value
if (value == NULL || !pyImageTypes.in(value->ob_type))
{
// report value error
PyErr_SetString(PyExc_TypeError, "Invalid type of value");
return -1;
}
// increase ref count for new value
Py_INCREF(value);
// release previous
Py_XDECREF(self->m_source);
// set new value
self->m_source = reinterpret_cast<PyImage*>(value);
// return success
return 0;
}
// class Texture methods
static PyMethodDef textureMethods[] =
{
{ "close", (PyCFunction)Texture_close, METH_NOARGS, "Close dynamic texture and restore original"},
{ "refresh", (PyCFunction)Texture_refresh, METH_VARARGS, "Refresh texture from source"},
{NULL} /* Sentinel */
};
// class Texture attributes
static PyGetSetDef textureGetSets[] =
{
{"source", (getter)Texture_getSource, (setter)Texture_setSource, "source of texture", NULL},
{"mipmap", (getter)Texture_getMipmap, (setter)Texture_setMipmap, "mipmap texture", NULL},
{NULL}
};
// class Texture declaration
PyTypeObject TextureType =
{
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"VideoTexture.Texture", /*tp_name*/
sizeof(Texture), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor)Texture_dealloc,/*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/
"Texture objects", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
textureMethods, /* tp_methods */
0, /* tp_members */
textureGetSets, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)Texture_init, /* tp_init */
0, /* tp_alloc */
Texture_new, /* tp_new */
};

@ -0,0 +1,87 @@
/* $Id$
-----------------------------------------------------------------------------
This source file is part of VideoTexture library
Copyright (c) 2006 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 TEXTURE_H
#define TEXTURE_H
#include <Python.h>
#include <structmember.h>
#include <DNA_image_types.h>
#include <BL_Texture.h>
#include <KX_BlenderMaterial.h>
#include "ImageBase.h"
#include "BlendType.h"
// type Texture declaration
struct Texture
{
PyObject_HEAD
// video texture bind code
unsigned int m_actTex;
// original texture bind code
unsigned int m_orgTex;
// original texture saved
bool m_orgSaved;
// texture image for game materials
Image * m_imgTexture;
// texture for blender materials
BL_Texture * m_matTexture;
// use mipmapping
bool m_mipmap;
// scaled image buffer
unsigned int * m_scaledImg;
// scaled image buffer size
unsigned int m_scaledImgSize;
// last refresh
double m_lastClock;
// image source
PyImage * m_source;
};
// Texture type description
extern PyTypeObject TextureType;
// usage of Blender materials
extern bool blendMats;
// load texture
void loadTexture (unsigned int texId, unsigned int * texture, short * size,
bool mipmap = false);
// get material
RAS_IPolyMaterial * getMaterial (PyObject *obj, short matID);
// get material ID
short getMaterialID (PyObject * obj, char * name);
#endif

@ -0,0 +1,183 @@
/* $Id$
-----------------------------------------------------------------------------
This source file is part of VideoTexture 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 WIN32
#define WINDOWS_LEAN_AND_MEAN
#include <Windows.h>
#endif
#include "VideoBase.h"
#include "FilterSource.h"
// VideoBase implementation
// initialize image data
void VideoBase::init(short width, short height)
{
// save original sizes
m_orgSize[0] = width;
m_orgSize[1] = height;
// call base class initialization
ImageBase::init(width, height);
}
// process video frame
void VideoBase::process (BYTE * sample)
{
// if scale was changed
if (m_scaleChange)
// reset image
init(m_orgSize[0], m_orgSize[1]);
// if image is allocated and is able to store new image
if (m_image != NULL && !m_avail)
{
// filters used
FilterRGB24 filtRGB;
FilterYV12 filtYUV;
// convert video format to image
switch (m_format)
{
case RGB24:
// use filter object for format to convert image
filterImage(filtRGB, sample, m_orgSize);
// finish
break;
case YV12:
// use filter object for format to convert image
filtYUV.setBuffs(sample, m_orgSize);
filterImage(filtYUV, sample, m_orgSize);
// finish
break;
}
}
}
// python functions
// exceptions for video source initialization
ExceptionID SourceVideoEmpty, SourceVideoCreation;
ExpDesc SourceVideoEmptyDesc (SourceVideoEmpty, "Source Video is empty");
ExpDesc SourceVideoCreationDesc (SourceVideoCreation, "SourceVideo object was not created");
// open video source
void Video_open (VideoBase * self, char * file, short captureID)
{
// if file is empty, throw exception
if (file == NULL) THRWEXCP(SourceVideoEmpty, S_OK);
// open video file or capture device
if (captureID >= 0)
self->openCam(file, captureID);
else
self->openFile(file);
}
// play video
PyObject * Video_play (PyImage * self)
{ if (getVideo(self)->play()) Py_RETURN_TRUE; else Py_RETURN_FALSE; }
// stop video
PyObject * Video_stop (PyImage * self)
{ if (getVideo(self)->stop()) Py_RETURN_TRUE; else Py_RETURN_FALSE; }
// get status
PyObject * Video_getStatus (PyImage * self, void * closure)
{
return Py_BuildValue("h", getVideo(self)->getStatus());
}
// refresh video
PyObject * Video_refresh (PyImage * self)
{
getVideo(self)->refresh();
return Video_getStatus(self, NULL);
}
// get range
PyObject * Video_getRange (PyImage * self, void * closure)
{
return Py_BuildValue("[ff]", getVideo(self)->getRange()[0],
getVideo(self)->getRange()[1]);
}
// set range
int Video_setRange (PyImage * self, PyObject * value, void * closure)
{
// check validity of parameter
if (value == NULL || !PySequence_Check(value) || PySequence_Length(value) != 2
|| !PyFloat_Check(PySequence_Fast_GET_ITEM(value, 0))
|| !PyFloat_Check(PySequence_Fast_GET_ITEM(value, 1)))
{
PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 2 longs");
return -1;
}
// set range
getVideo(self)->setRange(PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 0)),
PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 1)));
// success
return 0;
}
// get repeat
PyObject * Video_getRepeat (PyImage * self, void * closure)
{ return Py_BuildValue("h", getVideo(self)->getRepeat()); }
// set repeat
int Video_setRepeat (PyImage * self, PyObject * value, void * closure)
{
// check validity of parameter
if (value == NULL || !PyInt_Check(value))
{
PyErr_SetString(PyExc_TypeError, "The value must be an int");
return -1;
}
// set repeat
getVideo(self)->setRepeat(int(PyInt_AsLong(value)));
// success
return 0;
}
// get frame rate
PyObject * Video_getFrameRate (PyImage * self, void * closure)
{ return Py_BuildValue("f", double(getVideo(self)->getFrameRate())); }
// set frame rate
int Video_setFrameRate (PyImage * self, PyObject * value, void * closure)
{
// check validity of parameter
if (value == NULL || !PyFloat_Check(value))
{
PyErr_SetString(PyExc_TypeError, "The value must be a float");
return -1;
}
// set repeat
getVideo(self)->setFrameRate(float(PyFloat_AsDouble(value)));
// success
return 0;
}

@ -0,0 +1,185 @@
/* $Id$
-----------------------------------------------------------------------------
This source file is part of VideoTexture 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 VIDEOBASE_H
#define VIDEOBASE_H
#include <Python.h>
#include "ImageBase.h"
#include "Exception.h"
// source states
const int SourceError = -1;
const int SourceEmpty = 0;
const int SourceReady = 1;
const int SourcePlaying = 2;
const int SourceStopped = 3;
// video source formats
enum VideoFormat { None, RGB24, YV12 };
/// base class for video source
class VideoBase : public ImageBase
{
public:
/// constructor
VideoBase (void) : ImageBase(true), m_format(None), m_status(SourceEmpty),
m_repeat(0), m_frameRate(1.0)
{
m_orgSize[0] = m_orgSize[1] = 0;
m_range[0] = m_range[1] = 0.0;
}
/// destructor
virtual ~VideoBase (void) {}
/// open video file
virtual void openFile (char * file)
{
m_isFile = true;
m_status = SourceReady;
}
/// open video capture device
virtual void openCam (char * file, short camIdx)
{
m_isFile = false;
m_status = SourceReady;
}
/// play video
virtual bool play (void)
{
if (m_status == SourceReady || m_status == SourceStopped)
{
m_status = SourcePlaying;
return true;
}
return false;
}
/// stop/pause video
virtual bool stop (void)
{
if (m_status == SourcePlaying)
{
m_status = SourceStopped;
return true;
}
return false;
}
// get video status
int getStatus (void) { return m_status; }
/// get play range
const double * getRange (void) { return m_range; }
/// set play range
virtual void setRange (double start, double stop)
{
if (m_isFile)
{
m_range[0] = start;
m_range[1] = stop;
}
}
// get video repeat
int getRepeat (void) { return m_repeat; }
/// set video repeat
virtual void setRepeat (int rep)
{ if (m_isFile) m_repeat = rep; }
/// get frame rate
float getFrameRate (void) { return m_frameRate; }
/// set frame rate
virtual void setFrameRate (float rate)
{ if (m_isFile) m_frameRate = rate > 0.0 ? rate : 1.0f; }
protected:
/// video format
VideoFormat m_format;
/// original video size
short m_orgSize[2];
/// video status
int m_status;
/// is source file
bool m_isFile;
/// replay range
double m_range[2];
/// repeat count
int m_repeat;
/// frame rate
float m_frameRate;
/// initialize image data
void init (short width, short height);
/// process source data
void process (BYTE * sample);
};
// python fuctions
// cast Image pointer to Video
inline VideoBase * getVideo (PyImage * self)
{ return static_cast<VideoBase*>(self->m_image); }
extern ExceptionID SourceVideoCreation;
// object initialization
template <class T> void Video_init (PyImage * self)
{
// create source video object
if (self->m_image != NULL) delete self->m_image;
HRESULT hRslt = S_OK;
self->m_image = new T(&hRslt);
CHCKHRSLT(hRslt, SourceVideoCreation);
}
// video functions
void Video_open (VideoBase * self, char * file, short captureID);
PyObject * Video_play (PyImage * self);
PyObject * Video_stop (PyImage * self);
PyObject * Video_refresh (PyImage * self);
PyObject * Video_getStatus (PyImage * self, void * closure);
PyObject * Video_getRange (PyImage * self, void * closure);
int Video_setRange (PyImage * self, PyObject * value, void * closure);
PyObject * Video_getRepeat (PyImage * self, void * closure);
int Video_setRepeat (PyImage * self, PyObject * value, void * closure);
PyObject * Video_getFrameRate (PyImage * self, void * closure);
int Video_setFrameRate (PyImage * self, PyObject * value, void * closure);
#endif

@ -0,0 +1,747 @@
/* $Id$
-----------------------------------------------------------------------------
This source file is part of VideoTexture 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.
-----------------------------------------------------------------------------
*/
#include "MEM_guardedalloc.h"
#include "PIL_time.h"
#include <string>
#include "Exception.h"
#include "VideoFFmpeg.h"
#ifdef WITH_FFMPEG
// default framerate
const double defFrameRate = 25.0;
// time scale constant
const long timeScale = 1000;
// macro for exception handling and logging
#define CATCH_EXCP catch (Exception & exp) \
{ exp.report(); m_status = SourceError; }
extern "C" void do_init_ffmpeg();
// class RenderVideo
// constructor
VideoFFmpeg::VideoFFmpeg (HRESULT * hRslt) : VideoBase(),
m_codec(NULL), m_formatCtx(NULL), m_codecCtx(NULL),
m_frame(NULL), m_frameDeinterlaced(NULL), m_frameBGR(NULL), m_imgConvertCtx(NULL),
m_deinterlace(false), m_preseek(0), m_videoStream(-1), m_baseFrameRate(25.0),
m_lastFrame(-1), m_curPosition(-1), m_startTime(0),
m_captWidth(0), m_captHeight(0), m_captRate(0.f)
{
// set video format
m_format = RGB24;
// force flip because ffmpeg always return the image in the wrong orientation for texture
setFlip(true);
// construction is OK
*hRslt = S_OK;
}
// destructor
VideoFFmpeg::~VideoFFmpeg ()
{
}
// release components
bool VideoFFmpeg::release()
{
// release
if (m_codecCtx)
{
avcodec_close(m_codecCtx);
}
if (m_formatCtx)
{
av_close_input_file(m_formatCtx);
}
if (m_frame)
{
av_free(m_frame);
}
if (m_frameDeinterlaced)
{
MEM_freeN(m_frameDeinterlaced->data[0]);
av_free(m_frameDeinterlaced);
}
if (m_frameBGR)
{
MEM_freeN(m_frameBGR->data[0]);
av_free(m_frameBGR);
}
if (m_imgConvertCtx)
{
sws_freeContext(m_imgConvertCtx);
}
m_codec = NULL;
m_codecCtx = NULL;
m_formatCtx = NULL;
m_frame = NULL;
m_frame = NULL;
m_frameBGR = NULL;
m_imgConvertCtx = NULL;
// object will be deleted after that
return true;
}
// set initial parameters
void VideoFFmpeg::initParams (short width, short height, float rate)
{
m_captWidth = width;
m_captHeight = height;
m_captRate = rate;
}
int VideoFFmpeg::openStream(const char *filename, AVInputFormat *inputFormat, AVFormatParameters *formatParams)
{
AVFormatContext *formatCtx;
int i, videoStream;
AVCodec *codec;
AVCodecContext *codecCtx;
if(av_open_input_file(&formatCtx, filename, inputFormat, 0, formatParams)!=0)
return -1;
if(av_find_stream_info(formatCtx)<0)
{
av_close_input_file(formatCtx);
return -1;
}
/* Find the first video stream */
videoStream=-1;
for(i=0; i<formatCtx->nb_streams; i++)
{
if(formatCtx->streams[i] &&
get_codec_from_stream(formatCtx->streams[i]) &&
(get_codec_from_stream(formatCtx->streams[i])->codec_type==CODEC_TYPE_VIDEO))
{
videoStream=i;
break;
}
}
if(videoStream==-1)
{
av_close_input_file(formatCtx);
return -1;
}
codecCtx = get_codec_from_stream(formatCtx->streams[videoStream]);
/* Find the decoder for the video stream */
codec=avcodec_find_decoder(codecCtx->codec_id);
if(codec==NULL)
{
av_close_input_file(formatCtx);
return -1;
}
codecCtx->workaround_bugs = 1;
if(avcodec_open(codecCtx, codec)<0)
{
av_close_input_file(formatCtx);
return -1;
}
#ifdef FFMPEG_OLD_FRAME_RATE
if(codecCtx->frame_rate>1000 && codecCtx->frame_rate_base==1)
codecCtx->frame_rate_base=1000;
m_baseFrameRate = (double)codecCtx->frame_rate / (double)codecCtx->frame_rate_base;
#else
m_baseFrameRate = av_q2d(formatCtx->streams[videoStream]->r_frame_rate);
#endif
if (m_baseFrameRate <= 0.0)
m_baseFrameRate = defFrameRate;
m_codec = codec;
m_codecCtx = codecCtx;
m_formatCtx = formatCtx;
m_videoStream = videoStream;
m_frame = avcodec_alloc_frame();
m_frameDeinterlaced = avcodec_alloc_frame();
m_frameBGR = avcodec_alloc_frame();
// allocate buffer if deinterlacing is required
avpicture_fill((AVPicture*)m_frameDeinterlaced,
(uint8_t*)MEM_callocN(avpicture_get_size(
m_codecCtx->pix_fmt,
m_codecCtx->width, m_codecCtx->height),
"ffmpeg deinterlace"),
m_codecCtx->pix_fmt, m_codecCtx->width, m_codecCtx->height);
// allocate buffer to store final decoded frame
avpicture_fill((AVPicture*)m_frameBGR,
(uint8_t*)MEM_callocN(avpicture_get_size(
PIX_FMT_BGR24,
m_codecCtx->width, m_codecCtx->height),
"ffmpeg bgr"),
PIX_FMT_BGR24, m_codecCtx->width, m_codecCtx->height);
// allocate sws context
m_imgConvertCtx = sws_getContext(
m_codecCtx->width,
m_codecCtx->height,
m_codecCtx->pix_fmt,
m_codecCtx->width,
m_codecCtx->height,
PIX_FMT_BGR24,
SWS_FAST_BILINEAR,
NULL, NULL, NULL);
if (!m_imgConvertCtx) {
avcodec_close(m_codecCtx);
av_close_input_file(m_formatCtx);
av_free(m_frame);
MEM_freeN(m_frameDeinterlaced->data[0]);
av_free(m_frameDeinterlaced);
MEM_freeN(m_frameBGR->data[0]);
av_free(m_frameBGR);
return -1;
}
return 0;
}
// open video file
void VideoFFmpeg::openFile (char * filename)
{
do_init_ffmpeg();
if (openStream(filename, NULL, NULL) != 0)
return;
if (m_codecCtx->gop_size)
m_preseek = (m_codecCtx->gop_size < 25) ? m_codecCtx->gop_size+1 : 25;
else if (m_codecCtx->has_b_frames)
m_preseek = 25; // should determine gopsize
else
m_preseek = 0;
// get video time range
m_range[0] = 0.0;
m_range[1] = (double)m_formatCtx->duration / AV_TIME_BASE;
// open base class
VideoBase::openFile(filename);
if (m_formatCtx->pb->is_streamed)
{
// the file is in fact a streaming source, prevent seeking
m_isFile = false;
// for streaming it is important to do non blocking read
m_formatCtx->flags |= AVFMT_FLAG_NONBLOCK;
}
}
// open video capture device
void VideoFFmpeg::openCam (char * file, short camIdx)
{
// open camera source
AVInputFormat *inputFormat;
AVFormatParameters formatParams;
AVRational frameRate;
char *p, filename[28], rateStr[20];
do_init_ffmpeg();
memset(&formatParams, 0, sizeof(formatParams));
#ifdef WIN32
// video capture on windows only through Video For Windows driver
inputFormat = av_find_input_format("vfwcap");
if (!inputFormat)
// Video For Windows not supported??
return;
sprintf(filename, "%d", camIdx);
#else
// In Linux we support two types of devices: VideoForLinux and DV1394.
// the user specify it with the filename:
// [<device_type>][:<standard>]
// <device_type> : 'v4l' for VideoForLinux, 'dv1394' for DV1394. By default 'v4l'
// <standard> : 'pal', 'secam' or 'ntsc'. By default 'ntsc'
// The driver name is constructed automatically from the device type:
// v4l : /dev/video<camIdx>
// dv1394: /dev/dv1394/<camIdx>
// If you have different driver name, you can specify the driver name explicitely
// instead of device type. Examples of valid filename:
// /dev/v4l/video0:pal
// /dev/ieee1394/1:ntsc
// dv1394:secam
// v4l:pal
if (file && strstr(file, "1394") != NULL)
{
// the user specifies a driver, check if it is v4l or d41394
inputFormat = av_find_input_format("dv1394");
sprintf(filename, "/dev/dv1394/%d", camIdx);
} else
{
inputFormat = av_find_input_format("video4linux");
sprintf(filename, "/dev/video%d", camIdx);
}
if (!inputFormat)
// these format should be supported, check ffmpeg compilation
return;
if (file && strncmp(file, "/dev", 4) == 0)
{
// user does not specify a driver
strncpy(filename, file, sizeof(filename));
filename[sizeof(filename)-1] = 0;
if ((p = strchr(filename, ':')) != 0)
*p = 0;
}
if (file && (p = strchr(file, ":")) != NULL)
formatParams.standard = p+1;
#endif
//frame rate
if (m_captRate <= 0.f)
m_captRate = defFrameRate;
sprintf(rateStr, "%f", m_captRate);
av_parse_video_frame_rate(&frameRate, rateStr);
// populate format parameters
// need to specify the time base = inverse of rate
formatParams.time_base.num = frameRate.den;
formatParams.time_base.den = frameRate.num;
formatParams.width = m_captWidth;
formatParams.height = m_captHeight;
if (openStream(filename, inputFormat, &formatParams) != 0)
return;
// for video capture it is important to do non blocking read
m_formatCtx->flags |= AVFMT_FLAG_NONBLOCK;
// open base class
VideoBase::openCam(file, camIdx);
}
// play video
bool VideoFFmpeg::play (void)
{
try
{
// if object is able to play
if (VideoBase::play())
{
// set video position
setPositions();
// return success
return true;
}
}
CATCH_EXCP;
return false;
}
// stop video
bool VideoFFmpeg::stop (void)
{
try
{
if (VideoBase::stop())
{
return true;
}
}
CATCH_EXCP;
return false;
}
// set video range
void VideoFFmpeg::setRange (double start, double stop)
{
try
{
// set range
VideoBase::setRange(start, stop);
// set range for video
setPositions();
}
CATCH_EXCP;
}
// set framerate
void VideoFFmpeg::setFrameRate (float rate)
{
VideoBase::setFrameRate(rate);
}
// image calculation
void VideoFFmpeg::calcImage (unsigned int texId)
{
loadFrame();
}
// load frame from video
void VideoFFmpeg::loadFrame (void)
{
// get actual time
double actTime = PIL_check_seconds_timer() - m_startTime;
// if video has ended
if (m_isFile && actTime * m_frameRate >= m_range[1])
{
// if repeats are set, decrease them
if (m_repeat > 0)
--m_repeat;
// if video has to be replayed
if (m_repeat != 0)
{
// reset its position
actTime -= (m_range[1] - m_range[0]) / m_frameRate;
m_startTime += (m_range[1] - m_range[0]) / m_frameRate;
}
// if video has to be stopped, stop it
else
m_status = SourceStopped;
}
// if video is playing
if (m_status == SourcePlaying)
{
// actual frame
long actFrame = m_isFile ? long(actTime * actFrameRate()) : m_lastFrame + 1;
// if actual frame differs from last frame
if (actFrame != m_lastFrame)
{
// get image
if(grabFrame(actFrame))
{
AVFrame* frame = getFrame();
// save actual frame
m_lastFrame = actFrame;
// init image, if needed
init(short(m_codecCtx->width), short(m_codecCtx->height));
// process image
process((BYTE*)(frame->data[0]));
}
}
}
}
// set actual position
void VideoFFmpeg::setPositions (void)
{
// set video start time
m_startTime = PIL_check_seconds_timer();
// if file is played and actual position is before end position
if (m_isFile && m_lastFrame >= 0 && m_lastFrame < m_range[1] * actFrameRate())
// continue from actual position
m_startTime -= double(m_lastFrame) / actFrameRate();
else
m_startTime -= m_range[0];
}
// position pointer in file, position in second
bool VideoFFmpeg::grabFrame(long position)
{
AVPacket packet;
int frameFinished;
int posFound = 1;
bool frameLoaded = false;
long long targetTs = 0;
// first check if the position that we are looking for is in the preseek range
// if so, just read the frame until we get there
if (position > m_curPosition + 1
&& m_preseek
&& position - (m_curPosition + 1) < m_preseek)
{
while(av_read_frame(m_formatCtx, &packet)>=0)
{
if (packet.stream_index == m_videoStream)
{
avcodec_decode_video(
m_codecCtx,
m_frame, &frameFinished,
packet.data, packet.size);
if (frameFinished)
m_curPosition++;
}
av_free_packet(&packet);
if (position == m_curPosition+1)
break;
}
}
// if the position is not in preseek, do a direct jump
if (position != m_curPosition + 1) {
double timeBase = av_q2d(m_formatCtx->streams[m_videoStream]->time_base);
long long pos = (long long)
((long long) (position - m_preseek) * AV_TIME_BASE / m_baseFrameRate);
long long startTs = m_formatCtx->streams[m_videoStream]->start_time;
if (pos < 0)
pos = 0;
if (startTs != AV_NOPTS_VALUE)
pos += (long long)(startTs * AV_TIME_BASE * timeBase);
av_seek_frame(m_formatCtx, -1, pos, AVSEEK_FLAG_BACKWARD);
// current position is now lost, guess a value.
// It's not important because it will be set at this end of this function
m_curPosition = position - m_preseek - 1;
// this is the timestamp of the frame we're looking for
targetTs = (long long)(((double) position) / m_baseFrameRate / timeBase);
if (startTs != AV_NOPTS_VALUE)
targetTs += startTs;
posFound = 0;
avcodec_flush_buffers(m_codecCtx);
}
while(av_read_frame(m_formatCtx, &packet)>=0)
{
if(packet.stream_index == m_videoStream)
{
avcodec_decode_video(m_codecCtx,
m_frame, &frameFinished,
packet.data, packet.size);
if (frameFinished && !posFound)
{
if (packet.dts >= targetTs)
posFound = 1;
}
if(frameFinished && posFound == 1)
{
AVFrame * input = m_frame;
/* This means the data wasnt read properly,
this check stops crashing */
if ( input->data[0]==0 && input->data[1]==0
&& input->data[2]==0 && input->data[3]==0)
{
av_free_packet(&packet);
break;
}
if (m_deinterlace)
{
if (avpicture_deinterlace(
(AVPicture*) m_frameDeinterlaced,
(const AVPicture*) m_frame,
m_codecCtx->pix_fmt,
m_codecCtx->width,
m_codecCtx->height) >= 0)
{
input = m_frameDeinterlaced;
}
}
// convert to BGR24
sws_scale(m_imgConvertCtx,
input->data,
input->linesize,
0,
m_codecCtx->height,
m_frameBGR->data,
m_frameBGR->linesize);
av_free_packet(&packet);
frameLoaded = true;
break;
}
}
av_free_packet(&packet);
}
if (frameLoaded)
m_curPosition = position;
return frameLoaded;
}
// python methods
// cast Image pointer to VideoFFmpeg
inline VideoFFmpeg * getVideoFFmpeg (PyImage * self)
{ return static_cast<VideoFFmpeg*>(self->m_image); }
// object initialization
static int VideoFFmpeg_init (PyObject * pySelf, PyObject * args, PyObject * kwds)
{
PyImage * self = reinterpret_cast<PyImage*>(pySelf);
// parameters - video source
// file name or format type for capture (only for Linux: video4linux or dv1394)
char * file = NULL;
// capture device number
short capt = -1;
// capture width, only if capt is >= 0
short width = 0;
// capture height, only if capt is >= 0
short height = 0;
// capture rate, only if capt is >= 0
float rate = 25.f;
static char *kwlist[] = {"file", "capture", "rate", "width", "height", NULL};
// get parameters
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|hfhh", kwlist, &file, &capt,
&rate, &width, &height))
return -1;
try
{
// create video object
Video_init<VideoFFmpeg>(self);
// set thread usage
getVideoFFmpeg(self)->initParams(width, height, rate);
// open video source
Video_open(getVideo(self), file, capt);
}
catch (Exception & exp)
{
exp.report();
return -1;
}
// initialization succeded
return 0;
}
PyObject * VideoFFmpeg_getPreseek (PyImage *self, void * closure)
{
return Py_BuildValue("h", getFFmpeg(self)->getPreseek());
}
// set range
int VideoFFmpeg_setPreseek (PyImage * self, PyObject * value, void * closure)
{
// check validity of parameter
if (value == NULL || !PyInt_Check(value))
{
PyErr_SetString(PyExc_TypeError, "The value must be an integer");
return -1;
}
// set preseek
getFFmpeg(self)->setPreseek(PyInt_AsLong(value));
// success
return 0;
}
// get deinterlace
PyObject * VideoFFmpeg_getDeinterlace (PyImage * self, void * closure)
{
if (getFFmpeg(self)->getDeinterlace())
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}
// set flip
int VideoFFmpeg_setDeinterlace (PyImage * self, PyObject * value, void * closure)
{
// check parameter, report failure
if (value == NULL || !PyBool_Check(value))
{
PyErr_SetString(PyExc_TypeError, "The value must be a bool");
return -1;
}
// set deinterlace
getFFmpeg(self)->setDeinterlace(value == Py_True);
// success
return 0;
}
// methods structure
static PyMethodDef videoMethods[] =
{ // methods from VideoBase class
{"play", (PyCFunction)Video_play, METH_NOARGS, "Play video"},
{"stop", (PyCFunction)Video_stop, METH_NOARGS, "Stop (pause) video"},
{"refresh", (PyCFunction)Video_refresh, METH_NOARGS, "Refresh video - get its status"},
{NULL}
};
// attributes structure
static PyGetSetDef videoGetSets[] =
{ // methods from VideoBase class
{"status", (getter)Video_getStatus, NULL, "video status", NULL},
{"range", (getter)Video_getRange, (setter)Video_setRange, "replay range", NULL},
{"repeat", (getter)Video_getRepeat, (setter)Video_setRepeat, "repeat count, -1 for infinite repeat", NULL},
{"framerate", (getter)Video_getFrameRate, (setter)Video_setFrameRate, "frame rate", NULL},
// attributes from ImageBase class
{"image", (getter)Image_getImage, NULL, "image data", NULL},
{"size", (getter)Image_getSize, NULL, "image size", NULL},
{"scale", (getter)Image_getScale, (setter)Image_setScale, "fast scale of image (near neighbour)", NULL},
{"flip", (getter)Image_getFlip, (setter)Image_setFlip, "flip image vertically", NULL},
{"filter", (getter)Image_getFilter, (setter)Image_setFilter, "pixel filter", NULL},
{"preseek", (getter)VideoFFmpeg_getPreseek, (setter)VideoFFmpeg_setPreseek, "nb of frames of preseek", NULL},
{"deinterlace", (getter)VideoFFmpeg_getDeinterlace, (setter)VideoFFmpeg_setDeinterlace, "deinterlace image", NULL},
{NULL}
};
// python type declaration
PyTypeObject VideoFFmpegType =
{
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"VideoTexture.VideoFFmpeg", /*tp_name*/
sizeof(PyImage), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor)Image_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/
"FFmpeg video source", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
videoMethods, /* tp_methods */
0, /* tp_members */
videoGetSets, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)VideoFFmpeg_init, /* tp_init */
0, /* tp_alloc */
Image_allocNew, /* tp_new */
};
#endif //WITH_FFMPEG

@ -0,0 +1,159 @@
/* $Id$
-----------------------------------------------------------------------------
This source file is part of VideoTexture 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 VIDEOFFMPEG_H
#define VIDEOFFMPEG_H
#ifdef WITH_FFMPEG
extern "C" {
#include <ffmpeg/avformat.h>
#include <ffmpeg/avcodec.h>
#include <ffmpeg/rational.h>
#include <ffmpeg/swscale.h>
}
#if LIBAVFORMAT_VERSION_INT < (49 << 16)
#define FFMPEG_OLD_FRAME_RATE 1
#else
#define FFMPEG_CODEC_IS_POINTER 1
#endif
#ifdef FFMPEG_CODEC_IS_POINTER
static inline AVCodecContext* get_codec_from_stream(AVStream* stream)
{
return stream->codec;
}
#else
static inline AVCodecContext* get_codec_from_stream(AVStream* stream)
{
return &stream->codec;
}
#endif
#include "VideoBase.h"
// type VideoFFmpeg declaration
class VideoFFmpeg : public VideoBase
{
public:
/// constructor
VideoFFmpeg (HRESULT * hRslt);
/// destructor
virtual ~VideoFFmpeg ();
/// set initial parameters
void initParams (short width, short height, float rate);
/// open video file
virtual void openFile (char * file);
/// open video capture device
virtual void openCam (char * driver, short camIdx);
/// release video source
virtual bool release (void);
/// play video
virtual bool play (void);
/// stop/pause video
virtual bool stop (void);
/// set play range
virtual void setRange (double start, double stop);
/// set frame rate
virtual void setFrameRate (float rate);
// some specific getters and setters
int getPreseek(void) { return m_preseek; }
void setPreseek(int preseek) { if (preseek >= 0) m_preseek = preseek; }
bool getDeinterlace(void) { return m_deinterlace; }
void setDeinterlace(bool deinterlace) { m_deinterlace = deinterlace; }
protected:
// format and codec information
AVCodec *m_codec;
AVFormatContext *m_formatCtx;
AVCodecContext *m_codecCtx;
// raw frame extracted from video file
AVFrame *m_frame;
// deinterlaced frame if codec requires it
AVFrame *m_frameDeinterlaced;
// decoded RGB24 frame if codec requires it
AVFrame *m_frameBGR;
// conversion from raw to RGB is done with sws_scale
struct SwsContext *m_imgConvertCtx;
// should the codec be deinterlaced?
bool m_deinterlace;
// number of frame of preseek
int m_preseek;
// order number of stream holding the video in format context
int m_videoStream;
// the actual frame rate
double m_baseFrameRate;
/// last displayed frame
long m_lastFrame;
/// current file pointer position in file expressed in frame number
long m_curPosition;
/// time of video play start
double m_startTime;
/// width of capture in pixel
short m_captWidth;
/// height of capture in pixel
short m_captHeight;
/// frame rate of capture in frames per seconds
float m_captRate;
/// image calculation
virtual void calcImage (unsigned int texId);
/// load frame from video
void loadFrame (void);
/// set actual position
void setPositions (void);
/// get actual framerate
double actFrameRate (void) { return m_frameRate * m_baseFrameRate; }
/// common function to video file and capture
int openStream(const char *filename, AVInputFormat *inputFormat, AVFormatParameters *formatParams);
/// check if a frame is available and load it in pFrame, return true if a frame could be retrieved
bool grabFrame(long frame);
/// return the frame in RGB24 format, the image data is found in AVFrame.data[0]
AVFrame* getFrame(void) { return m_frameBGR; }
};
inline VideoFFmpeg * getFFmpeg (PyImage * self)
{
return static_cast<VideoFFmpeg*>(self->m_image);
}
#endif //WITH_FFMPEG
#endif

@ -0,0 +1,206 @@
/* $Id$
-----------------------------------------------------------------------------
This source file is part of VideoTexure library
Copyright (c) 2006 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.
-----------------------------------------------------------------------------
*/
#define PY_ARRAY_UNIQUE_SYMBOL numpyPtr
#include <Python.h>
#include <RAS_GLExtensionManager.h>
#include <RAS_IPolygonMaterial.h>
#include <numpy/arrayobject.h>
//Old API
//#include "TexPlayer.h"
//#include "TexImage.h"
//#include "TexFrameBuff.h"
//#include "TexPlayerGL.h"
#include "ImageBase.h"
#include "FilterBase.h"
#include "Texture.h"
#include "Exception.h"
// get material id
static PyObject * getMaterialID (PyObject *self, PyObject *args)
{
// parameters - game object with video texture
PyObject * obj = NULL;
// material name
char * matName;
// get parameters
if (!PyArg_ParseTuple(args, "Os", &obj, &matName))
return NULL;
// get material id
short matID = getMaterialID(obj, matName);
// if material was not found, report errot
if (matID < 0)
{
PyErr_SetString(PyExc_RuntimeError, "object doesn't have material with given name");
return NULL;
}
// return material ID
return Py_BuildValue("h", matID);
}
// get last error description
static PyObject * getLastError (PyObject *self, PyObject *args)
{
return Py_BuildValue("s", Exception::m_lastError.c_str());
}
// set log file
static PyObject * setLogFile (PyObject *self, PyObject *args)
{
// get parameters
if (!PyArg_ParseTuple(args, "s", &Exception::m_logFile))
return Py_BuildValue("i", -1);
// log file was loaded
return Py_BuildValue("i", 0);
}
// function to initialize numpy structures
static bool initNumpy (void)
{
// init module and report failure
import_array1(false);
// report success
return true;
}
// image to numpy array
static PyObject * imageToArray (PyObject * self, PyObject *args)
{
// parameter is Image object
PyObject * pyImg;
if (!PyArg_ParseTuple(args, "O", &pyImg) || !pyImageTypes.in(pyImg->ob_type))
{
// if object is incorect, report error
PyErr_SetString(PyExc_TypeError, "The value must be a image source object");
return NULL;
}
// get image structure
PyImage * img = reinterpret_cast<PyImage*>(pyImg);
// check initialization of numpy interface, and initialize it if needed
if (numpyPtr == NULL && !initNumpy()) Py_RETURN_NONE;
// create array object
npy_intp dim[1];
dim[0] = img->m_image->getBuffSize() / sizeof(unsigned int);
unsigned int * imgBuff = img->m_image->getImage();
// if image is available, convert it to array
if (imgBuff != NULL)
return PyArray_SimpleNewFromData(1, dim, NPY_UBYTE, imgBuff);
// otherwise return None
Py_RETURN_NONE;
}
// metody modulu
static PyMethodDef moduleMethods[] =
{
{"materialID", getMaterialID, METH_VARARGS, "Gets object's Blender Material ID"},
{"getLastError", getLastError, METH_NOARGS, "Gets last error description"},
{"setLogFile", setLogFile, METH_VARARGS, "Sets log file name"},
{"imageToArray", imageToArray, METH_VARARGS, "get array from image source"},
{NULL} /* Sentinel */
};
#if WITH_FFMPEG
extern PyTypeObject VideoFFmpegType;
#endif
extern PyTypeObject FilterBlueScreenType;
extern PyTypeObject FilterGrayType;
extern PyTypeObject FilterColorType;
extern PyTypeObject FilterLevelType;
extern PyTypeObject FilterNormalType;
extern PyTypeObject FilterRGB24Type;
extern PyTypeObject FilterBGR24Type;
extern PyTypeObject ImageBuffType;
extern PyTypeObject ImageMixType;
extern PyTypeObject ImageRenderType;
extern PyTypeObject ImageViewportType;
extern PyTypeObject ImageViewportType;
static void registerAllTypes(void)
{
#if WITH_FFMPEG
pyImageTypes.add(&VideoFFmpegType, "VideoFFmpeg");
#endif
pyImageTypes.add(&ImageBuffType, "ImageBuff");
pyImageTypes.add(&ImageMixType, "ImageMix");
//pyImageTypes.add(&ImageRenderType, "ImageRender");
pyImageTypes.add(&ImageViewportType, "ImageViewport");
pyFilterTypes.add(&FilterBlueScreenType, "FilterBlueScreen");
pyFilterTypes.add(&FilterGrayType, "FilterGray");
pyFilterTypes.add(&FilterColorType, "FilterColor");
pyFilterTypes.add(&FilterLevelType, "FilterLevel");
pyFilterTypes.add(&FilterNormalType, "FilterNormal");
pyFilterTypes.add(&FilterRGB24Type, "FilterRGB24");
pyFilterTypes.add(&FilterBGR24Type, "FilterBGR24");
}
PyObject* initVideoTexture(void)
{
// initialize GL extensions
//bgl::InitExtensions(0);
// prepare classes
registerAllTypes();
if (!pyImageTypes.ready())
return NULL;
if (!pyFilterTypes.ready())
return NULL;
if (PyType_Ready(&TextureType) < 0)
return NULL;
PyObject * m = Py_InitModule4("VideoTexture", moduleMethods,
"Module that allows to play video files on textures in GameBlender.",
(PyObject*)NULL,PYTHON_API_VERSION);
if (m == NULL)
return NULL;
// prepare numpy array
numpyPtr = NULL;
// initialize classes
pyImageTypes.reg(m);
pyFilterTypes.reg(m);
Py_INCREF(&TextureType);
PyModule_AddObject(m, "Texture", (PyObject*)&TextureType);
// init last error description
Exception::m_lastError[0] = '\0';
return m;
}
// registration to Image types, put here because of silly linker bug