画像合成の例
QPainter での合成モードの動作を示します。
リソースファイルのセットアップ
画像合成の例では、imagecomposition.qrc 内に埋め込まれた 2 つのソース画像、butterfly.pngとchecker.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つのプライベート関数と、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クラスの実装
幅と高さが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
に設定される。QLabelのequalLabel
と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()
を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()
関数は、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()
関数は、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()
関数は、QComboBox のaddItem 関数を使用して、operatorComboBox
に項目を追加します。この関数は、QPainter::CompositionMode 、mode 、QString 、name を受け付けます。矩形は Qt::Transparent で塗りつぶされ、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(); }
©2024 The Qt Company Ltd. 本書に含まれる文書の著作権は、それぞれの所有者に帰属します。 本書で提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。