Blender V2.61 - r43446

ImageViewport.cpp

Go to the documentation of this file.
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 };