Fix bug 565 - "QImage missing *data constructors"
Fix bug 566 - "'PySide.QtGui.QImage' object has no attribute 'scanLine'" 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. scanLine() and bits() now return buffer objects pointing to the memory inside QImage.
This commit is contained in:
parent
9c7d055f3d
commit
279fb02429
2 changed files with 84 additions and 32 deletions
|
|
@ -722,45 +722,85 @@
|
||||||
<modify-function signature="QImage(const char *, const char *)" remove="all" />
|
<modify-function signature="QImage(const char *, const char *)" remove="all" />
|
||||||
<modify-function signature="QImage(const char **)" remove="all" />
|
<modify-function signature="QImage(const char **)" remove="all" />
|
||||||
|
|
||||||
<template name="QImageStringBufferConversionRule">
|
<template name="qimage_buffer_constructor">
|
||||||
const uchar* %out = reinterpret_cast<const uchar*>(PyString_AS_STRING(%PYARG_1));
|
PyTypeObject* pyType = reinterpret_cast<PyTypeObject*>(%PYARG_1->ob_type);
|
||||||
|
if (pyType->tp_as_buffer
|
||||||
|
&& pyType->tp_as_buffer->bf_getreadbuffer
|
||||||
|
&& pyType->tp_as_buffer->bf_getsegcount(%PYARG_1, 0) == 1) {
|
||||||
|
void* ptr;
|
||||||
|
pyType->tp_as_buffer->bf_getreadbuffer(%PYARG_1, 0, &ptr);
|
||||||
|
%0 = new %TYPE((uchar*)ptr, %ARGS);
|
||||||
|
} else {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "The object must support buffer protocol with just one segment.");
|
||||||
|
}
|
||||||
</template>
|
</template>
|
||||||
|
<modify-function signature="QImage(uchar *,int,int,int,QImage::Format)">
|
||||||
<modify-function signature="QImage(uchar *,int,int,int,QImage::Format)" remove="all"/>
|
|
||||||
<modify-function signature="QImage(const uchar*,int,int,int,QImage::Format)">
|
|
||||||
<modify-argument index="1">
|
<modify-argument index="1">
|
||||||
<replace-type modified-type="const char*"/>
|
<replace-type modified-type="PyObject"/>
|
||||||
<conversion-rule class="native">
|
|
||||||
<insert-template name="QImageStringBufferConversionRule"/>
|
|
||||||
</conversion-rule>
|
|
||||||
</modify-argument>
|
</modify-argument>
|
||||||
|
<inject-code>
|
||||||
|
<insert-template name="qimage_buffer_constructor">
|
||||||
|
<replace from="%ARGS" to="%2, %3, %4, %5" />
|
||||||
|
</insert-template>
|
||||||
|
</inject-code>
|
||||||
</modify-function>
|
</modify-function>
|
||||||
<modify-function signature="bits()const" remove="all" />
|
<modify-function signature="QImage(uchar*,int,int,QImage::Format)">
|
||||||
<modify-function signature="scanLine(int)const" remove="all" />
|
|
||||||
|
|
||||||
<modify-function signature="QImage(uchar*,int,int,QImage::Format)" remove="all" />
|
|
||||||
<modify-function signature="QImage(const uchar *, int, int, QImage::Format)">
|
|
||||||
<modify-argument index="1">
|
<modify-argument index="1">
|
||||||
<replace-type modified-type="const char*"/>
|
<replace-type modified-type="PyObject"/>
|
||||||
<conversion-rule class="native">
|
|
||||||
<insert-template name="QImageStringBufferConversionRule"/>
|
|
||||||
</conversion-rule>
|
|
||||||
</modify-argument>
|
</modify-argument>
|
||||||
|
<inject-code>
|
||||||
|
<insert-template name="qimage_buffer_constructor">
|
||||||
|
<replace from="%ARGS" to="%2, %3, %4" />
|
||||||
|
</insert-template>
|
||||||
|
</inject-code>
|
||||||
</modify-function>
|
</modify-function>
|
||||||
|
|
||||||
|
<!-- The non-const versions are already used -->
|
||||||
|
<modify-function signature="QImage(const uchar*,int,int,int,QImage::Format)" remove="all"/>
|
||||||
|
<modify-function signature="QImage(const uchar *, int, int, QImage::Format)" remove="all" />
|
||||||
|
|
||||||
|
|
||||||
<modify-function signature="loadFromData(const uchar*,int,const char*)" remove="all" />
|
<modify-function signature="loadFromData(const uchar*,int,const char*)" remove="all" />
|
||||||
|
<!-- Functions removed because we already have overloads using QString -->
|
||||||
<modify-function signature="setText(const char*,const char*,QString)" remove="all" />
|
<modify-function signature="setText(const char*,const char*,QString)" remove="all" />
|
||||||
<modify-function signature="text(const char*,const char*)const" remove="all" />
|
<modify-function signature="text(const char*,const char*)const" remove="all" />
|
||||||
|
<!--### Obsolete in 4.3-->
|
||||||
<modify-function signature="serialNumber()const" remove="all"/>
|
<modify-function signature="serialNumber()const" remove="all"/>
|
||||||
<!--### Obsolete in 4.3-->
|
|
||||||
<modify-function signature="textLanguages()const" remove="all"/>
|
<modify-function signature="textLanguages()const" remove="all"/>
|
||||||
<!--### Obsolete in 4.3-->
|
|
||||||
<modify-function signature="QImage(const char**)" remove="all"/>
|
<modify-function signature="QImage(const char**)" remove="all"/>
|
||||||
<modify-function signature="setColorTable(const QVector<uint>)" remove="all"/>
|
<!--### end of obsolete section -->
|
||||||
<modify-function signature="loadFromData(const uchar *,int,const char *)" remove="all"/>
|
<modify-function signature="loadFromData(const uchar *,int,const char *)" remove="all"/>
|
||||||
<modify-function signature="fromData(const uchar *,int,const char *)" remove="all"/>
|
<modify-function signature="fromData(const uchar *,int,const char *)" remove="all"/>
|
||||||
<modify-function signature="bits()" remove="all"/>
|
|
||||||
<modify-function signature="scanLine(int)" remove="all"/>
|
<modify-function signature="constBits()const" since="4.7">
|
||||||
|
<inject-code>
|
||||||
|
%PYARG_0 = PyBuffer_FromMemory(const_cast<uchar*>(%CPPSELF.%FUNCTION_NAME()), %CPPSELF.byteCount());
|
||||||
|
</inject-code>
|
||||||
|
</modify-function>
|
||||||
|
<modify-function signature="bits()">
|
||||||
|
<inject-code>
|
||||||
|
// byteCount() is only available on Qt4.7, so we use bytesPerLine * height
|
||||||
|
%PYARG_0 = PyBuffer_FromReadWriteMemory(%CPPSELF.%FUNCTION_NAME(), %CPPSELF.bytesPerLine() * %CPPSELF.height());
|
||||||
|
</inject-code>
|
||||||
|
</modify-function>
|
||||||
|
<modify-function signature="constScanLine(int)const" since="4.7">
|
||||||
|
<inject-code>
|
||||||
|
%PYARG_0 = PyBuffer_FromMemory(const_cast<uchar*>(%CPPSELF.%FUNCTION_NAME(%1)), %CPPSELF.bytesPerLine());
|
||||||
|
</inject-code>
|
||||||
|
</modify-function>
|
||||||
|
<modify-function signature="scanLine(int)">
|
||||||
|
<inject-code>
|
||||||
|
%PYARG_0 = PyBuffer_FromReadWriteMemory(%CPPSELF.%FUNCTION_NAME(%1), %CPPSELF.bytesPerLine());
|
||||||
|
</inject-code>
|
||||||
|
</modify-function>
|
||||||
|
<!--
|
||||||
|
Only the non-const version of bits() and scanLine() is exported to Python
|
||||||
|
If the user don't want to detach the QImage data he must use constBits or constScanLine
|
||||||
|
as Python doesn't have the concept of constness.
|
||||||
|
-->
|
||||||
|
<modify-function signature="bits()const" remove="all"/>
|
||||||
|
<modify-function signature="scanLine(int)const" remove="all"/>
|
||||||
|
|
||||||
<modify-function signature="invertPixels(QImage::InvertMode)">
|
<modify-function signature="invertPixels(QImage::InvertMode)">
|
||||||
<modify-argument index="1">
|
<modify-argument index="1">
|
||||||
<rename to="mode"/>
|
<rename to="mode"/>
|
||||||
|
|
|
||||||
|
|
@ -2,18 +2,30 @@
|
||||||
'''Test cases for QImage'''
|
'''Test cases for QImage'''
|
||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
|
from PySide.QtGui import *
|
||||||
from PySide.QtGui import QImage
|
from helper import *
|
||||||
|
|
||||||
from helper import UsesQApplication
|
|
||||||
|
|
||||||
class QImageTest(UsesQApplication):
|
class QImageTest(UsesQApplication):
|
||||||
'''Test case for calling setPixel with float as argument'''
|
'''Test case for calling setPixel with float as argument'''
|
||||||
|
|
||||||
def testQImageStringBuffer(self):
|
def testQImageStringBuffer(self):
|
||||||
'''Test if the QImage signatures receiving string buffers exist.'''
|
'''Test if the QImage signatures receiving string buffers exist.'''
|
||||||
img0 = QImage('', 100, 100, QImage.Format_ARGB32)
|
img0 = QImage(adjust_filename('sample.png', __file__))
|
||||||
img1 = QImage('', 100, 100, 0, QImage.Format_ARGB32)
|
|
||||||
|
print type(img0.bits())
|
||||||
|
|
||||||
|
# btw let's test the bits() method
|
||||||
|
img1 = QImage(img0.bits(), img0.width(), img0.height(), img0.format())
|
||||||
|
self.assertEqual(img0, img1)
|
||||||
|
img2 = QImage(img0.bits(), img0.width(), img0.height(), img0.bytesPerLine(), img0.format())
|
||||||
|
self.assertEqual(img0, img2)
|
||||||
|
|
||||||
|
## test scanLine method
|
||||||
|
data1 = img0.scanLine(0)
|
||||||
|
data2 = img1.scanLine(0)
|
||||||
|
self.assertEqual(data1, data2)
|
||||||
|
self.assertEquals(str(data1), img0.bits()[:img0.bytesPerLine()])
|
||||||
|
self.assertEquals(str(data2), img0.bits()[:img0.bytesPerLine()])
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue