|
Blender
V2.59
|
00001 00004 /* $Id: ImageBuff.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 // implementation 00027 00028 #include <PyObjectPlus.h> 00029 #include <structmember.h> 00030 00031 #include "ImageBuff.h" 00032 #include "Exception.h" 00033 #include "ImageBase.h" 00034 #include "FilterSource.h" 00035 00036 // use ImBuf API for image manipulation 00037 extern "C" { 00038 #include "IMB_imbuf_types.h" 00039 #include "IMB_imbuf.h" 00040 #include "bgl.h" 00041 }; 00042 00043 // default filter 00044 FilterRGB24 defFilter; 00045 00046 // forward declaration; 00047 extern PyTypeObject ImageBuffType; 00048 00049 static int ImageBuff_init (PyObject * pySelf, PyObject * args, PyObject * kwds) 00050 { 00051 short width = -1; 00052 short height = -1; 00053 unsigned char color = 0; 00054 PyObject *py_scale = Py_False; 00055 ImageBuff *image; 00056 00057 PyImage * self = reinterpret_cast<PyImage*>(pySelf); 00058 // create source object 00059 if (self->m_image != NULL) 00060 delete self->m_image; 00061 image = new ImageBuff(); 00062 self->m_image = image; 00063 00064 if (PyArg_ParseTuple(args, "hh|bO!:ImageBuff", &width, &height, &color, &PyBool_Type, &py_scale)) 00065 { 00066 // initialize image buffer 00067 image->setScale(py_scale == Py_True); 00068 image->clear(width, height, color); 00069 } 00070 else 00071 { 00072 // check if at least one argument was passed 00073 if (width != -1 || height != -1) 00074 // yes and they didn't match => it's an error 00075 return -1; 00076 // empty argument list is okay 00077 PyErr_Clear(); 00078 } 00079 // initialization succeded 00080 return 0; 00081 00082 } 00083 00084 ImageBuff::~ImageBuff (void) 00085 { 00086 if (m_imbuf) 00087 IMB_freeImBuf(m_imbuf); 00088 } 00089 00090 00091 // load image from buffer 00092 void ImageBuff::load (unsigned char * img, short width, short height) 00093 { 00094 // loading a new buffer implies to reset the imbuf if any, because the size may change 00095 if (m_imbuf) 00096 { 00097 IMB_freeImBuf(m_imbuf); 00098 m_imbuf = NULL; 00099 } 00100 // initialize image buffer 00101 init(width, height); 00102 // original size 00103 short orgSize[2] = {width, height}; 00104 // is filter available 00105 if (m_pyfilter != NULL) 00106 // use it to process image 00107 convImage(*(m_pyfilter->m_filter), img, orgSize); 00108 else 00109 // otherwise use default filter 00110 convImage(defFilter, img, orgSize); 00111 // image is available 00112 m_avail = true; 00113 } 00114 00115 void ImageBuff::clear (short width, short height, unsigned char color) 00116 { 00117 unsigned char *p; 00118 int size; 00119 00120 // loading a new buffer implies to reset the imbuf if any, because the size may change 00121 if (m_imbuf) 00122 { 00123 IMB_freeImBuf(m_imbuf); 00124 m_imbuf = NULL; 00125 } 00126 // initialize image buffer 00127 init(width, height); 00128 // the width/height may be different due to scaling 00129 size = (m_size[0] * m_size[1]); 00130 // initialize memory with color for all channels 00131 memset(m_image, color, size*4); 00132 // and change the alpha channel 00133 p = &((unsigned char*)m_image)[3]; 00134 for (; size>0; size--) 00135 { 00136 *p = 0xFF; 00137 p += 4; 00138 } 00139 // image is available 00140 m_avail = true; 00141 } 00142 00143 // img must point to a array of RGBA data of size width*height 00144 void ImageBuff::plot (unsigned char * img, short width, short height, short x, short y, short mode) 00145 { 00146 struct ImBuf* tmpbuf; 00147 00148 if (m_size[0] == 0 || m_size[1] == 0 || width <= 0 || height <= 0) 00149 return; 00150 00151 if (!m_imbuf) { 00152 // allocate most basic imbuf, we will assign the rect buffer on the fly 00153 m_imbuf = IMB_allocImBuf(m_size[0], m_size[1], 0, 0); 00154 } 00155 00156 tmpbuf = IMB_allocImBuf(width, height, 0, 0); 00157 00158 // assign temporarily our buffer to the ImBuf buffer, we use the same format 00159 tmpbuf->rect = (unsigned int*)img; 00160 m_imbuf->rect = m_image; 00161 IMB_rectblend(m_imbuf, tmpbuf, x, y, 0, 0, width, height, (IMB_BlendMode)mode); 00162 // remove so that MB_freeImBuf will free our buffer 00163 m_imbuf->rect = NULL; 00164 tmpbuf->rect = NULL; 00165 IMB_freeImBuf(tmpbuf); 00166 } 00167 00168 void ImageBuff::plot (ImageBuff* img, short x, short y, short mode) 00169 { 00170 if (m_size[0] == 0 || m_size[1] == 0 || img->m_size[0] == 0 || img->m_size[1] == 0) 00171 return; 00172 00173 if (!m_imbuf) { 00174 // allocate most basic imbuf, we will assign the rect buffer on the fly 00175 m_imbuf = IMB_allocImBuf(m_size[0], m_size[1], 0, 0); 00176 } 00177 if (!img->m_imbuf) { 00178 // allocate most basic imbuf, we will assign the rect buffer on the fly 00179 img->m_imbuf = IMB_allocImBuf(img->m_size[0], img->m_size[1], 0, 0); 00180 } 00181 // assign temporarily our buffer to the ImBuf buffer, we use the same format 00182 img->m_imbuf->rect = img->m_image; 00183 m_imbuf->rect = m_image; 00184 IMB_rectblend(m_imbuf, img->m_imbuf, x, y, 0, 0, img->m_imbuf->x, img->m_imbuf->y, (IMB_BlendMode)mode); 00185 // remove so that MB_freeImBuf will free our buffer 00186 m_imbuf->rect = NULL; 00187 img->m_imbuf->rect = NULL; 00188 } 00189 00190 00191 // cast Image pointer to ImageBuff 00192 inline ImageBuff * getImageBuff (PyImage * self) 00193 { return static_cast<ImageBuff*>(self->m_image); } 00194 00195 00196 // python methods 00197 00198 static bool testPyBuffer(Py_buffer* buffer, int width, int height, unsigned int pixsize) 00199 { 00200 if (buffer->itemsize != 1) 00201 { 00202 PyErr_SetString(PyExc_ValueError, "Buffer must be an array of bytes"); 00203 return false; 00204 } 00205 if (buffer->len != width*height*pixsize) 00206 { 00207 PyErr_SetString(PyExc_ValueError, "Buffer hasn't the correct size"); 00208 return false; 00209 } 00210 // multi dimension are ok as long as there is no hole in the memory 00211 Py_ssize_t size = buffer->itemsize; 00212 for (int i=buffer->ndim-1; i>=0 ; i--) 00213 { 00214 if (buffer->suboffsets != NULL && buffer->suboffsets[i] >= 0) 00215 { 00216 PyErr_SetString(PyExc_ValueError, "Buffer must be of one block"); 00217 return false; 00218 } 00219 if (buffer->strides != NULL && buffer->strides[i] != size) 00220 { 00221 PyErr_SetString(PyExc_ValueError, "Buffer must be of one block"); 00222 return false; 00223 } 00224 if (i > 0) 00225 size *= buffer->shape[i]; 00226 } 00227 return true; 00228 } 00229 00230 static bool testBGLBuffer(Buffer* buffer, int width, int height, unsigned int pixsize) 00231 { 00232 unsigned int size = BGL_typeSize(buffer->type); 00233 for (int i=0; i<buffer->ndimensions; i++) 00234 { 00235 size *= buffer->dimensions[i]; 00236 } 00237 if (size != width*height*pixsize) 00238 { 00239 PyErr_SetString(PyExc_ValueError, "Buffer hasn't the correct size"); 00240 return false; 00241 } 00242 return true; 00243 } 00244 00245 00246 // load image 00247 static PyObject * load (PyImage * self, PyObject * args) 00248 { 00249 // parameters: string image buffer, its size, width, height 00250 Py_buffer buffer; 00251 Buffer *bglBuffer; 00252 short width; 00253 short height; 00254 unsigned int pixSize; 00255 00256 // calc proper buffer size 00257 // use pixel size from filter 00258 if (self->m_image->getFilter() != NULL) 00259 pixSize = self->m_image->getFilter()->m_filter->firstPixelSize(); 00260 else 00261 pixSize = defFilter.firstPixelSize(); 00262 00263 // parse parameters 00264 if (!PyArg_ParseTuple(args, "s*hh:load", &buffer, &width, &height)) 00265 { 00266 PyErr_Clear(); 00267 // check if it is BGL buffer 00268 if (!PyArg_ParseTuple(args, "O!hh:load", &BGL_bufferType, &bglBuffer, &width, &height)) 00269 { 00270 // report error 00271 return NULL; 00272 } 00273 else 00274 { 00275 if (testBGLBuffer(bglBuffer, width, height, pixSize)) 00276 { 00277 try 00278 { 00279 // if correct, load image 00280 getImageBuff(self)->load((unsigned char*)bglBuffer->buf.asvoid, width, height); 00281 } 00282 catch (Exception & exp) 00283 { 00284 exp.report(); 00285 } 00286 } 00287 } 00288 } 00289 else 00290 { 00291 // check if buffer size is correct 00292 if (testPyBuffer(&buffer, width, height, pixSize)) 00293 { 00294 try 00295 { 00296 // if correct, load image 00297 getImageBuff(self)->load((unsigned char*)buffer.buf, width, height); 00298 } 00299 catch (Exception & exp) 00300 { 00301 exp.report(); 00302 } 00303 } 00304 PyBuffer_Release(&buffer); 00305 } 00306 if (PyErr_Occurred()) 00307 return NULL; 00308 Py_RETURN_NONE; 00309 } 00310 00311 static PyObject * plot (PyImage * self, PyObject * args) 00312 { 00313 PyImage * other; 00314 Buffer* bglBuffer; 00315 Py_buffer buffer; 00316 //unsigned char * buff; 00317 //unsigned int buffSize; 00318 short width; 00319 short height; 00320 short x, y; 00321 short mode = IMB_BLEND_COPY; 00322 00323 if (PyArg_ParseTuple(args, "s*hhhh|h:plot", &buffer, &width, &height, &x, &y, &mode)) 00324 { 00325 // correct decoding, verify that buffer size is correct 00326 // we need a continous memory buffer 00327 if (testPyBuffer(&buffer, width, height, 4)) 00328 { 00329 getImageBuff(self)->plot((unsigned char*)buffer.buf, width, height, x, y, mode); 00330 } 00331 PyBuffer_Release(&buffer); 00332 if (PyErr_Occurred()) 00333 return NULL; 00334 Py_RETURN_NONE; 00335 } 00336 PyErr_Clear(); 00337 // try the other format 00338 if (PyArg_ParseTuple(args, "O!hh|h:plot", &ImageBuffType, &other, &x, &y, &mode)) 00339 { 00340 getImageBuff(self)->plot(getImageBuff(other), x, y, mode); 00341 Py_RETURN_NONE; 00342 } 00343 PyErr_Clear(); 00344 // try the last format (BGL buffer) 00345 if (!PyArg_ParseTuple(args, "O!hhhh|h:plot", &BGL_bufferType, &bglBuffer, &width, &height, &x, &y, &mode)) 00346 { 00347 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"); 00348 return NULL; 00349 } 00350 if (testBGLBuffer(bglBuffer, width, height, 4)) 00351 { 00352 getImageBuff(self)->plot((unsigned char*)bglBuffer->buf.asvoid, width, height, x, y, mode); 00353 } 00354 if (PyErr_Occurred()) 00355 return NULL; 00356 Py_RETURN_NONE; 00357 } 00358 00359 // methods structure 00360 static PyMethodDef imageBuffMethods[] = 00361 { 00362 {"load", (PyCFunction)load, METH_VARARGS, "Load image from buffer"}, 00363 {"plot", (PyCFunction)plot, METH_VARARGS, "update image buffer"}, 00364 {NULL} 00365 }; 00366 // attributes structure 00367 static PyGetSetDef imageBuffGetSets[] = 00368 { // attributes from ImageBase class 00369 {(char*)"valid", (getter)Image_valid, NULL, (char*)"bool to tell if an image is available", NULL}, 00370 {(char*)"image", (getter)Image_getImage, NULL, (char*)"image data", NULL}, 00371 {(char*)"size", (getter)Image_getSize, NULL, (char*)"image size", NULL}, 00372 {(char*)"scale", (getter)Image_getScale, (setter)Image_setScale, (char*)"fast scale of image (near neighbour)", NULL}, 00373 {(char*)"flip", (getter)Image_getFlip, (setter)Image_setFlip, (char*)"flip image vertically", NULL}, 00374 {(char*)"filter", (getter)Image_getFilter, (setter)Image_setFilter, (char*)"pixel filter", NULL}, 00375 {NULL} 00376 }; 00377 00378 00379 // define python type 00380 PyTypeObject ImageBuffType = 00381 { 00382 PyVarObject_HEAD_INIT(NULL, 0) 00383 "VideoTexture.ImageBuff", /*tp_name*/ 00384 sizeof(PyImage), /*tp_basicsize*/ 00385 0, /*tp_itemsize*/ 00386 (destructor)Image_dealloc, /*tp_dealloc*/ 00387 0, /*tp_print*/ 00388 0, /*tp_getattr*/ 00389 0, /*tp_setattr*/ 00390 0, /*tp_compare*/ 00391 0, /*tp_repr*/ 00392 0, /*tp_as_number*/ 00393 0, /*tp_as_sequence*/ 00394 0, /*tp_as_mapping*/ 00395 0, /*tp_hash */ 00396 0, /*tp_call*/ 00397 0, /*tp_str*/ 00398 0, /*tp_getattro*/ 00399 0, /*tp_setattro*/ 00400 &imageBufferProcs, /*tp_as_buffer*/ 00401 Py_TPFLAGS_DEFAULT, /*tp_flags*/ 00402 "Image source from image buffer", /* tp_doc */ 00403 0, /* tp_traverse */ 00404 0, /* tp_clear */ 00405 0, /* tp_richcompare */ 00406 0, /* tp_weaklistoffset */ 00407 0, /* tp_iter */ 00408 0, /* tp_iternext */ 00409 imageBuffMethods, /* tp_methods */ 00410 0, /* tp_members */ 00411 imageBuffGetSets, /* tp_getset */ 00412 0, /* tp_base */ 00413 0, /* tp_dict */ 00414 0, /* tp_descr_get */ 00415 0, /* tp_descr_set */ 00416 0, /* tp_dictoffset */ 00417 (initproc)ImageBuff_init, /* tp_init */ 00418 0, /* tp_alloc */ 00419 Image_allocNew, /* tp_new */ 00420 }; 00421