support padded QImage

This commit is contained in:
KIU Shueng Chuan 2021-07-31 20:58:51 +08:00
parent 75654b8495
commit 9355ecf469
2 changed files with 39 additions and 11 deletions

View File

@ -1685,21 +1685,25 @@ def makeQImage(imgData, alpha=None, copy=True, transpose=True):
def qimage_to_ndarray(qimg):
img_ptr = qimg.bits()
if hasattr(img_ptr, 'setsize'): # PyQt sip.voidptr
if img_ptr is None:
raise ValueError("Null QImage not supported")
h, w = qimg.height(), qimg.width()
bpl = qimg.bytesPerLine()
depth = qimg.depth()
logical_bpl = w * depth // 8
if QT_LIB.startswith('PyQt'):
# sizeInBytes() was introduced in Qt 5.10
# however PyQt5 5.12 will fail with:
# "TypeError: QImage.sizeInBytes() is a private method"
# note that sizeInBytes() works fine with:
# PyQt5 5.15, PySide2 5.12, PySide2 5.15
try:
# 64-bits size
nbytes = qimg.sizeInBytes()
except (TypeError, AttributeError):
# 32-bits size
nbytes = qimg.byteCount()
img_ptr.setsize(nbytes)
img_ptr.setsize(h * bpl)
memory = np.frombuffer(img_ptr, dtype=np.ubyte).reshape((h, bpl))
memory = memory[:, :logical_bpl]
depth = qimg.depth()
if depth in (8, 24, 32):
dtype = np.uint8
nchan = depth // 8
@ -1708,10 +1712,12 @@ def qimage_to_ndarray(qimg):
nchan = depth // 16
else:
raise ValueError("Unsupported Image Type")
shape = qimg.height(), qimg.width()
shape = h, w
if nchan != 1:
shape = shape + (nchan,)
return np.frombuffer(img_ptr, dtype=dtype).reshape(shape)
arr = memory.view(dtype).reshape(shape)
return arr
def imageToArray(img, copy=False, transpose=True):

View File

@ -9,6 +9,7 @@ import pytest
from numpy.testing import assert_array_almost_equal
import pyqtgraph as pg
from pyqtgraph.Qt import QtGui
np.random.seed(12345)
@ -340,3 +341,24 @@ def test_ndarray_from_qpolygonf():
poly = pg.functions.create_qpolygonf(0)
arr = pg.functions.ndarray_from_qpolygonf(poly)
assert isinstance(arr, np.ndarray)
def test_qimage_to_ndarray():
# for QImages created w/o specifying bytesPerLine, Qt will pad
# each line to a multiple of 4-bytes.
# test that we can handle such QImages.
h = 10
fmt = QtGui.QImage.Format.Format_RGB888
for w in [5, 6, 7, 8]:
qimg = QtGui.QImage(w, h, fmt)
qimg.fill(0)
arr = pg.functions.qimage_to_ndarray(qimg)
assert arr.shape == (h, w, 3)
fmt = QtGui.QImage.Format.Format_Grayscale8
for w in [5, 6, 7, 8]:
qimg = QtGui.QImage(w, h, fmt)
qimg.fill(0)
arr = pg.functions.qimage_to_ndarray(qimg)
assert arr.shape == (h, w)