static void Bitmap_setPixels(Bitmap& bitmap, PyObject* exporter) { Py_buffer bufferView; // PyObject_Print(PyObject_Type(exporter), stderr, 0); if (PyObject_CheckBuffer(exporter)) { PyObject_GetBuffer(exporter, &bufferView, PyBUF_READ); const unsigned char* pBuf = reinterpret_cast<unsigned char*>(bufferView.buf); bitmap.setPixels(pBuf); PyBuffer_Release(&bufferView); } else if (PyBuffer_Check(exporter)) { PyTypeObject * pType = exporter->ob_type; PyBufferProcs * pProcs = pType->tp_as_buffer; AVG_ASSERT(pProcs); Py_ssize_t numBytes; Py_ssize_t numSegments = pProcs->bf_getsegcount(exporter, &numBytes); if (numBytes != bitmap.getMemNeeded()) { throw Exception(AVG_ERR_INVALID_ARGS, "Second parameter to Bitmap.setPixels must fit bitmap size."); } // TODO: check if bitmap size is correct unsigned char* pDestPixels = bitmap.getPixels(); for (unsigned i=0; i<numSegments; ++i) { void* pSrcPixels; long bytesInSegment = pProcs->bf_getreadbuffer(exporter, i, &pSrcPixels); memcpy(pDestPixels, pSrcPixels, bytesInSegment); pDestPixels += bytesInSegment; } } else { throw Exception(AVG_ERR_INVALID_ARGS, "Second parameter to Bitmap.setPixels must support the buffer interface."); } }
Py_ssize_t PyBuffer_GetMemory(PyObject* buffer, const char** pp) { PyBufferProcs* procs = buffer->ob_type->tp_as_buffer; if (!procs || !PyType_HasFeature(buffer->ob_type, Py_TPFLAGS_HAVE_GETCHARBUFFER)) { // Can't access the memory directly because the buffer object doesn't support it. return -1; } if (procs->bf_getsegcount(buffer, 0) != 1) { // Can't access the memory directly because there is more than one segment. return -1; } #if PY_VERSION_HEX >= 0x02050000 char* pT = 0; #else const char* pT = 0; #endif Py_ssize_t cb = procs->bf_getcharbuffer(buffer, 0, &pT); if (pp) *pp = pT; return cb; }
static Py_ssize_t get_buffer(PyObject *obj, unsigned char **buf_p, PyObject **tmp_obj_p) { PyBufferProcs *bfp; PyObject *str = NULL; Py_ssize_t res; /* check for None */ if (obj == Py_None) { PyErr_Format(PyExc_TypeError, "None is not allowed"); return -1; } /* is string or unicode ? */ if (PyString_Check(obj) || PyUnicode_Check(obj)) { if (PyString_AsStringAndSize(obj, (char**)buf_p, &res) < 0) return -1; return res; } /* try to get buffer */ bfp = obj->ob_type->tp_as_buffer; if (bfp && bfp->bf_getsegcount && bfp->bf_getreadbuffer) { if (bfp->bf_getsegcount(obj, NULL) == 1) return bfp->bf_getreadbuffer(obj, 0, (void**)buf_p); } /* * Not a string-like object, run str() or it. */ /* are we in recursion? */ if (tmp_obj_p == NULL) { PyErr_Format(PyExc_TypeError, "Cannot convert to string - get_buffer() recusively failed"); return -1; } /* do str() then */ str = PyObject_Str(obj); res = -1; if (str != NULL) { res = get_buffer(str, buf_p, NULL); if (res >= 0) { *tmp_obj_p = str; } else { Py_CLEAR(str); } } return res; }
// Convert the Python values to a raw array. static void *convert_values(Array *array, PyObject *values, GLenum gl_type, sipErrorState *estate) { #if PY_VERSION_HEX >= 0x02060300 int rc = sipGetBufferInfo(values, &array->buffer); if (rc < 0) { *estate = sipErrorFail; return 0; } if (rc > 0) { // Check the buffer is compatible with what we need. GLenum array_type; switch (*array->buffer.bi_format) { case 'b': array_type = GL_BYTE; break; case 'B': array_type = GL_UNSIGNED_BYTE; break; case 'h': array_type = GL_SHORT; break; case 'H': array_type = GL_UNSIGNED_SHORT; break; case 'i': array_type = GL_INT; break; case 'I': array_type = GL_UNSIGNED_INT; break; case 'f': array_type = GL_FLOAT; break; #if defined(SIP_FEATURE_PyQt_Desktop_OpenGL) case 'd': array_type = GL_DOUBLE; break; #endif default: PyErr_Format(PyExc_TypeError, "unsupported buffer type '%s'", array->buffer.bi_format); *estate = sipErrorFail; return 0; } if (array_type != gl_type) { PyErr_SetString(PyExc_TypeError, "the buffer type is not the same as the array type"); *estate = sipErrorFail; return 0; } return array->buffer.bi_buf; } #else PyBufferProcs *bf = Py_TYPE(values)->tp_as_buffer; if (bf && bf->bf_getreadbuffer && bf->bf_getsegcount) { if (bf->bf_getsegcount(values, 0) != 1) { PyErr_SetString(PyExc_TypeError, "single-segment buffer object expected"); *estate = sipErrorFail; return 0; } if (bf->bf_getreadbuffer(values, 0, reinterpret_cast<void **>(&array)) < 0) { *estate = sipErrorFail; return 0; } Py_INCREF(values); array->buffer = values; return array; } #endif PyObject *seq = PySequence_Fast(values, "array must be a sequence or a buffer"); if (!seq) { *estate = sipErrorContinue; return 0; } Py_ssize_t nr_items = Sequence_Fast_Size(seq); if (nr_items < 1) { Py_DECREF(seq); PyErr_SetString(PyExc_TypeError, "array must have at least one element"); *estate = sipErrorFail; return 0; } void (*convertor)(PyObject *, void *, Py_ssize_t); size_t element_size; switch (gl_type) { case GL_BYTE: convertor = convert_byte; element_size = sizeof (GLbyte); break; case GL_UNSIGNED_BYTE: convertor = convert_ubyte; element_size = sizeof (GLubyte); break; case GL_SHORT: convertor = convert_short; element_size = sizeof (GLshort); break; case GL_UNSIGNED_SHORT: convertor = convert_ushort; element_size = sizeof (GLushort); break; case GL_INT: convertor = convert_int; element_size = sizeof (GLint); break; case GL_UNSIGNED_INT: convertor = convert_uint; element_size = sizeof (GLuint); break; case GL_FLOAT: convertor = convert_float; element_size = sizeof (GLfloat); break; #if defined(SIP_FEATURE_PyQt_Desktop_OpenGL) #if GL_DOUBLE != GL_FLOAT case GL_DOUBLE: convertor = convert_double; element_size = sizeof (GLdouble); break; #endif #endif default: Py_DECREF(seq); PyErr_SetString(PyExc_TypeError, "unsupported GL element type"); *estate = sipErrorFail; return 0; } void *data = sipMalloc(nr_items * element_size); if (!data) { Py_DECREF(seq); *estate = sipErrorFail; return 0; } for (Py_ssize_t i = 0; i < nr_items; ++i) { PyErr_Clear(); convertor(Sequence_Fast_GetItem(seq, i), data, i); if (PyErr_Occurred()) { sipFree(data); Py_DECREF(seq); *estate = sipErrorFail; return 0; } } Py_DECREF(seq); array->data = data; return data; }