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 // implementation 00028 00029 #include <PyObjectPlus.h> 00030 #include <structmember.h> 00031 00032 #include "GL/glew.h" 00033 00034 #include "Texture.h" 00035 #include "ImageBase.h" 00036 #include "FilterSource.h" 00037 #include "ImageViewport.h" 00038 00039 00040 // constructor 00041 ImageViewport::ImageViewport (void) : m_alpha(false), m_texInit(false) 00042 { 00043 // get viewport rectangle 00044 glGetIntegerv(GL_VIEWPORT, m_viewport); 00045 // create buffer for viewport image 00046 m_viewportImage = new BYTE [4 * getViewportSize()[0] * getViewportSize()[1]]; 00047 // set attributes 00048 setWhole(false); 00049 } 00050 00051 // destructor 00052 ImageViewport::~ImageViewport (void) 00053 { delete m_viewportImage; } 00054 00055 00056 // use whole viewport to capture image 00057 void ImageViewport::setWhole (bool whole) 00058 { 00059 // set whole 00060 m_whole = whole; 00061 // set capture size to viewport size, if whole, 00062 // otherwise place area in the middle of viewport 00063 for (int idx = 0; idx < 2; ++idx) 00064 { 00065 // capture size 00066 m_capSize[idx] = whole ? short(getViewportSize()[idx]) 00067 : calcSize(short(getViewportSize()[idx])); 00068 // position 00069 m_position[idx] = whole ? 0 : ((getViewportSize()[idx] - m_capSize[idx]) >> 1); 00070 } 00071 // init image 00072 init(m_capSize[0], m_capSize[1]); 00073 // set capture position 00074 setPosition(); 00075 } 00076 00077 void ImageViewport::setCaptureSize (short * size) 00078 { 00079 m_whole = false; 00080 if (size == NULL) 00081 size = m_capSize; 00082 for (int idx = 0; idx < 2; ++idx) 00083 { 00084 if (size[idx] < 1) 00085 m_capSize[idx] = 1; 00086 else if (size[idx] > getViewportSize()[idx]) 00087 m_capSize[idx] = short(getViewportSize()[idx]); 00088 else 00089 m_capSize[idx] = size[idx]; 00090 } 00091 init(m_capSize[0], m_capSize[1]); 00092 // set capture position 00093 setPosition(); 00094 } 00095 00096 // set position of capture rectangle 00097 void ImageViewport::setPosition (GLint * pos) 00098 { 00099 // if new position is not provided, use existing position 00100 if (pos == NULL) pos = m_position; 00101 // save position 00102 for (int idx = 0; idx < 2; ++idx) 00103 m_position[idx] = pos[idx] < 0 ? 0 : pos[idx] >= getViewportSize()[idx] 00104 - m_capSize[idx] ? getViewportSize()[idx] - m_capSize[idx] : pos[idx]; 00105 // recalc up left corner 00106 for (int idx = 0; idx < 2; ++idx) 00107 m_upLeft[idx] = m_position[idx] + m_viewport[idx]; 00108 } 00109 00110 00111 // capture image from viewport 00112 void ImageViewport::calcImage (unsigned int texId, double ts) 00113 { 00114 // if scale was changed 00115 if (m_scaleChange) 00116 // reset image 00117 init(m_capSize[0], m_capSize[1]); 00118 // if texture wasn't initialized 00119 if (!m_texInit) 00120 { 00121 // initialize it 00122 loadTexture(texId, m_image, m_size); 00123 m_texInit = true; 00124 } 00125 // if texture can be directly created 00126 if (texId != 0 && m_pyfilter == NULL && m_capSize[0] == calcSize(m_capSize[0]) 00127 && m_capSize[1] == calcSize(m_capSize[1]) && !m_flip) 00128 { 00129 // just copy current viewport to texture 00130 glBindTexture(GL_TEXTURE_2D, texId); 00131 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_upLeft[0], m_upLeft[1], (GLsizei)m_capSize[0], (GLsizei)m_capSize[1]); 00132 // image is not available 00133 m_avail = false; 00134 } 00135 // otherwise copy viewport to buffer, if image is not available 00136 else if (!m_avail) 00137 { 00138 // get frame buffer data 00139 if (m_alpha) 00140 { 00141 glReadPixels(m_upLeft[0], m_upLeft[1], (GLsizei)m_capSize[0], (GLsizei)m_capSize[1], GL_RGBA, 00142 GL_UNSIGNED_BYTE, m_viewportImage); 00143 // filter loaded data 00144 FilterRGBA32 filt; 00145 filterImage(filt, m_viewportImage, m_capSize); 00146 } 00147 else 00148 { 00149 glReadPixels(m_upLeft[0], m_upLeft[1], (GLsizei)m_capSize[0], (GLsizei)m_capSize[1], GL_RGB, 00150 GL_UNSIGNED_BYTE, m_viewportImage); 00151 // filter loaded data 00152 FilterRGB24 filt; 00153 filterImage(filt, m_viewportImage, m_capSize); 00154 } 00155 } 00156 } 00157 00158 00159 00160 // cast Image pointer to ImageViewport 00161 inline ImageViewport * getImageViewport (PyImage * self) 00162 { return static_cast<ImageViewport*>(self->m_image); } 00163 00164 00165 // python methods 00166 00167 00168 // get whole 00169 PyObject * ImageViewport_getWhole (PyImage * self, void * closure) 00170 { 00171 if (self->m_image != NULL && getImageViewport(self)->getWhole()) Py_RETURN_TRUE; 00172 else Py_RETURN_FALSE; 00173 } 00174 00175 // set whole 00176 int ImageViewport_setWhole (PyImage * self, PyObject * value, void * closure) 00177 { 00178 // check parameter, report failure 00179 if (value == NULL || !PyBool_Check(value)) 00180 { 00181 PyErr_SetString(PyExc_TypeError, "The value must be a bool"); 00182 return -1; 00183 } 00184 try 00185 { 00186 // set whole, can throw in case of resize and buffer exports 00187 if (self->m_image != NULL) getImageViewport(self)->setWhole(value == Py_True); 00188 } 00189 catch (Exception & exp) 00190 { 00191 exp.report(); 00192 return -1; 00193 } 00194 // success 00195 return 0; 00196 } 00197 00198 // get alpha 00199 PyObject * ImageViewport_getAlpha (PyImage * self, void * closure) 00200 { 00201 if (self->m_image != NULL && getImageViewport(self)->getAlpha()) Py_RETURN_TRUE; 00202 else Py_RETURN_FALSE; 00203 } 00204 00205 // set whole 00206 int ImageViewport_setAlpha (PyImage * self, PyObject * value, void * closure) 00207 { 00208 // check parameter, report failure 00209 if (value == NULL || !PyBool_Check(value)) 00210 { 00211 PyErr_SetString(PyExc_TypeError, "The value must be a bool"); 00212 return -1; 00213 } 00214 // set alpha 00215 if (self->m_image != NULL) getImageViewport(self)->setAlpha(value == Py_True); 00216 // success 00217 return 0; 00218 } 00219 00220 00221 // get position 00222 static PyObject * ImageViewport_getPosition (PyImage * self, void * closure) 00223 { 00224 return Py_BuildValue("(ii)", getImageViewport(self)->getPosition()[0], 00225 getImageViewport(self)->getPosition()[1]); 00226 } 00227 00228 // set position 00229 static int ImageViewport_setPosition (PyImage * self, PyObject * value, void * closure) 00230 { 00231 // check validity of parameter 00232 if (value == NULL || !PySequence_Check(value) || PySequence_Size(value) != 2 00233 || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 0)) 00234 || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 1))) 00235 { 00236 PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 2 ints"); 00237 return -1; 00238 } 00239 // set position 00240 GLint pos [] = { 00241 GLint(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 0))), 00242 GLint(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 1))) 00243 }; 00244 getImageViewport(self)->setPosition(pos); 00245 // success 00246 return 0; 00247 } 00248 00249 // get capture size 00250 PyObject * ImageViewport_getCaptureSize (PyImage * self, void * closure) 00251 { 00252 return Py_BuildValue("(ii)", getImageViewport(self)->getCaptureSize()[0], 00253 getImageViewport(self)->getCaptureSize()[1]); 00254 } 00255 00256 // set capture size 00257 int ImageViewport_setCaptureSize (PyImage * self, PyObject * value, void * closure) 00258 { 00259 // check validity of parameter 00260 if (value == NULL || !PySequence_Check(value) || PySequence_Size(value) != 2 00261 || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 0)) 00262 || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 1))) 00263 { 00264 PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 2 ints"); 00265 return -1; 00266 } 00267 // set capture size 00268 short size [] = { 00269 short(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 0))), 00270 short(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 1))) 00271 }; 00272 try 00273 { 00274 // can throw in case of resize and buffer exports 00275 getImageViewport(self)->setCaptureSize(size); 00276 } 00277 catch (Exception & exp) 00278 { 00279 exp.report(); 00280 return -1; 00281 } 00282 // success 00283 return 0; 00284 } 00285 00286 00287 // methods structure 00288 static PyMethodDef imageViewportMethods[] = 00289 { // methods from ImageBase class 00290 {"refresh", (PyCFunction)Image_refresh, METH_NOARGS, "Refresh image - invalidate its current content"}, 00291 {NULL} 00292 }; 00293 // attributes structure 00294 static PyGetSetDef imageViewportGetSets[] = 00295 { 00296 {(char*)"whole", (getter)ImageViewport_getWhole, (setter)ImageViewport_setWhole, (char*)"use whole viewport to capture", NULL}, 00297 {(char*)"position", (getter)ImageViewport_getPosition, (setter)ImageViewport_setPosition, (char*)"upper left corner of captured area", NULL}, 00298 {(char*)"capsize", (getter)ImageViewport_getCaptureSize, (setter)ImageViewport_setCaptureSize, (char*)"size of viewport area being captured", NULL}, 00299 {(char*)"alpha", (getter)ImageViewport_getAlpha, (setter)ImageViewport_setAlpha, (char*)"use alpha in texture", NULL}, 00300 // attributes from ImageBase class 00301 {(char*)"valid", (getter)Image_valid, NULL, (char*)"bool to tell if an image is available", NULL}, 00302 {(char*)"image", (getter)Image_getImage, NULL, (char*)"image data", NULL}, 00303 {(char*)"size", (getter)Image_getSize, NULL, (char*)"image size", NULL}, 00304 {(char*)"scale", (getter)Image_getScale, (setter)Image_setScale, (char*)"fast scale of image (near neighbour)", NULL}, 00305 {(char*)"flip", (getter)Image_getFlip, (setter)Image_setFlip, (char*)"flip image vertically", NULL}, 00306 {(char*)"filter", (getter)Image_getFilter, (setter)Image_setFilter, (char*)"pixel filter", NULL}, 00307 {NULL} 00308 }; 00309 00310 00311 // define python type 00312 PyTypeObject ImageViewportType = 00313 { 00314 PyVarObject_HEAD_INIT(NULL, 0) 00315 "VideoTexture.ImageViewport", /*tp_name*/ 00316 sizeof(PyImage), /*tp_basicsize*/ 00317 0, /*tp_itemsize*/ 00318 (destructor)Image_dealloc, /*tp_dealloc*/ 00319 0, /*tp_print*/ 00320 0, /*tp_getattr*/ 00321 0, /*tp_setattr*/ 00322 0, /*tp_compare*/ 00323 0, /*tp_repr*/ 00324 0, /*tp_as_number*/ 00325 0, /*tp_as_sequence*/ 00326 0, /*tp_as_mapping*/ 00327 0, /*tp_hash */ 00328 0, /*tp_call*/ 00329 0, /*tp_str*/ 00330 0, /*tp_getattro*/ 00331 0, /*tp_setattro*/ 00332 &imageBufferProcs, /*tp_as_buffer*/ 00333 Py_TPFLAGS_DEFAULT, /*tp_flags*/ 00334 "Image source from viewport", /* tp_doc */ 00335 0, /* tp_traverse */ 00336 0, /* tp_clear */ 00337 0, /* tp_richcompare */ 00338 0, /* tp_weaklistoffset */ 00339 0, /* tp_iter */ 00340 0, /* tp_iternext */ 00341 imageViewportMethods, /* tp_methods */ 00342 0, /* tp_members */ 00343 imageViewportGetSets, /* tp_getset */ 00344 0, /* tp_base */ 00345 0, /* tp_dict */ 00346 0, /* tp_descr_get */ 00347 0, /* tp_descr_set */ 00348 0, /* tp_dictoffset */ 00349 (initproc)Image_init<ImageViewport>, /* tp_init */ 00350 0, /* tp_alloc */ 00351 Image_allocNew, /* tp_new */ 00352 };