Blender  V2.59
ImageViewport.cpp
Go to the documentation of this file.
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 };