이미지 구도 예시

QPainter 에서 컴포지션 모드가 어떻게 작동하는지 보여줍니다.

리소스 파일 설정

이미지 컴포지션 예제에는 imagecomposition.qrc에 포함된 두 개의 소스 이미지, butterfly.pngchecker.png가 필요합니다. 이 파일에는 다음 코드가 포함되어 있습니다:

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

리소스 파일에 대한 자세한 내용은 Qt 리소스 시스템을 참조하십시오.

이미지 컴포지션 클래스 정의

ImageComposer 클래스는 QWidget 의 서브클래스로서 chooseSource(), chooseDestination(), recalculateResult() 의 세 개의 비공개 슬롯을 구현합니다.

class ImageComposer : public QWidget
{
    Q_OBJECT

public:
    ImageComposer();

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

또한 ImageComposeraddOp(), 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;
};

이미지 컴포저 클래스 구현

폭과 높이가 200인 정적 상수로 QSize 객체 resultSize 를 선언합니다.

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 로 설정됩니다. QLabelequalLabelresultLabel 가 생성되고 resultLabelminimumWidth 가 설정됩니다.

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

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

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

다음 신호를 해당 슬롯에 연결합니다:

  • sourceButtonclicked() 신호는 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 은 모든 위젯을 배치하는 데 사용됩니다. mainLayoutsizeConstraint 속성은 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 속성을 "이미지 컴포지션"으로 설정합니다.

    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() 함수는 QComboBoxaddItem 함수를 사용하여 operatorComboBox 에 항목을 추가합니다. 이 함수는 QPainter::CompositionMode, mode, QString, name 을 받아들입니다. 직사각형은 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.