4

I need to access the pixel data in a qimage object with PyQt4.

The .pixel() is too slow so the docs say to use the scanline() method.

In c++ I can get the pointer returned by the scanline() method and read/write the pixel RGB value from the buffer.

With Python I get the SIP voidptr object that points to the pixels buffer so I can only read the pixel RGB value using bytearray but I cannot change the value in the original pointer.

Any suggestions?

risinglf
  • 41
  • 1
  • 2

1 Answers1

8

Here are some examples:

from PyQt4 import QtGui, QtCore
img = QtGui.QImage(100, 100, QtGui.QImage.Format_ARGB32)
img.fill(0xdeadbeef)

ptr = img.bits()
ptr.setsize(img.byteCount())

## copy the data out as a string
strData = ptr.asstring()

## get a read-only buffer to access the data
buf = buffer(ptr, 0, img.byteCount())

## view the data as a read-only numpy array
import numpy as np
arr = np.frombuffer(buf, dtype=np.ubyte).reshape(img.height(), img.width(), 4)

## view the data as a writable numpy array
arr = np.asarray(ptr).reshape(img.height(), img.width(), 4)
Tobias Kienzler
  • 25,759
  • 22
  • 127
  • 221
Luke
  • 11,374
  • 2
  • 48
  • 61
  • Good question; added another answer to the list. – Luke Sep 06 '12 at 21:07
  • 1
    Dude, you can't imagine how long I was googling how to do that. Huge thanks. Worth saying that the last line creates a view, not a copy into the data. If somebody wants to create a copy of QImage, call `.copy()` on array. Plus, keep an eye on format. I needed to get RGB, thus calling something like `arr[:, :, [0, 2]] = arr[:, :, [2, 0]]` helped – Alexander Serikov Mar 16 '19 at 22:07
  • Very nice solution. In python 3.6 and PySide6, `setsize`, `byteCount`, `asstring` and `buffer` are not available. One might need to use `img.bytePerLine() * img.height()` and `memoryview` instead. – Zézouille Oct 08 '21 at 22:28
  • @Zézouille please consider adding a new answer! – Luke Oct 13 '21 at 23:42