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