Blender V2.61 - r43446

ImageBase.cpp

Go to the documentation of this file.
00001 /*
00002 -----------------------------------------------------------------------------
00003 This source file is part of VideoTexture library
00004 
00005 Copyright (c) 2007 The Zdeno Ash Miklas
00006 
00007 This program is free software; you can redistribute it and/or modify it under
00008 the terms of the GNU Lesser General Public License as published by the Free Software
00009 Foundation; either version 2 of the License, or (at your option) any later
00010 version.
00011 
00012 This program is distributed in the hope that it will be useful, but WITHOUT
00013 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00014 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
00015 
00016 You should have received a copy of the GNU Lesser General Public License along with
00017 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
00018 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
00019 http://www.gnu.org/copyleft/lesser.txt.
00020 -----------------------------------------------------------------------------
00021 */
00022 
00027 #include "ImageBase.h"
00028 extern "C" {
00029 #include "bgl.h"
00030 }
00031 #include "GL/glew.h"
00032 
00033 #include <vector>
00034 #include <string.h>
00035 
00036 #include <PyObjectPlus.h>
00037 #include <structmember.h>
00038 
00039 #include "FilterBase.h"
00040 
00041 #include "Exception.h"
00042 
00043 #if (defined(WIN32) || defined(WIN64)) && !defined(FREE_WINDOWS)
00044 #define strcasecmp  _stricmp
00045 #endif
00046 
00047 // ImageBase class implementation
00048 
00049 // constructor
00050 ImageBase::ImageBase (bool staticSrc) : m_image(NULL), m_imgSize(0),
00051 m_avail(false), m_scale(false), m_scaleChange(false), m_flip(false),
00052 m_staticSources(staticSrc), m_pyfilter(NULL)
00053 {
00054     m_size[0] = m_size[1] = 0;
00055     m_exports = 0;
00056 }
00057 
00058 
00059 // destructor
00060 ImageBase::~ImageBase (void)
00061 {
00062     // release image
00063     if (m_image)
00064         delete [] m_image;
00065 }
00066 
00067 
00068 // release python objects
00069 bool ImageBase::release (void)
00070 {
00071     // iterate sources
00072     for (ImageSourceList::iterator it = m_sources.begin(); it != m_sources.end(); ++it)
00073     {
00074         // release source object
00075         delete *it;
00076         *it = NULL;
00077     }
00078     // release filter object
00079     Py_XDECREF(m_pyfilter);
00080     m_pyfilter = NULL;
00081     return true;
00082 }
00083 
00084 
00085 // get image
00086 unsigned int * ImageBase::getImage (unsigned int texId, double ts)
00087 {
00088     // if image is not available
00089     if (!m_avail)
00090     {
00091         // if there are any sources
00092         if (!m_sources.empty())
00093         {
00094             // get images from sources
00095             for (ImageSourceList::iterator it = m_sources.begin(); it != m_sources.end(); ++it)
00096                 // get source image
00097                 (*it)->getImage(ts);
00098             // init image
00099             init(m_sources[0]->getSize()[0], m_sources[0]->getSize()[1]);
00100         }
00101         // calculate new image
00102         calcImage(texId, ts);
00103     }
00104     // if image is available, return it, otherwise NULL
00105     return m_avail ? m_image : NULL;
00106 }
00107 
00108 
00109 // refresh image source
00110 void ImageBase::refresh (void)
00111 {
00112     // invalidate this image
00113     m_avail = false;
00114     // refresh all sources
00115     for (ImageSourceList::iterator it = m_sources.begin(); it != m_sources.end(); ++it)
00116         (*it)->refresh();
00117 }
00118 
00119 
00120 // get source object
00121 PyImage * ImageBase::getSource (const char * id)
00122 {
00123     // find source
00124     ImageSourceList::iterator src = findSource(id);
00125     // return it, if found
00126     return src != m_sources.end() ? (*src)->getSource() : NULL;
00127 }
00128 
00129 
00130 // set source object
00131 bool ImageBase::setSource (const char * id, PyImage * source)
00132 {
00133     // find source
00134     ImageSourceList::iterator src = findSource(id);
00135     // check source loop
00136     if (source != NULL && source->m_image->loopDetect(this))
00137         return false;
00138     // if found, set new object
00139     if (src != m_sources.end())
00140         // if new object is not empty or sources are static
00141         if (source != NULL || m_staticSources)
00142             // replace previous source
00143             (*src)->setSource(source);
00144         // otherwise delete source
00145         else
00146             m_sources.erase(src);
00147     // if source is not found and adding is allowed
00148     else
00149         if (!m_staticSources)
00150         {
00151             // create new source
00152             ImageSource * newSrc = newSource(id);
00153             newSrc->setSource(source);
00154             // if source was created, add it to source list
00155             if (newSrc != NULL) m_sources.push_back(newSrc);
00156         }
00157         // otherwise source wasn't set
00158         else 
00159             return false;
00160     // source was set
00161     return true;
00162 }
00163 
00164 
00165 // set pixel filter
00166 void ImageBase::setFilter (PyFilter * filt)
00167 {
00168     // reference new filter
00169     if (filt != NULL) Py_INCREF(filt);
00170     // release previous filter
00171     Py_XDECREF(m_pyfilter);
00172     // set new filter
00173     m_pyfilter = filt;
00174 }
00175 
00176 ExceptionID ImageHasExports;
00177 ExceptionID InvalidColorChannel;
00178 
00179 ExpDesc ImageHasExportsDesc (ImageHasExports, "Image has exported buffers, cannot resize");
00180 ExpDesc InvalidColorChannelDesc (InvalidColorChannel, "Invalid or too many color channels specified. At most 4 values within R, G, B, A, 0, 1");
00181 
00182 // initialize image data
00183 void ImageBase::init (short width, short height)
00184 {
00185     // if image has to be scaled
00186     if (m_scale)
00187     {
00188         // recalc sizes of image
00189         width = calcSize(width);
00190         height = calcSize(height);
00191     }
00192     // if sizes differ
00193     if (width != m_size[0] || height != m_size[1])
00194     {
00195         if (m_exports > 0)
00196             THRWEXCP(ImageHasExports,S_OK);
00197 
00198         // new buffer size
00199         unsigned int newSize = width * height;
00200         // if new buffer is larger than previous
00201         if (newSize > m_imgSize)
00202         {
00203             // set new buffer size
00204             m_imgSize = newSize;
00205             // release previous and create new buffer
00206             if (m_image)
00207                 delete [] m_image;
00208             m_image = new unsigned int[m_imgSize];
00209         }
00210         // new image size
00211         m_size[0] = width;
00212         m_size[1] = height;
00213         // scale was processed
00214         m_scaleChange = false;
00215     }
00216 }
00217 
00218 
00219 // find source
00220 ImageSourceList::iterator ImageBase::findSource (const char * id)
00221 {
00222     // iterate sources
00223     ImageSourceList::iterator it;
00224     for (it = m_sources.begin(); it != m_sources.end(); ++it)
00225         // if id matches, return iterator
00226         if ((*it)->is(id)) return it;
00227     // source not found
00228     return it;
00229 }
00230 
00231 
00232 // check sources sizes
00233 bool ImageBase::checkSourceSizes (void)
00234 {
00235     // reference size
00236     short * refSize = NULL;
00237     // iterate sources
00238     for (ImageSourceList::iterator it = m_sources.begin(); it != m_sources.end(); ++it)
00239     {
00240         // get size of current source
00241         short * curSize = (*it)->getSize();
00242         // if size is available and is not empty
00243         if (curSize[0] != 0 && curSize[1] != 0) {
00244             // if reference size is not set
00245             if (refSize == NULL) {
00246                 // set current size as reference
00247                 refSize = curSize;
00248         // otherwise check with current size
00249             } else if (curSize[0] != refSize[0] || curSize[1] != refSize[1]) {
00250                 // if they don't match, report it
00251                 return false;
00252             }
00253         }
00254     }
00255     // all sizes match
00256     return true;
00257 }
00258 
00259 
00260 // compute nearest power of 2 value
00261 short ImageBase::calcSize (short size)
00262 {
00263     // while there is more than 1 bit in size value
00264     while ((size & (size - 1)) != 0)
00265         // clear last bit
00266         size = size & (size - 1);
00267     // return result
00268     return size;
00269 }
00270 
00271 
00272 // perform loop detection
00273 bool ImageBase::loopDetect (ImageBase * img)
00274 {
00275     // if this object is the same as parameter, loop is detected
00276     if (this == img) return true;
00277     // check all sources
00278     for (ImageSourceList::iterator it = m_sources.begin(); it != m_sources.end(); ++it)
00279         // if source detected loop, return this result
00280         if ((*it)->getSource() != NULL && (*it)->getSource()->m_image->loopDetect(img))
00281             return true;
00282     // no loop detected
00283     return false;
00284 }
00285 
00286 
00287 // ImageSource class implementation
00288 
00289 // constructor
00290 ImageSource::ImageSource (const char * id) : m_source(NULL), m_image(NULL)
00291 {
00292     // copy id
00293     int idx;
00294     for (idx = 0; id[idx] != '\0' && idx < SourceIdSize - 1; ++idx)
00295         m_id[idx] = id[idx];
00296     m_id[idx] = '\0';
00297 }
00298 
00299 // destructor
00300 ImageSource::~ImageSource (void)
00301 {
00302     // release source
00303     setSource(NULL);
00304 }
00305 
00306 
00307 // compare id
00308 bool ImageSource::is (const char * id)
00309 {
00310     for (char * myId = m_id; *myId != '\0'; ++myId, ++id)
00311         if (*myId != *id) return false;
00312     return *id == '\0';
00313 }
00314 
00315 
00316 // set source object
00317 void ImageSource::setSource (PyImage * source)
00318 {
00319     // reference new source
00320     if (source != NULL) Py_INCREF(source);
00321     // release previous source
00322     Py_XDECREF(m_source);
00323     // set new source
00324     m_source = source;
00325 }
00326 
00327 
00328 // get image from source
00329 unsigned int * ImageSource::getImage (double ts)
00330 {
00331     // if source is available
00332     if (m_source != NULL)
00333         // get image from source
00334         m_image = m_source->m_image->getImage(0, ts);
00335     // otherwise reset buffer
00336     else
00337         m_image = NULL;
00338     // return image
00339     return m_image;
00340 }
00341 
00342 
00343 // refresh source
00344 void ImageSource::refresh (void)
00345 {
00346     // if source is available, refresh it
00347     if (m_source != NULL) m_source->m_image->refresh();
00348 }
00349 
00350 
00351 
00352 // list of image types
00353 PyTypeList pyImageTypes;
00354 
00355 
00356 
00357 // functions for python interface
00358 
00359 // object allocation
00360 PyObject * Image_allocNew (PyTypeObject * type, PyObject * args, PyObject * kwds)
00361 {
00362     // allocate object
00363     PyImage * self = reinterpret_cast<PyImage*>(type->tp_alloc(type, 0));
00364     // initialize object structure
00365     self->m_image = NULL;
00366     // return allocated object
00367     return reinterpret_cast<PyObject*>(self);
00368 }
00369 
00370 // object deallocation
00371 void Image_dealloc (PyImage * self)
00372 {
00373     // release object attributes
00374     if (self->m_image != NULL)
00375     {
00376         if (self->m_image->m_exports > 0)
00377         {
00378             PyErr_SetString(PyExc_SystemError,
00379                             "deallocated Image object has exported buffers");
00380             PyErr_Print();
00381         }
00382         // if release requires deleting of object, do it
00383         if (self->m_image->release())
00384             delete self->m_image;
00385         self->m_image = NULL;
00386     }
00387 }
00388 
00389 // get image data
00390 PyObject * Image_getImage (PyImage * self, char * mode)
00391 {
00392     try
00393     {
00394         unsigned int * image = self->m_image->getImage();
00395         if (image) 
00396         {
00397             // build BGL buffer
00398             int dimensions = self->m_image->getBuffSize();
00399             Buffer * buffer;
00400             if (mode == NULL || !strcasecmp(mode, "RGBA"))
00401             {
00402                 buffer = BGL_MakeBuffer( GL_BYTE, 1, &dimensions, image);
00403             }
00404             else 
00405             {
00406                 int i, c, ncolor, pixels;
00407                 int offset[4];
00408                 unsigned char *s, *d;
00409                 // scan the mode to get the channels requested, no more than 4
00410                 for (i=ncolor=0; mode[i] != 0 && ncolor < 4; i++)
00411                 {
00412                     switch (toupper(mode[i]))
00413                     {
00414                     case 'R':
00415                         offset[ncolor++] = 0;
00416                         break;
00417                     case 'G':
00418                         offset[ncolor++] = 1;
00419                         break;
00420                     case 'B':
00421                         offset[ncolor++] = 2;
00422                         break;
00423                     case 'A':
00424                         offset[ncolor++] = 3;
00425                         break;
00426                     case '0':
00427                         offset[ncolor++] = -1;
00428                         break;
00429                     case '1':
00430                         offset[ncolor++] = -2;
00431                         break;
00432                     // if you add more color code, change the switch further down
00433                     default:
00434                         THRWEXCP(InvalidColorChannel,S_OK);
00435                     }
00436                 }
00437                 if (mode[i] != 0) {
00438                     THRWEXCP(InvalidColorChannel,S_OK);
00439                 }
00440                 // first get the number of pixels
00441                 pixels = dimensions / 4;
00442                 // multiple by the number of channels, each is one byte
00443                 dimensions = pixels * ncolor;
00444                 // get an empty buffer
00445                 buffer = BGL_MakeBuffer( GL_BYTE, 1, &dimensions, NULL);
00446                 // and fill it
00447                 for (i=0, d=(unsigned char*)buffer->buf.asbyte, s=(unsigned char*)image; 
00448                      i<pixels; 
00449                      ++i, d+=ncolor, s+=4)
00450                 {
00451                     for (c=0; c<ncolor; c++)
00452                     {
00453                         switch (offset[c])
00454                         {
00455                         case 0: d[c] = s[0]; break;
00456                         case 1: d[c] = s[1]; break;
00457                         case 2: d[c] = s[2]; break;
00458                         case 3: d[c] = s[3]; break;
00459                         case -1: d[c] = 0; break;
00460                         case -2: d[c] = 0xFF; break;
00461                         }
00462                     }
00463                 }
00464             }
00465             return (PyObject*)buffer;
00466         }
00467     }
00468     catch (Exception & exp)
00469     {
00470         exp.report();
00471         return NULL;
00472     }
00473     Py_RETURN_NONE;
00474 }
00475 
00476 // get image size
00477 PyObject * Image_getSize (PyImage * self, void * closure)
00478 {
00479     return Py_BuildValue("(hh)", self->m_image->getSize()[0],
00480         self->m_image->getSize()[1]);
00481 }
00482 
00483 // refresh image
00484 PyObject * Image_refresh (PyImage * self)
00485 {
00486     self->m_image->refresh();
00487     Py_RETURN_NONE;
00488 }
00489 
00490 // get scale
00491 PyObject * Image_getScale (PyImage * self, void * closure)
00492 {
00493     if (self->m_image != NULL && self->m_image->getScale()) Py_RETURN_TRUE;
00494     else Py_RETURN_FALSE;
00495 }
00496 
00497 // set scale
00498 int Image_setScale (PyImage * self, PyObject * value, void * closure)
00499 {
00500     // check parameter, report failure
00501     if (value == NULL || !PyBool_Check(value))
00502     {
00503         PyErr_SetString(PyExc_TypeError, "The value must be a bool");
00504         return -1;
00505     }
00506     // set scale
00507     if (self->m_image != NULL) self->m_image->setScale(value == Py_True);
00508     // success
00509     return 0;
00510 }
00511 
00512 // get flip
00513 PyObject * Image_getFlip (PyImage * self, void * closure)
00514 {
00515     if (self->m_image != NULL && self->m_image->getFlip()) Py_RETURN_TRUE;
00516     else Py_RETURN_FALSE;
00517 }
00518 
00519 // set flip
00520 int Image_setFlip (PyImage * self, PyObject * value, void * closure)
00521 {
00522     // check parameter, report failure
00523     if (value == NULL || !PyBool_Check(value))
00524     {
00525         PyErr_SetString(PyExc_TypeError, "The value must be a bool");
00526         return -1;
00527     }
00528     // set scale
00529     if (self->m_image != NULL) self->m_image->setFlip(value == Py_True);
00530     // success
00531     return 0;
00532 }
00533 
00534 
00535 // get filter source object
00536 PyObject * Image_getSource (PyImage * self, PyObject * args)
00537 {
00538     // get arguments
00539     char * id;
00540     if (!PyArg_ParseTuple(args, "s:getSource", &id))
00541         return NULL;
00542     if (self->m_image != NULL)
00543     {
00544         // get source object
00545         PyObject * src = reinterpret_cast<PyObject*>(self->m_image->getSource(id));
00546         // if source is available
00547         if (src != NULL)
00548         {
00549             // return source
00550             Py_INCREF(src);
00551             return src;
00552         }
00553     }
00554     // source was not found
00555     Py_RETURN_NONE;
00556 }
00557 
00558 
00559 // set filter source object
00560 PyObject * Image_setSource (PyImage * self, PyObject * args)
00561 {
00562     // get arguments
00563     char * id;
00564     PyObject * obj;
00565     if (!PyArg_ParseTuple(args, "sO:setSource", &id, &obj))
00566         return NULL;
00567     if (self->m_image != NULL)
00568     {
00569         // check type of object
00570         if (pyImageTypes.in(Py_TYPE(obj)))
00571         {
00572             // convert to image struct
00573             PyImage * img = reinterpret_cast<PyImage*>(obj);
00574             // set source
00575             if (!self->m_image->setSource(id, img))
00576             {
00577                 // if not set, retport error
00578                 PyErr_SetString(PyExc_RuntimeError, "Invalid source or id");
00579                 return NULL;
00580             }
00581         }
00582         // else report error
00583         else
00584         {
00585             PyErr_SetString(PyExc_RuntimeError, "Invalid type of object");
00586             return NULL;
00587         }
00588     }
00589     // return none
00590     Py_RETURN_NONE;
00591 }
00592 
00593 
00594 // get pixel filter object
00595 PyObject * Image_getFilter (PyImage * self, void * closure)
00596 {
00597     // if image object is available
00598     if (self->m_image != NULL)
00599     {
00600         // pixel filter object
00601         PyObject * filt = reinterpret_cast<PyObject*>(self->m_image->getFilter());
00602         // if filter is present
00603         if (filt != NULL)
00604         {
00605             // return it
00606             Py_INCREF(filt);
00607             return filt;
00608         }
00609     }
00610     // otherwise return none
00611     Py_RETURN_NONE;
00612 }
00613 
00614 
00615 // set pixel filter object
00616 int Image_setFilter (PyImage * self, PyObject * value, void * closure)
00617 {
00618     // if image object is available
00619     if (self->m_image != NULL)
00620     {
00621         // check new value
00622         if (value == NULL || !pyFilterTypes.in(Py_TYPE(value)))
00623         {
00624             // report value error
00625             PyErr_SetString(PyExc_TypeError, "Invalid type of value");
00626             return -1;
00627         }
00628         // set new value
00629         self->m_image->setFilter(reinterpret_cast<PyFilter*>(value));
00630     }
00631     // return success
00632     return 0;
00633 }
00634 PyObject * Image_valid(PyImage * self, void * closure)
00635 {
00636     if (self->m_image->isImageAvailable())
00637     {
00638         Py_RETURN_TRUE;
00639     }
00640     else
00641     {
00642         Py_RETURN_FALSE;
00643     }
00644 }
00645 
00646 int Image_getbuffer(PyImage *self, Py_buffer *view, int flags)
00647 {
00648     unsigned int * image;
00649     int ret;
00650 
00651     try
00652     {
00653         // can throw in case of resize
00654         image = self->m_image->getImage();
00655     }
00656     catch (Exception & exp)
00657     {
00658         // cannot return -1, this creates a crash in Python, for now we will just return an empty buffer
00659         exp.report();
00660         //return -1;
00661         goto error;
00662     }
00663 
00664     if (!image)
00665     {
00666         // same remark, see above
00667         //PyErr_SetString(PyExc_BufferError, "Image buffer is not available");
00668         //return -1;
00669         goto error;
00670     }
00671     if (view == NULL)
00672     {
00673         self->m_image->m_exports++;
00674         return 0;
00675     }
00676     ret = PyBuffer_FillInfo(view, (PyObject*)self, image, self->m_image->getBuffSize(), 0, flags);
00677     if (ret >= 0)
00678         self->m_image->m_exports++;
00679     return ret;
00680 
00681 error:
00682     // Return a empty buffer to avoid a crash in Python 3.1
00683     // The bug is fixed in Python SVN 77916, as soon as the python revision used by Blender is
00684     // updated, you can simply return -1 and set the error
00685     static char* buf = (char *)"";
00686     ret = PyBuffer_FillInfo(view, (PyObject*)self, buf, 0, 0, flags);
00687     if (ret >= 0)
00688         self->m_image->m_exports++;
00689     return ret;
00690     
00691 }
00692 
00693 void Image_releaseBuffer(PyImage *self, Py_buffer *buffer)
00694 {
00695     self->m_image->m_exports--;
00696 }
00697 
00698 PyBufferProcs imageBufferProcs = 
00699 {
00700     (getbufferproc)Image_getbuffer,
00701     (releasebufferproc)Image_releaseBuffer
00702 };
00703