Menu

Direct access to low level data (QImage)?

2012-10-12
2013-04-06
  • Chris Meyer

    Chris Meyer - 2012-10-12

    I'd like to efficiently get access to the 'bits' of a QImage from within Python - something similar to what qimage2ndarray provides for PyQt.

    The equivalent problem is getting r/w access to the data in a QByteArray without copying the data.

    Anyone have any suggestions? Any snippets of code that might be helpful?

     
  • Florian Link

    Florian Link - 2012-10-13

    The wrappers generated by PythonQt do not yet support this.
    The "buffer" object and protocol of Python could be used to provide a view to the internal data,
    but it requires manual wrapping of each of the methods that should return such a buffer object.

    Such wrappers can either be implemented in the typesystem xml files or they can be added by your program
    via decorator slots. This latter allows you to implement your own direct access code without patching PythonQt.
    A decorator slot can simply return a PyObject (e.g. a buffer object) and PythonQt will pass that on to Python directly.

    I did not yet investigate how the buffer objects work exactly, so if you give it a try, it would be nice if you share your results.

    Instead of buffer object you could also directly create a ndarray object and pass it the raw data pointer from the QImage or QByteArray, but that will require linking of numpy into your wrapper code. We actually use this direct way in MeVisLab to provide access to low level image data via ndarray to Python.

     
  • Chris Meyer

    Chris Meyer - 2012-10-30

    Here is code which I've written to return an ndarray object from a Python object. In this case my object is an internal object named 'Data' but 'Data' could easily be replaced by QByteArray or QImage.

    The code:

    static PyObject *dataToPyArray(PyObject * /*self*/, PyObject *args)
    {
        _import_array();
        // Grab the Data object
        PyObject* obj = PyTuple_GET_ITEM(args, 0);
        if (!PyObject_TypeCheck(obj, &PythonQtInstanceWrapper_Type))
            return NULL;
        PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)obj;
        Data *data = static_cast<Data* >(wrap->_obj.data());
        Py_ssize_t dims[1];
        dims[0] = data->length();
        PyObject *result = PyArray_SimpleNewFromData(1, dims, NPY_UINT8, (void *)data->bits());
        PyArray_BASE(result) = obj;
        Py_INCREF(obj);
        return result;
    }
    

    And you register the function like this:

        static PyMethodDef Methods[] = {
            {"dataToPyArray",  dataToPyArray, METH_VARARGS, "dataToPyArray."},
            {NULL, NULL, 0, NULL}        /* Sentinel */
        };
        (void) Py_InitModule("MyLibrary", Methods);
    
     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.