PyQt and QImage.scanLine()

As we can see from the documentation QImage.scanLine() returns sip.voidptr object. But how to get pixels colors from this object? Reading sip documentation tells us that it has asstring(length) method, which returns length bytes from sip.voidptr position. Ok, that's enough to get colors pixel by pixel.

Let's see an example:

import struct;
from PyQt4 import QtGui;

# get QImage object
# ...
img = img.convertToFormat(QtGui.QImage.Format_RGB32);
width = img.width();
height = img.height();

linebytes = width * 4;
for y in xrange(0, height):
    pixels = img.scanLine(y).asstring(linebytes);
    for x in xrange(0, width):
        # unpack 32 bit integer
        color = struct.unpack('I', pixels[x*4:x*4+4])[0];
        # here it is
        r = QtGui.qRed(color);
        g = QtGui.qGreen(color);
        b = QtGui.qBlue(color);

Comments (3)

loïc botrel says:
Fri, 12 Jul 2013
Thanks a lot, this is one of the rare python examples for a proper use of the scanline function.
In addition, I presume Format_ARGB32 (0xAARRGGBB)could be used because it matches with RGB32 (0xffRRGGBB) in the QImage Format reference.

linebytes can be found by img.bytesPerLine()

I would appreciate if you had an optimised function to dynamicall change the pixels (a grayscale function for example).

Andrew says:
Thu, 11 Dec 2014
How would this be done with an 8bit QImage?

The unpacking has me totally lost.
Oleg says:
Fri, 19 Dec 2014
Andrew: this should be struct.unpack('B', pixels[x*1:x*1+1]) and don't forget to replace 4 with 1 everywhere

Add comment

Fields marked * are required.
This form has a bot protection mechanism, that requires Cookies.
Please, don't disable them.


Paragraphs are created automatically. Available tags: [quote], [code].