Blender V2.61 - r43446
|
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