1
from __future__ import annotations
3
from pathlib import Path
4
from typing import TYPE_CHECKING, Union
8
from PIL import Image, ImageQt
10
from .helper import assert_image_equal_tofile, assert_image_similar, hopper
16
QApplication = Union[PyQt6.QtWidgets.QApplication, PySide6.QtWidgets.QApplication]
17
QHBoxLayout = Union[PyQt6.QtWidgets.QHBoxLayout, PySide6.QtWidgets.QHBoxLayout]
18
QImage = Union[PyQt6.QtGui.QImage, PySide6.QtGui.QImage]
19
QLabel = Union[PyQt6.QtWidgets.QLabel, PySide6.QtWidgets.QLabel]
20
QPainter = Union[PyQt6.QtGui.QPainter, PySide6.QtGui.QPainter]
21
QPixmap = Union[PyQt6.QtGui.QPixmap, PySide6.QtGui.QPixmap]
22
QPoint = Union[PyQt6.QtCore.QPoint, PySide6.QtCore.QPoint]
23
QRegion = Union[PyQt6.QtGui.QRegion, PySide6.QtGui.QRegion]
24
QWidget = Union[PyQt6.QtWidgets.QWidget, PySide6.QtWidgets.QWidget]
26
if ImageQt.qt_is_installed:
27
from PIL.ImageQt import QPixmap
29
if ImageQt.qt_version == "6":
30
from PyQt6.QtCore import QPoint
31
from PyQt6.QtGui import QImage, QPainter, QRegion
32
from PyQt6.QtWidgets import QApplication, QHBoxLayout, QLabel, QWidget
33
elif ImageQt.qt_version == "side6":
34
from PySide6.QtCore import QPoint
35
from PySide6.QtGui import QImage, QPainter, QRegion
36
from PySide6.QtWidgets import QApplication, QHBoxLayout, QLabel, QWidget
38
class Example(QWidget): # type: ignore[misc]
39
def __init__(self) -> None:
42
img = hopper().resize((1000, 1000))
44
qimage = ImageQt.ImageQt(img)
46
pixmap1 = getattr(ImageQt.QPixmap, "fromImage")(qimage)
49
QHBoxLayout(self) # type: ignore[operator]
51
lbl = QLabel(self) # type: ignore[operator]
52
# Segfault in the problem
53
lbl.setPixmap(pixmap1.copy())
56
def roundtrip(expected: Image.Image) -> None:
57
result = ImageQt.fromqpixmap(ImageQt.toqpixmap(expected))
58
# Qt saves all pixmaps as rgb
59
assert_image_similar(result, expected.convert("RGB"), 1)
62
@pytest.mark.skipif(not ImageQt.qt_is_installed, reason="Qt bindings are not installed")
63
def test_sanity(tmp_path: Path) -> None:
65
app: QApplication | None = QApplication([]) # type: ignore[operator]
67
assert app # Silence warning
68
assert ex # Silence warning
70
for mode in ("1", "RGB", "RGBA", "L", "P"):
73
data = ImageQt.toqpixmap(im)
75
assert data.__class__.__name__ == "QPixmap"
76
assert not data.isNull()
78
# Test saving the file
79
tempfile = str(tmp_path / f"temp_{mode}.png")
83
imageqt = ImageQt.ImageQt(im)
84
data = getattr(QPixmap, "fromImage")(imageqt)
85
qt_format = getattr(QImage, "Format") if ImageQt.qt_version == "6" else QImage
86
qimage = QImage(128, 128, getattr(qt_format, "Format_ARGB32")) # type: ignore[operator]
87
painter = QPainter(qimage) # type: ignore[operator]
88
image_label = QLabel() # type: ignore[operator]
89
image_label.setPixmap(data)
90
image_label.render(painter, QPoint(0, 0), QRegion(0, 0, 128, 128)) # type: ignore[operator]
92
rendered_tempfile = str(tmp_path / f"temp_rendered_{mode}.png")
93
qimage.save(rendered_tempfile)
94
assert_image_equal_tofile(im.convert("RGBA"), rendered_tempfile)
97
roundtrip(hopper(mode))