图像合成示例
展示了QPainter 中合成模式的工作原理。

设置资源文件
“图像合成”示例需要两张源图像:butterfly.png和checker.png,它们已嵌入到imagecomposition.qrc 文件中。该文件包含以下代码:
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>images/butterfly.png</file>
<file>images/checker.png</file>
</qresource>
</RCC>有关资源文件的更多信息,请参阅《Qt 资源系统》。
ImageComposer 类定义
ImageComposer 类是QWidget 的子类,它实现了三个私有槽:chooseSource() 、chooseDestination() 和recalculateResult() 。
class ImageComposer : public QWidget
{
Q_OBJECT
public:
ImageComposer();
private slots:
void chooseSource();
void chooseDestination();
void recalculateResult();此外,ImageComposer 包含五个私有函数:addOp() 、chooseImage() 、loadImage() 、currentMode() 和imagePos() ,以及QToolButton 、QComboBox 、QLabel 和QImage 的私有实例。
private:
void addOp(QPainter::CompositionMode mode, const QString &name);
void chooseImage(const QString &title, QImage *image, QToolButton *button);
void loadImage(const QString &fileName, QImage *image, QToolButton *button);
QPainter::CompositionMode currentMode() const;
QPoint imagePos(const QImage &image) const;
QToolButton *sourceButton;
QToolButton *destinationButton;
QComboBox *operatorComboBox;
QLabel *equalLabel;
QLabel *resultLabel;
QImage sourceImage;
QImage destinationImage;
QImage resultImage;
};ImageComposer 类的实现
我们将一个QSize 对象resultSize 声明为静态常量,其宽度和高度均设为 200。
static const QSize resultSize(200, 200);在构造函数中,我们实例化一个QToolButton 对象,即sourceButton ,并将它的iconSize 属性设置为resultSize 。operatorComboBox 被实例化,随后通过addOp() 函数进行初始化。该函数接受QPainter::CompositionMode 、mode 以及QString 、name 作为参数,这些参数分别表示合成模式的名称。
ImageComposer::ImageComposer()
{
sourceButton = new QToolButton;
sourceButton->setIconSize(resultSize);
operatorComboBox = new 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"));destinationButton 被实例化,其iconSize 属性也设置为resultSize 。创建了QLabelsequalLabel 和resultLabel ,并设置了resultLabel 的minimumWidth 。
destinationButton = new QToolButton;
destinationButton->setIconSize(resultSize);
equalLabel = new QLabel(tr("="));
resultLabel = new QLabel;
resultLabel->setMinimumWidth(resultSize.width());我们将以下信号连接到相应的插槽:
sourceButton的clicked() 信号连接到chooseSource(),operatorComboBox的activated() 信号连接至recalculateResult(),以及destinationButton的clicked() 信号连接到chooseDestination()。
connect(sourceButton, &QAbstractButton::clicked,
this, &ImageComposer::chooseSource);
connect(operatorComboBox, &QComboBox::activated,
this, &ImageComposer::recalculateResult);
connect(destinationButton, &QAbstractButton::clicked,
this, &ImageComposer::chooseDestination);使用一个QGridLayout (mainLayout )来放置所有控件。请注意,mainLayout 的sizeConstraint 属性被设置为QLayout::SetFixedSize ,这意味着ImageComposer 的大小完全无法调整。
QGridLayout *mainLayout = new 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);我们创建一个QImage 和resultImage ,并调用两次loadImage() 来加载imagecomposition.qrc文件中的两张图像文件。随后,我们将windowTitle 属性设置为“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"));
}chooseSource() 和chooseDestination() 函数是便捷函数,它们会使用特定参数调用chooseImage() 。
void ImageComposer::chooseSource()
{
chooseImage(tr("Choose Source Image"), &sourceImage, sourceButton);
}
void ImageComposer::chooseDestination()
{
chooseImage(tr("Choose Destination Image"), &destinationImage, destinationButton);
}chooseImage() 函数根据title 、image 和button 的设置,加载用户选择的图像。
void ImageComposer::chooseImage(const QString &title, QImage *image,
QToolButton *button)
{
QString fileName = QFileDialog::getOpenFileName(this, title);
if (!fileName.isEmpty())
loadImage(fileName, image, button);
}recalculateResult() 函数用于计算并显示两张图像在用户选择的合成模式下合并后的结果。
void ImageComposer::recalculateResult()
{
QPainter::CompositionMode mode = currentMode();
QPainter painter(&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));
}addOp() operatorComboBox QComboBox addItem QPainter::CompositionMode mode QString name sourceImage destinationImage resultLabel
void ImageComposer::addOp(QPainter::CompositionMode mode, const QString &name)
{
operatorComboBox->addItem(name, mode);
}loadImage() 函数使用fillRect()绘制透明背景,并使用drawImage()将image 绘制在中心位置。随后将此image 设置为button 的图标。
void ImageComposer::loadImage(const QString &fileName, QImage *image,
QToolButton *button)
{
image->load(fileName);
// Scale the image to given size
*image = image->scaled(resultSize, Qt::KeepAspectRatio);
QImage fixedImage(resultSize, QImage::Format_ARGB32_Premultiplied);
QPainter painter(&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();
}currentMode() 函数返回operatorComboBox 中当前选定的合成模式。
QPainter::CompositionMode ImageComposer::currentMode() const
{
return (QPainter::CompositionMode)
operatorComboBox->itemData(operatorComboBox->currentIndex()).toInt();
}我们使用imagePos() 函数来确保加载到QToolButton 对象(sourceButton 和destinationButton )上的图像居中显示。
QPoint ImageComposer::imagePos(const QImage &image) const
{
return QPoint((resultSize.width() - image.width()) / 2,
(resultSize.height() - image.height()) / 2);
}main() 函数
main() 函数会实例化QApplication 和ImageComposer ,并调用其show()函数。
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
ImageComposer composer;
composer.show();
return app.exec();
}© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.