PySide Bugzilla Closed for New Bugs

PySide is now a Qt Add-on and uses the Qt Project's JIRA Bug Tracker instead of this Bugzilla instance. This Bugzilla is left for reference purposes.

Bug 565 - QImage missing *data constructors
: QImage missing *data constructors
Status: CLOSED FIXED
Product: PySide
Classification: Unclassified
Component: QtGui
: HEAD
: All All
: P3 normal
Assigned To: Hugo Parente Lima
:
:
:
  Show dependency treegraph
 
Reported: 2010-12-22 19:14 EET by Daniel Ashbrook
Modified: 2011-02-02 15:46 EET (History)
9 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Daniel Ashbrook 2010-12-22 19:14:40 EET
QImage has several constructors that take data as input:

QImage(uchar * data, int width, int height, Format format)
QImage(const uchar * data, int width, int height, Format format)
QImage(uchar * data, int width, int height, int bytesPerLine, Format format)
QImage(const uchar * data, int width, int height, int bytesPerLine, Format
format)
QImage(const char * const[] xpm)

however, the only supported constructors in PySide are:

PySide.QtGui.QImage()
PySide.QtGui.QImage(PySide.QtGui.QImage)
PySide.QtGui.QImage(PySide.QtCore.QSize, PySide.QtGui.QImage.Format)
PySide.QtGui.QImage(QString, str = None)
PySide.QtGui.QImage(int, int, PySide.QtGui.QImage.Format)

Given a large amount of image data in Python, it should be supported to create
a QImage based on this data, rather than the extremely slow process of looping
through a blank QImage and using setPixel().

The Python Imaging Library has a function to convert its format to a QImage
(unfortunately a PyQt.QImage rather than a PySide.QImage):

http://www.pythonware.com/library/pil/handbook/imageqt.htm

which may provide some inspiration to more generic functionality for PySide.
Comment 1 Matti Airas 2010-12-23 06:49:38 EET
A very brief look at the bug would suggest this to be a duplicate of bug 489,
which has already been fixed in beta2. Once you get your hands to beta2
packages, could you please verify whether this is the case.

I'm leaving this UNCONFIRMED for now.
Comment 2 Daniel Ashbrook 2010-12-27 15:25:51 EET
This does not seem to be fixed. The TypeError raised with wrong argument types
still only lists

PySide.QtGui.QImage()
PySide.QtGui.QImage(PySide.QtGui.QImage)
PySide.QtGui.QImage(PySide.QtCore.QSize, PySide.QtGui.QImage.Format)
PySide.QtGui.QImage(QString, str = None)
PySide.QtGui.QImage(int, int, PySide.QtGui.QImage.Format)

as valid constructors; trying a QImage(str, int, int, Format) set of arguments
gives

TypeError: PySide.QtGui.QImage(): too many arguments.

This suggests that bug 489 may not be truly fixed?

Note: I used the precompiled OS X binary pyside-1.0.0-beta1-qt47-py26apple.pkg
from http://developer.qt.nokia.com/wiki/PySideBinariesMacOSX .
Comment 3 Matti Airas 2011-01-04 08:49:09 EET
To clarify: did you test this on beta1 or beta2? The bug is expected to occur
with beta1 but not on beta2, because bug 489 was only released in beta2.
Comment 4 Matti Airas 2011-01-18 08:11:00 EET
I'm making this NEW in any case to not keep it in limbo forever. P3.
Comment 5 Kenneth Arnold 2011-01-27 16:01:03 EET
This appears to be incompletely fixed. In PyQt4 we are able to do:

    self.pixels = numpy.zeros((height, width, 4), dtype='uint8')
    self.img = QImage(self.pixels, width, height, QImage.Format_RGB32)

Then each time self.img is painted, it gets the new contents of self.pixels.
This is very important for performance since it removes the need to call
setPixel for each point for each frame, or even packing the image data into a
string and then having QImage unpack it.

Instead, PySide HEAD gives me:

TypeError: 'PySide.QtGui.QImage' called with wrong argument types:
  PySide.QtGui.QImage(numpy.ndarray, int, int, Format)
Supported signatures:
  PySide.QtGui.QImage()
  PySide.QtGui.QImage(PySide.QtGui.QImage)
  PySide.QtGui.QImage(PySide.QtCore.QSize, PySide.QtGui.QImage.Format)
  PySide.QtGui.QImage(QString, str = None)
  PySide.QtGui.QImage(uchar, int, int, PySide.QtGui.QImage.Format)
  PySide.QtGui.QImage(uchar, int, int, int, PySide.QtGui.QImage.Format)
  PySide.QtGui.QImage(int, int, PySide.QtGui.QImage.Format)

By comparison, when I force the PyQt version to fail (by passing `object()`
instead of self.pixels), I get:

TypeError: arguments did not match any overloaded call:
  QImage(): too many arguments
  QImage(QSize, QImage.Format): argument 1 has unexpected type 'object'
  QImage(int, int, QImage.Format): argument 1 has unexpected type 'object'
  QImage(str, int, int, QImage.Format): argument 1 has unexpected type 'object'
  QImage(sip.voidptr, int, int, QImage.Format): argument 1 has unexpected type
'object'
  QImage(str, int, int, int, QImage.Format): argument 1 has unexpected type
'object'
  QImage(sip.voidptr, int, int, int, QImage.Format): argument 1 has unexpected
type 'object'
  QImage(list-of-str): argument 1 has unexpected type 'object'
  QImage(QString, str format=None): argument 1 has unexpected type 'object'
  QImage(QImage): argument 1 has unexpected type 'object'
  QImage(QVariant): too many arguments

Notice that PyQt offers a 'voidptr' type, which accounts for both actual Python
strings and buffer-like things such as numpy arrays. The right solution for
both this bug and #566 would be to have a voidptr-like type that wraps things
with the Python buffer interface. When returning one from C++, it should
support the buffer interface on the Python side as well.

I'm working around this for now by making a new QImage(pixels.asstring(), ...)
for each frame, but that's a performance hit.
Comment 6 Hugo Parente Lima 2011-01-27 16:47:17 EET
Hi Kenneth Arnold, I'm working on this bug right now, among with other QImage
issues like the lack of bits(), constBits(), scanLine() and constScanLine()
methods, i.e. all methods that return internal buffers.

The problem that the previous fix to QImage(uchar,...) constructor copies the
data isntead of using it as is like the QImage documentation says.

I think all can be solved using Python buffers, the only requirement are that
the memory pointed by the buffer must be contiguous, but it'll be fast,
flexible =].
Comment 7 Hugo Parente Lima 2011-01-31 14:48:26 EET
Fixed in commit:
pyside/2a4391902406552815140f4ebe078f9f7e9a955c

The constructors now accepts any PyObject which implements the buffer protocol,
as the C++ and PyQt4 version the buffer must be alive during the life time of
QImage because QImage *does not* copy the image data.
Comment 8 renato filho 2011-02-02 15:46:05 EET
released on beta 5