画像合成の例

QPainter での合成モードの動作を示します。

リソースファイルのセットアップ

画像合成の例では、imagecomposition.qrc 内に埋め込まれた 2 つのソース画像、butterfly.pngchecker.pngが必要です。このファイルには以下のコードが含まれています:

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

リソースファイルの詳細については、Qt Resource System を参照してください。

ImageComposer クラスの定義

ImageComposer クラスはQWidget のサブクラスで、chooseSource()chooseDestination()recalculateResult() の3つのプライベートスロットを実装しています。

class ImageComposer : public QWidget
{
    Q_OBJECT

public:
    ImageComposer();

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

また、ImageComposer は、addOp()chooseImage()loadImage()currentMode()imagePos() の5つのプライベート関数と、QToolButtonQComboBoxQLabelQImage のプライベートインスタンスで構成されています。

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クラスの実装

幅と高さが200に等しい静的定数として、QSize オブジェクト、resultSize を宣言する。

static const QSize resultSize(200, 200);

コンストラクタ内で、QToolButton オブジェクト、sourceButton をインスタンス化し、そのiconSize プロパティをresultSize に設定します。operatorComboBox はインスタンス化され、addOp() 関数を使用して入力されます。この関数は、QPainter::CompositionModemodeQStringname を受け取り、合成モードの名前を表します。

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 に設定される。QLabelequalLabelresultLabel が作成され、resultLabelminimumWidth が設定される。

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

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

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

以下のシグナルを対応するスロットに接続する:

  • sourceButton clicked() シグナルは に接続される、chooseSource()
  • operatorComboBoxactivated() シグナルはrecalculateResult() に接続される。
  • destinationButtonclicked() シグナルは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);

QImageresultImage を作成し、loadImage() を2回呼び出して、imagecomposition.qrcファイル内の両方の画像ファイルを読み込みます。そして、windowTitle プロパティを「画像合成」に設定します。

    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() 関数は、titleimagebutton に応じて、ユーザーが選択した画像をロードします。

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

recalculateResult() 関数は、2つの画像をユーザーが選択した合成モードで合成した結果を計算し、表示するために使用されます。

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() 関数は、QComboBoxaddItem 関数を使用して、operatorComboBox に項目を追加します。この関数は、QPainter::CompositionModemodeQStringname を受け付けます。矩形は Qt::Transparent で塗りつぶされ、sourceImagedestinationImage の両方がペイントされた後、resultLabel に表示されます。

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

loadImage() 関数は、fillRect() を使って透明な背景を描き、drawImage() を使ってimage を中心位置に描画します。このimagebutton のアイコンとして設定される。

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 オブジェクト、sourceButtondestinationButton に読み込まれた画像が中央に配置されるようにしています。

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

main() 関数

main() 関数はQApplicationImageComposer をインスタンス化し、show() 関数を呼び出します。

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

プロジェクト例 @ code.qt.io

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