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