code cleanup: gpl header update (formatting)
[blender.git] / source / gameengine / VideoTexture / ImageBuff.cpp
index eccac9d9f89a7bff15629526d757f3c69d0017df..1593a08bb4b4c3b0a20e18ec08684cfc31b004f4 100644 (file)
@@ -1,32 +1,40 @@
-/* $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.
------------------------------------------------------------------------------
-*/
+/*
+ * ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright (c) 2007 The Zdeno Ash Miklas
+ *
+ * This source file is part of VideoTexture library
+ *
+ * Contributor(s):
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file gameengine/VideoTexture/ImageBuff.cpp
+ *  \ingroup bgevideotex
+ */
 
 // implementation
 
-#include <PyObjectPlus.h>
+#include "PyObjectPlus.h"
 #include <structmember.h>
 
 #include "ImageBuff.h"
-
+#include "Exception.h"
 #include "ImageBase.h"
 #include "FilterSource.h"
 
@@ -34,6 +42,7 @@ http://www.gnu.org/copyleft/lesser.txt.
 extern "C" {
 #include "IMB_imbuf_types.h"
 #include "IMB_imbuf.h"
+#include "bgl.h"
 };
 
 // default filter
@@ -42,6 +51,41 @@ FilterRGB24 defFilter;
 // forward declaration;
 extern PyTypeObject ImageBuffType;
 
+static int ImageBuff_init (PyObject *pySelf, PyObject *args, PyObject *kwds)
+{
+       short width = -1;
+       short height = -1;
+       unsigned char color = 0;
+       PyObject *py_scale = Py_False;
+       ImageBuff *image;
+
+       PyImage *self = reinterpret_cast<PyImage*>(pySelf);
+       // create source object
+       if (self->m_image != NULL) 
+               delete self->m_image;
+       image = new ImageBuff();
+       self->m_image = image;
+
+       if (PyArg_ParseTuple(args, "hh|bO!:ImageBuff", &width, &height, &color, &PyBool_Type, &py_scale)) 
+       {
+               // initialize image buffer
+               image->setScale(py_scale == Py_True);
+               image->clear(width, height, color);
+       }
+       else
+       {
+               // check if at least one argument was passed
+               if (width != -1 || height != -1)
+                       // yes and they didn't match => it's an error
+                       return -1;
+               // empty argument list is okay
+               PyErr_Clear();
+       }
+       // initialization succeded
+       return 0;
+
+}
+
 ImageBuff::~ImageBuff (void)
 {
        if (m_imbuf)
@@ -73,20 +117,48 @@ void ImageBuff::load (unsigned char * img, short width, short height)
        m_avail = true;
 }
 
+void ImageBuff::clear (short width, short height, unsigned char color)
+{
+       unsigned char *p;
+       int size;
+
+       // loading a new buffer implies to reset the imbuf if any, because the size may change
+       if (m_imbuf)
+       {
+               IMB_freeImBuf(m_imbuf);
+               m_imbuf = NULL;
+       }
+       // initialize image buffer
+       init(width, height);
+       // the width/height may be different due to scaling
+       size = (m_size[0] * m_size[1]);
+       // initialize memory with color for all channels
+       memset(m_image, color, size*4);
+       // and change the alpha channel
+       p = &((unsigned char*)m_image)[3];
+       for (; size>0; size--)
+       {
+               *p = 0xFF;
+               p += 4;
+       }
+       // image is available
+       m_avail = true;
+}
+
 // img must point to a array of RGBA data of size width*height
 void ImageBuff::plot (unsigned char * img, short width, short height, short x, short y, short mode)
 {
-       struct ImBuftmpbuf;
+       struct ImBuf *tmpbuf;
 
        if (m_size[0] == 0 || m_size[1] == 0 || width <= 0 || height <= 0)
                return;
 
        if (!m_imbuf) {
                // allocate most basic imbuf, we will assign the rect buffer on the fly
-               m_imbuf = IMB_allocImBuf(m_size[0], m_size[1], 0, 0, 0);
+               m_imbuf = IMB_allocImBuf(m_size[0], m_size[1], 0, 0);
        }
 
-       tmpbuf = IMB_allocImBuf(width, height, 0, 0, 0);
+       tmpbuf = IMB_allocImBuf(width, height, 0, 0);
 
        // assign temporarily our buffer to the ImBuf buffer, we use the same format
        tmpbuf->rect = (unsigned int*)img;
@@ -105,11 +177,11 @@ void ImageBuff::plot (ImageBuff* img, short x, short y, short mode)
 
        if (!m_imbuf) {
                // allocate most basic imbuf, we will assign the rect buffer on the fly
-               m_imbuf = IMB_allocImBuf(m_size[0], m_size[1], 0, 0, 0);
+               m_imbuf = IMB_allocImBuf(m_size[0], m_size[1], 0, 0);
        }
        if (!img->m_imbuf) {
                // allocate most basic imbuf, we will assign the rect buffer on the fly
-               img->m_imbuf = IMB_allocImBuf(img->m_size[0], img->m_size[1], 0, 0, 0);
+               img->m_imbuf = IMB_allocImBuf(img->m_size[0], img->m_size[1], 0, 0);
        }
        // assign temporarily our buffer to the ImBuf buffer, we use the same format
        img->m_imbuf->rect = img->m_image;
@@ -122,7 +194,7 @@ void ImageBuff::plot (ImageBuff* img, short x, short y, short mode)
 
 
 // cast Image pointer to ImageBuff
-inline ImageBuff * getImageBuff (PyImage * self)
+inline ImageBuff * getImageBuff (PyImage *self)
 { return static_cast<ImageBuff*>(self->m_image); }
 
 
@@ -137,7 +209,7 @@ static bool testPyBuffer(Py_buffer* buffer, int width, int height, unsigned int
        } 
        if (buffer->len != width*height*pixsize)
        {
-               PyErr_SetString(PyExc_ValueError, "Buffer hasn't correct size");
+               PyErr_SetString(PyExc_ValueError, "Buffer hasn't the correct size");
                return false;
        } 
        // multi dimension are ok as long as there is no hole in the memory
@@ -160,43 +232,91 @@ static bool testPyBuffer(Py_buffer* buffer, int width, int height, unsigned int
        return true;
 }
 
+static bool testBGLBuffer(Buffer* buffer, int width, int height, unsigned int pixsize)
+{
+       unsigned int size = BGL_typeSize(buffer->type);
+       for (int i=0; i<buffer->ndimensions; i++)
+       {
+               size *= buffer->dimensions[i];
+       }
+       if (size != width*height*pixsize)
+       {
+               PyErr_SetString(PyExc_ValueError, "Buffer hasn't the correct size");
+               return false;
+       } 
+       return true;
+}
+
+
 // load image
-static PyObject * load (PyImage * self, PyObject * args)
+static PyObject *load(PyImage *self, PyObject *args)
 {
        // parameters: string image buffer, its size, width, height
        Py_buffer buffer;
+       Buffer *bglBuffer;
        short width;
        short height;
+       unsigned int pixSize;
+
+       // calc proper buffer size
+       // use pixel size from filter
+       if (self->m_image->getFilter() != NULL)
+               pixSize = self->m_image->getFilter()->m_filter->firstPixelSize();
+       else
+               pixSize = defFilter.firstPixelSize();
+
        // parse parameters
        if (!PyArg_ParseTuple(args, "s*hh:load", &buffer, &width, &height))
        {
-               // report error
-               return NULL;
+               PyErr_Clear();
+               // check if it is BGL buffer
+               if (!PyArg_ParseTuple(args, "O!hh:load", &BGL_bufferType, &bglBuffer, &width, &height))
+               {
+                       // report error
+                       return NULL;
+               }
+               else
+               {
+                       if (testBGLBuffer(bglBuffer, width, height, pixSize))
+                       {
+                               try
+                               {
+                                       // if correct, load image
+                                       getImageBuff(self)->load((unsigned char*)bglBuffer->buf.asvoid, width, height);
+                               }
+                               catch (Exception & exp)
+                               {
+                                       exp.report();
+                               }
+                       }
+               }
        }
-       // else check buffer size
        else
        {
-               // calc proper buffer size
-               unsigned int pixSize;
-               // use pixel size from filter
-               if (self->m_image->getFilter() != NULL)
-                       pixSize = self->m_image->getFilter()->m_filter->firstPixelSize();
-               else
-                       pixSize = defFilter.firstPixelSize();
                // check if buffer size is correct
                if (testPyBuffer(&buffer, width, height, pixSize))
                {
-                       // if correct, load image
-                       getImageBuff(self)->load((unsigned char*)buffer.buf, width, height);
+                       try 
+                       {
+                               // if correct, load image
+                               getImageBuff(self)->load((unsigned char*)buffer.buf, width, height);
+                       }
+                       catch (Exception & exp)
+                       {
+                               exp.report();
+                       }
                }
                PyBuffer_Release(&buffer);
        }
-       Py_RETURN_NONE; 
+       if (PyErr_Occurred())
+               return NULL;
+       Py_RETURN_NONE;
 }
 
-static PyObject * plot (PyImage * self, PyObject * args)
+static PyObject *plot (PyImage *self, PyObject *args)
 {
        PyImage * other;
+       Buffer* bglBuffer;
        Py_buffer buffer;
        //unsigned char * buff;
        //unsigned int buffSize;
@@ -208,22 +328,36 @@ static PyObject * plot (PyImage * self, PyObject * args)
        if (PyArg_ParseTuple(args, "s*hhhh|h:plot", &buffer, &width, &height, &x, &y, &mode))
        {
                // correct decoding, verify that buffer size is correct
-               // we need a continous memory buffer
+               // we need a continuous memory buffer
                if (testPyBuffer(&buffer, width, height, 4))
                {
                        getImageBuff(self)->plot((unsigned char*)buffer.buf, width, height, x, y, mode);
                }
                PyBuffer_Release(&buffer);
-               Py_RETURN_NONE; 
+               if (PyErr_Occurred())
+                       return NULL;
+               Py_RETURN_NONE;
        }
        PyErr_Clear();
        // try the other format
-       if (!PyArg_ParseTuple(args, "O!hh|h:plot", &ImageBuffType, &other, &x, &y, &mode))
+       if (PyArg_ParseTuple(args, "O!hh|h:plot", &ImageBuffType, &other, &x, &y, &mode))
+       {
+               getImageBuff(self)->plot(getImageBuff(other), x, y, mode);
+               Py_RETURN_NONE;
+       }
+       PyErr_Clear();
+       // try the last format (BGL buffer)
+       if (!PyArg_ParseTuple(args, "O!hhhh|h:plot", &BGL_bufferType, &bglBuffer, &width, &height, &x, &y, &mode))
        {
-               PyErr_SetString(PyExc_TypeError, "Expecting ImageBuff or string,width,height as first arguments, postion x, y and mode and last arguments");
+               PyErr_SetString(PyExc_TypeError, "Expecting ImageBuff or Py buffer or BGL buffer as first argument; width, height next; postion x, y and mode as last arguments");
                return NULL;
        }
-       getImageBuff(self)->plot(getImageBuff(other), x, y, mode);
+       if (testBGLBuffer(bglBuffer, width, height, 4))
+       {
+               getImageBuff(self)->plot((unsigned char*)bglBuffer->buf.asvoid, width, height, x, y, mode);
+       }
+       if (PyErr_Occurred())
+               return NULL;
        Py_RETURN_NONE;
 }
 
@@ -237,9 +371,10 @@ static PyMethodDef imageBuffMethods[] =
 // attributes structure
 static PyGetSetDef imageBuffGetSets[] =
 {      // attributes from ImageBase class
+       {(char*)"valid", (getter)Image_valid, NULL, (char*)"bool to tell if an image is available", NULL},
        {(char*)"image", (getter)Image_getImage, NULL, (char*)"image data", NULL},
        {(char*)"size", (getter)Image_getSize, NULL, (char*)"image size", NULL},
-       {(char*)"scale", (getter)Image_getScale, (setter)Image_setScale, (char*)"fast scale of image (near neighbour)", NULL},
+       {(char*)"scale", (getter)Image_getScale, (setter)Image_setScale, (char*)"fast scale of image (near neighbor)", NULL},
        {(char*)"flip", (getter)Image_getFlip, (setter)Image_setFlip, (char*)"flip image vertically", NULL},
        {(char*)"filter", (getter)Image_getFilter, (setter)Image_setFilter, (char*)"pixel filter", NULL},
        {NULL}
@@ -267,7 +402,7 @@ PyTypeObject ImageBuffType =
        0,                         /*tp_str*/
        0,                         /*tp_getattro*/
        0,                         /*tp_setattro*/
-       0,                         /*tp_as_buffer*/
+       &imageBufferProcs,         /*tp_as_buffer*/
        Py_TPFLAGS_DEFAULT,        /*tp_flags*/
        "Image source from image buffer",       /* tp_doc */
        0,                             /* tp_traverse */
@@ -284,7 +419,7 @@ PyTypeObject ImageBuffType =
        0,                         /* tp_descr_get */
        0,                         /* tp_descr_set */
        0,                         /* tp_dictoffset */
-       (initproc)Image_init<ImageBuff>,     /* tp_init */
+       (initproc)ImageBuff_init,     /* tp_init */
        0,                         /* tp_alloc */
        Image_allocNew,           /* tp_new */
 };