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())