Pillow/Tests/test_qt_image_qapplication.py
2024-08-26 23:49:03 +10:00

101 lines
3.5 KiB
Python

from __future__ import annotations
from pathlib import Path
from typing import TYPE_CHECKING, Union
import pytest
from PIL import Image, ImageQt
from .helper import assert_image_equal_tofile, assert_image_similar, hopper
if TYPE_CHECKING:
import PyQt6
import PySide6
QApplication = Union[PyQt6.QtWidgets.QApplication, PySide6.QtWidgets.QApplication]
QHBoxLayout = Union[PyQt6.QtWidgets.QHBoxLayout, PySide6.QtWidgets.QHBoxLayout]
QImage = Union[PyQt6.QtGui.QImage, PySide6.QtGui.QImage]
QLabel = Union[PyQt6.QtWidgets.QLabel, PySide6.QtWidgets.QLabel]
QPainter = Union[PyQt6.QtGui.QPainter, PySide6.QtGui.QPainter]
QPixmap = Union[PyQt6.QtGui.QPixmap, PySide6.QtGui.QPixmap]
QPoint = Union[PyQt6.QtCore.QPoint, PySide6.QtCore.QPoint]
QRegion = Union[PyQt6.QtGui.QRegion, PySide6.QtGui.QRegion]
QWidget = Union[PyQt6.QtWidgets.QWidget, PySide6.QtWidgets.QWidget]
if ImageQt.qt_is_installed:
from PIL.ImageQt import QPixmap
if ImageQt.qt_version == "6":
from PyQt6.QtCore import QPoint
from PyQt6.QtGui import QImage, QPainter, QRegion
from PyQt6.QtWidgets import QApplication, QHBoxLayout, QLabel, QWidget
elif ImageQt.qt_version == "side6":
from PySide6.QtCore import QPoint
from PySide6.QtGui import QImage, QPainter, QRegion
from PySide6.QtWidgets import QApplication, QHBoxLayout, QLabel, QWidget
class Example(QWidget): # type: ignore[misc]
def __init__(self) -> None:
super().__init__()
img = hopper().resize((1000, 1000))
qimage = ImageQt.ImageQt(img)
pixmap1 = getattr(ImageQt.QPixmap, "fromImage")(qimage)
# hbox
QHBoxLayout(self) # type: ignore[operator]
lbl = QLabel(self) # type: ignore[operator]
# Segfault in the problem
lbl.setPixmap(pixmap1.copy())
def roundtrip(expected: Image.Image) -> None:
result = ImageQt.fromqpixmap(ImageQt.toqpixmap(expected))
# Qt saves all pixmaps as rgb
assert_image_similar(result, expected.convert("RGB"), 1)
@pytest.mark.skipif(not ImageQt.qt_is_installed, reason="Qt bindings are not installed")
def test_sanity(tmp_path: Path) -> None:
# Segfault test
app: QApplication | None = QApplication([]) # type: ignore[operator]
ex = Example()
assert app # Silence warning
assert ex # Silence warning
for mode in ("1", "RGB", "RGBA", "L", "P"):
# to QPixmap
im = hopper(mode)
data = ImageQt.toqpixmap(im)
assert data.__class__.__name__ == "QPixmap"
assert not data.isNull()
# Test saving the file
tempfile = str(tmp_path / f"temp_{mode}.png")
data.save(tempfile)
# Render the image
imageqt = ImageQt.ImageQt(im)
data = getattr(QPixmap, "fromImage")(imageqt)
qt_format = getattr(QImage, "Format") if ImageQt.qt_version == "6" else QImage
qimage = QImage(128, 128, getattr(qt_format, "Format_ARGB32")) # type: ignore[operator]
painter = QPainter(qimage) # type: ignore[operator]
image_label = QLabel() # type: ignore[operator]
image_label.setPixmap(data)
image_label.render(painter, QPoint(0, 0), QRegion(0, 0, 128, 128)) # type: ignore[operator]
painter.end()
rendered_tempfile = str(tmp_path / f"temp_rendered_{mode}.png")
qimage.save(rendered_tempfile)
assert_image_equal_tofile(im.convert("RGBA"), rendered_tempfile)
# from QPixmap
roundtrip(hopper(mode))
app.quit()
app = None