Warning
This section contains snippets that were automatically translated from C++ to Python and may contain errors.
Image Composition Example#
Shows how composition modes work in QPainter
.
The Image Composition example lets the user combine images together using any composition mode supported by QPainter
, described in detail in Composition Modes
.
Setting Up The Resource File#
The Image Composition example requires two source images, butterfly.png and checker.png that are embedded within imagecomposition.qrc. The file contains the following code:
<Code snippet "/data/qt5-full-650/6.5.0/Src/qtbase/painting/imagecomposition/imagecomposition.qrc" not found>
For more information on resource files, see The Qt Resource System .
ImageComposer Class Definition#
The ImageComposer
class is a subclass of QWidget
that implements three private slots, chooseSource()
, chooseDestination()
, and recalculateResult()
.
class ImageComposer(QWidget): Q_OBJECT # public ImageComposer() # private slots def chooseSource(): def chooseDestination(): def recalculateResult():
In addition, ImageComposer
consists of five private functions, addOp()
, chooseImage()
, loadImage()
, currentMode()
, and imagePos()
, as well as private instances of QToolButton
, QComboBox
, QLabel
, and QImage
.
# private def addOp(mode, name): def chooseImage(title, image, button): def loadImage(fileName, image, button): QPainter.CompositionMode currentMode() imagePos = QPoint(QImage image) sourceButton = QToolButton() destinationButton = QToolButton() operatorComboBox = QComboBox() equalLabel = QLabel() resultLabel = QLabel() sourceImage = QImage() destinationImage = QImage() resultImage = QImage()
ImageComposer Class Implementation#
We declare a QSize
object, resultSize
, as a static constant with width and height equal to 200.
resultSize = QSize(200, 200)
Within the constructor, we instantiate a QToolButton
object, sourceButton
and set its iconSize
property to resultSize
. The operatorComboBox
is instantiated and then populated using the addOp()
function. This function accepts a CompositionMode
, mode
, and a QString
, name
, representing the name of the composition mode.
def __init__(self): sourceButton = QToolButton() sourceButton.setIconSize(resultSize) operatorComboBox = QComboBox() addOp(QPainter.CompositionMode_SourceOver, tr("SourceOver")) addOp(QPainter.CompositionMode_DestinationOver, tr("DestinationOver")) addOp(QPainter.CompositionMode_Clear, tr("Clear")) addOp(QPainter.CompositionMode_Source, tr("Source")) addOp(QPainter.CompositionMode_Destination, tr("Destination")) addOp(QPainter.CompositionMode_SourceIn, tr("SourceIn")) addOp(QPainter.CompositionMode_DestinationIn, tr("DestinationIn")) addOp(QPainter.CompositionMode_SourceOut, tr("SourceOut")) addOp(QPainter.CompositionMode_DestinationOut, tr("DestinationOut")) addOp(QPainter.CompositionMode_SourceAtop, tr("SourceAtop")) addOp(QPainter.CompositionMode_DestinationAtop, tr("DestinationAtop")) addOp(QPainter.CompositionMode_Xor, tr("Xor")) addOp(QPainter.CompositionMode_Plus, tr("Plus")) addOp(QPainter.CompositionMode_Multiply, tr("Multiply")) addOp(QPainter.CompositionMode_Screen, tr("Screen")) addOp(QPainter.CompositionMode_Overlay, tr("Overlay")) addOp(QPainter.CompositionMode_Darken, tr("Darken")) addOp(QPainter.CompositionMode_Lighten, tr("Lighten")) addOp(QPainter.CompositionMode_ColorDodge, tr("ColorDodge")) addOp(QPainter.CompositionMode_ColorBurn, tr("ColorBurn")) addOp(QPainter.CompositionMode_HardLight, tr("HardLight")) addOp(QPainter.CompositionMode_SoftLight, tr("SoftLight")) addOp(QPainter.CompositionMode_Difference, tr("Difference")) addOp(QPainter.CompositionMode_Exclusion, tr("Exclusion"))
The destinationButton
is instantiated and its iconSize
property is set to resultSize
as well. The QLabel
s equalLabel
and resultLabel
are created and resultLabel
's minimumWidth
is set.
destinationButton = QToolButton() destinationButton.setIconSize(resultSize) equalLabel = QLabel(tr("=")) resultLabel = QLabel() resultLabel.setMinimumWidth(resultSize.width())
We connect the following signals to their corresponding slots:
sourceButton
'sclicked()
signal is connected tochooseSource()
,
operatorComboBox
'sactivated()
signal is connected torecalculateResult()
, and
destinationButton
'sclicked()
signal is connected tochooseDestination()
.sourceButton.clicked.connect( self.chooseSource) operatorComboBox.activated.connect( self.recalculateResult) destinationButton.clicked.connect( self.chooseDestination)
A QGridLayout
, mainLayout
, is used to place all the widgets. Note that mainLayout
's sizeConstraint
property is set to SetFixedSize
, which means that ImageComposer
's size cannot be resized at all.
mainLayout = QGridLayout() mainLayout.addWidget(sourceButton, 0, 0, 3, 1) mainLayout.addWidget(operatorComboBox, 1, 1) mainLayout.addWidget(destinationButton, 0, 2, 3, 1) mainLayout.addWidget(equalLabel, 1, 3) mainLayout.addWidget(resultLabel, 0, 4, 3, 1) mainLayout.setSizeConstraint(QLayout.SetFixedSize) setLayout(mainLayout)
We create a QImage
, resultImage
, and we invoke loadImage()
twice to load both the image files in our imagecomposition.qrc file. Then, we set the windowTitle
property to “Image Composition”.
resultImage = QImage(resultSize, QImage.Format_ARGB32_Premultiplied) loadImage(":/images/butterfly.png", sourceImage, sourceButton) loadImage(":/images/checker.png", destinationImage, destinationButton) setWindowTitle(tr("Image Composition"))
The chooseSource()
and chooseDestination()
functions are convenience functions that invoke chooseImage()
with specific parameters.
def chooseSource(self): chooseImage(tr("Choose Source Image"), sourceImage, sourceButton) def chooseDestination(self): chooseImage(tr("Choose Destination Image"), destinationImage, destinationButton)
The chooseImage()
function loads an image of the user’s choice, depending on the title
, image
, and button
.
def chooseImage(self, title, image,): QToolButton button) fileName = QFileDialog.getOpenFileName(self, title) if not fileName.isEmpty(): loadImage(fileName, image, button)
The recalculateResult()
function is used to calculate amd display the result of combining the two images together with the user’s choice of composition mode.
def recalculateResult(self): QPainter.CompositionMode mode = currentMode() painter = QPainter(resultImage) painter.setCompositionMode(QPainter.CompositionMode_Source) painter.fillRect(resultImage.rect(), Qt.transparent) painter.setCompositionMode(QPainter.CompositionMode_SourceOver) painter.drawImage(0, 0, destinationImage) painter.setCompositionMode(mode) painter.drawImage(0, 0, sourceImage) painter.setCompositionMode(QPainter.CompositionMode_DestinationOver) painter.fillRect(resultImage.rect(), Qt.white) painter.end() resultLabel.setPixmap(QPixmap.fromImage(resultImage))
The addOp()
function adds an item to the operatorComboBox
using QComboBox
‘s addItem
function. This function accepts a CompositionMode
, mode
, and a QString
, name
. The rectangle is filled with Qt::Transparent and both the sourceImage
and destinationImage
are painted, before displaying it on resultLabel
.
def addOp(self, mode, name): operatorComboBox.addItem(name, mode)
The loadImage()
function paints a transparent background using fillRect()
and draws image
in a centralized position using drawImage()
. This image
is then set as the button
's icon.
def loadImage(self, fileName, image,): QToolButton button) image.load(fileName) # Scale the image to given size image = image.scaled(resultSize, Qt.KeepAspectRatio) fixedImage = QImage(resultSize, QImage.Format_ARGB32_Premultiplied) painter = QPainter(fixedImage) painter.setCompositionMode(QPainter.CompositionMode_Source) painter.fillRect(fixedImage.rect(), Qt.transparent) painter.setCompositionMode(QPainter.CompositionMode_SourceOver) painter.drawImage(imagePos(image), image) painter.end() button.setIcon(QPixmap.fromImage(fixedImage)) image = fixedImage recalculateResult()
The currentMode()
function returns the composition mode currently selected in operatorComboBox
.
QPainter.CompositionMode ImageComposer.currentMode() return (QPainter.CompositionMode) operatorComboBox.itemData(operatorComboBox.currentIndex()).toInt()
We use the imagePos()
function to ensure that images loaded onto the QToolButton
objects, sourceButton
and destinationButton
, are centralized.
def imagePos(self, QImage image): return QPoint((resultSize.width() - image.width()) / 2, (resultSize.height() - image.height()) / 2)
The `` main()``
Function#
The main()
function instantiates QApplication
and ImageComposer
and invokes its show()
function.
if __name__ == "__main__": Q_INIT_RESOURCE(imagecomposition) app = QApplication([]) composer = ImageComposer() composer.show() sys.exit(app.exec())