En esta página

Ejemplo de composición de imágenes

Muestra cómo funcionan los modos de composición en QPainter.

Aplicación que combina dos imágenes utilizando modos de composición

Configuración del archivo de recursos

El ejemplo de composición de imágenes requiere dos imágenes fuente, butterfly.png y checker.png que están incrustadas dentro de imagecomposition.qrc. El archivo contiene el siguiente código:

<!DOCTYPE RCC><RCC version="1.0">
<qresource>
    <file>images/butterfly.png</file>
    <file>images/checker.png</file>
</qresource>
</RCC>

Para más información sobre archivos de recursos, ver El Sistema de Recursos Qt.

Definición de la clase ImageComposer

La clase ImageComposer es una subclase de QWidget que implementa tres ranuras privadas, chooseSource(), chooseDestination(), y recalculateResult().

class ImageComposer : public QWidget
{
    Q_OBJECT

public:
    ImageComposer();

private slots:
    void chooseSource();
    void chooseDestination();
    void recalculateResult();

Además, ImageComposer consta de cinco funciones privadas, addOp(), chooseImage(), loadImage(), currentMode(), y imagePos(), así como instancias privadas de QToolButton, QComboBox, QLabel, y 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;
};

Implementación de la clase ImageComposer

Declaramos un objeto QSize, resultSize, como una constante estática con anchura y altura iguales a 200.

static const QSize resultSize(200, 200);

Dentro del constructor, instanciamos un objeto QToolButton, sourceButton y establecemos su propiedad iconSize a resultSize. El operatorComboBox es instanciado y luego poblado usando la función addOp(). Esta función acepta un QPainter::CompositionMode, mode, y un QString, name, que representa el nombre del modo de composición.

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"));

El destinationButton es instanciado y su propiedad iconSize es establecida a resultSize también. Los QLabels equalLabel y resultLabel se crean y resultLabel's minimumWidth se establece.

    destinationButton = new QToolButton;
    destinationButton->setIconSize(resultSize);

    equalLabel = new QLabel(tr("="));

    resultLabel = new QLabel;
    resultLabel->setMinimumWidth(resultSize.width());

Conectamos las siguientes señales a sus ranuras correspondientes:

  • sourceButtonLa señal 's clicked() se conecta a chooseSource(),
  • operatorComboBoxla señal 's activated() se conecta a recalculateResult(), y
  • destinationButtonLa señal 's clicked() está conectada a chooseDestination().
    connect(sourceButton, &QAbstractButton::clicked,
            this, &ImageComposer::chooseSource);
    connect(operatorComboBox, &QComboBox::activated,
            this, &ImageComposer::recalculateResult);
    connect(destinationButton, &QAbstractButton::clicked,
            this, &ImageComposer::chooseDestination);

Un QGridLayout, mainLayout, se utiliza para colocar todos los widgets. Ten en cuenta que la propiedad sizeConstraint de mainLayout está fijada en QLayout::SetFixedSize, lo que significa que el tamaño de ImageComposer no se puede redimensionar en absoluto.

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

Creamos un QImage, resultImage, e invocamos loadImage() dos veces para cargar ambos archivos de imagen en nuestro archivo imagecomposition.qrc. A continuación, establecemos la propiedad windowTitle en "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"));
}

Las funciones chooseSource() y chooseDestination() son funciones de conveniencia que invocan a chooseImage() con parámetros específicos.

void ImageComposer::chooseSource()
{
    chooseImage(tr("Choose Source Image"), &sourceImage, sourceButton);
}

void ImageComposer::chooseDestination()
{
    chooseImage(tr("Choose Destination Image"), &destinationImage, destinationButton);
}

La función chooseImage() carga una imagen a elección del usuario, en función de los parámetros title, image, y button.

void ImageComposer::chooseImage(const QString &title, QImage *image,
                                QToolButton *button)
{
    QString fileName = QFileDialog::getOpenFileName(this, title);
    if (!fileName.isEmpty())
        loadImage(fileName, image, button);
}

La función recalculateResult() se utiliza para calcular y mostrar el resultado de combinar las dos imágenes junto con el modo de composición elegido por el usuario.

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));
}

La función addOp() añade un elemento a operatorComboBox utilizando la función QComboBox's addItem. Esta función acepta un QPainter::CompositionMode, mode, y un QString, name. El rectángulo se rellena con Qt::Transparent y se pintan tanto sourceImage como destinationImage, antes de mostrarlo en resultLabel.

void ImageComposer::addOp(QPainter::CompositionMode mode, const QString &name)
{
    operatorComboBox->addItem(name, mode);
}

La función loadImage() pinta un fondo transparente usando fillRect() y dibuja image en una posición centralizada usando drawImage(). A continuación, image se establece como icono de 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();
}

La función currentMode() devuelve el modo de composición actualmente seleccionado en operatorComboBox.

QPainter::CompositionMode ImageComposer::currentMode() const
{
    return (QPainter::CompositionMode)
           operatorComboBox->itemData(operatorComboBox->currentIndex()).toInt();
}

Utilizamos la función imagePos() para asegurarnos de que las imágenes cargadas en los objetos QToolButton, sourceButton y destinationButton, están centralizadas.

QPoint ImageComposer::imagePos(const QImage &image) const
{
    return QPoint((resultSize.width() - image.width()) / 2,
                  (resultSize.height() - image.height()) / 2);
}

La función main()

La función main() instancia QApplication y ImageComposer e invoca su función show().

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    ImageComposer composer;
    composer.show();
    return app.exec();
}

Proyecto de ejemplo @ code.qt.io

© 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.