support padded QImage
This commit is contained in:
parent
75654b8495
commit
9355ecf469
@ -1685,21 +1685,25 @@ def makeQImage(imgData, alpha=None, copy=True, transpose=True):
|
|||||||
def qimage_to_ndarray(qimg):
|
def qimage_to_ndarray(qimg):
|
||||||
img_ptr = qimg.bits()
|
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
|
# sizeInBytes() was introduced in Qt 5.10
|
||||||
# however PyQt5 5.12 will fail with:
|
# however PyQt5 5.12 will fail with:
|
||||||
# "TypeError: QImage.sizeInBytes() is a private method"
|
# "TypeError: QImage.sizeInBytes() is a private method"
|
||||||
# note that sizeInBytes() works fine with:
|
# note that sizeInBytes() works fine with:
|
||||||
# PyQt5 5.15, PySide2 5.12, PySide2 5.15
|
# PyQt5 5.15, PySide2 5.12, PySide2 5.15
|
||||||
try:
|
img_ptr.setsize(h * bpl)
|
||||||
# 64-bits size
|
|
||||||
nbytes = qimg.sizeInBytes()
|
memory = np.frombuffer(img_ptr, dtype=np.ubyte).reshape((h, bpl))
|
||||||
except (TypeError, AttributeError):
|
memory = memory[:, :logical_bpl]
|
||||||
# 32-bits size
|
|
||||||
nbytes = qimg.byteCount()
|
|
||||||
img_ptr.setsize(nbytes)
|
|
||||||
|
|
||||||
depth = qimg.depth()
|
|
||||||
if depth in (8, 24, 32):
|
if depth in (8, 24, 32):
|
||||||
dtype = np.uint8
|
dtype = np.uint8
|
||||||
nchan = depth // 8
|
nchan = depth // 8
|
||||||
@ -1708,10 +1712,12 @@ def qimage_to_ndarray(qimg):
|
|||||||
nchan = depth // 16
|
nchan = depth // 16
|
||||||
else:
|
else:
|
||||||
raise ValueError("Unsupported Image Type")
|
raise ValueError("Unsupported Image Type")
|
||||||
shape = qimg.height(), qimg.width()
|
|
||||||
|
shape = h, w
|
||||||
if nchan != 1:
|
if nchan != 1:
|
||||||
shape = shape + (nchan,)
|
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):
|
def imageToArray(img, copy=False, transpose=True):
|
||||||
|
@ -9,6 +9,7 @@ import pytest
|
|||||||
from numpy.testing import assert_array_almost_equal
|
from numpy.testing import assert_array_almost_equal
|
||||||
|
|
||||||
import pyqtgraph as pg
|
import pyqtgraph as pg
|
||||||
|
from pyqtgraph.Qt import QtGui
|
||||||
|
|
||||||
np.random.seed(12345)
|
np.random.seed(12345)
|
||||||
|
|
||||||
@ -340,3 +341,24 @@ def test_ndarray_from_qpolygonf():
|
|||||||
poly = pg.functions.create_qpolygonf(0)
|
poly = pg.functions.create_qpolygonf(0)
|
||||||
arr = pg.functions.ndarray_from_qpolygonf(poly)
|
arr = pg.functions.ndarray_from_qpolygonf(poly)
|
||||||
assert isinstance(arr, np.ndarray)
|
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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user