Overlaying Images in a QLabel for Onion Skinning

  pyqt, python

I’m trying to produce an onion skin effect using a QLabel in PyQt. In the simplified example below, three images are loaded in and drawn to the label using QPainter.

from PyQt5.QtWidgets import QApplication, QWidget, QGridLayout, QLabel
from PyQt5.QtCore import Qt, QPoint
from PyQt5.QtGui import QImage, QPixmap, QPainter
import sys
from pathlib import Path


class MainWindow(QWidget):
    def __init__(self):
        super().__init__()

        # -------------------------------------------------------------
        # Define the display.
        self.display = QLabel()

        # -------------------------------------------------------------
        # Import the frames
        frame_1 = QImage(str(Path(f'fixtures/test_onion_skin/frame_{1}.png')))
        frame_2 = QImage(str(Path(f'fixtures/test_onion_skin/frame_{2}.png')))
        frame_3 = QImage(str(Path(f'fixtures/test_onion_skin/frame_{3}.png')))    

        # -------------------------------------------------------------
        # Populate the display
        frame_1_scaled = frame_1.scaled(self.size(), Qt.KeepAspectRatio)
        frame_2_scaled = frame_2.scaled(self.size(), Qt.KeepAspectRatio)
        frame_3_scaled = frame_3.scaled(self.size(), Qt.KeepAspectRatio)

        base_pixmap = QPixmap(frame_1_scaled.size())

        painter = QPainter(base_pixmap)
        painter.drawImage(QPoint(), frame_3_scaled)
        painter.setOpacity(0.5)
        painter.drawImage(QPoint(), frame_2_scaled)
        painter.setOpacity(0.3)
        painter.drawImage(QPoint(), frame_1_scaled)
        painter.end()

        self.display.setPixmap(base_pixmap)

        # -------------------------------------------------------------
        # Set the layout.
        layout = QGridLayout()
        layout.addWidget(self.display, 0, 0)
        self.setLayout(layout)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    app.exec()

Ideally, the last image would show as fully opaque, with earlier images having an increasingly higher transparency. Instead, I’m getting an output where all three images blend together equally. This seems like a simple problem to fix, but my ‘Google Fu’ hasn’t yielded much this time around.

Source: Python Questions

LEAVE A COMMENT