File indexing completed on 2025-01-05 03:51:28
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2009-02-28 0007 * Description : batch tool to add visible watermark. 0008 * 0009 * SPDX-FileCopyrightText: 2009-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0010 * SPDX-FileCopyrightText: 2010 by Mikkel Baekhoej Christensen <mbc at baekhoej dot dk> 0011 * SPDX-FileCopyrightText: 2017 by Ahmed Fathi <ahmed dot fathi dot abdelmageed at gmail dot com> 0012 * 0013 * SPDX-License-Identifier: GPL-2.0-or-later 0014 * 0015 * ============================================================ */ 0016 0017 #include "watermark.h" 0018 0019 // Qt includes 0020 0021 #include <QFontMetrics> 0022 #include <QLabel> 0023 #include <QPainter> 0024 #include <QPen> 0025 #include <QPoint> 0026 #include <QRect> 0027 #include <QWidget> 0028 #include <QGridLayout> 0029 #include <QRadioButton> 0030 #include <QCheckBox> 0031 #include <QGroupBox> 0032 #include <QApplication> 0033 #include <QStyle> 0034 #include <QFontComboBox> 0035 #include <QComboBox> 0036 #include <QDoubleSpinBox> 0037 #include <QRandomGenerator> 0038 0039 // KDE includes 0040 0041 #include <klocalizedstring.h> 0042 0043 // Local includes 0044 0045 #include "dlayoutbox.h" 0046 #include "dnuminput.h" 0047 #include "dfileselector.h" 0048 #include "digikam_debug.h" 0049 #include "dimg.h" 0050 #include "blurfilter.h" 0051 #include "dfontproperties.h" 0052 #include "metaengine.h" 0053 #include "dcolorselector.h" 0054 #include "dtextedit.h" 0055 0056 namespace DigikamBqmWatermarkPlugin 0057 { 0058 0059 class Q_DECL_HIDDEN WaterMark::Private 0060 { 0061 0062 public: 0063 0064 enum WaterMarkPositon 0065 { 0066 TopLeft = 0, 0067 TopRight, 0068 BottomLeft, 0069 BottomRight, 0070 Center, 0071 TopCenter, 0072 BottomCenter 0073 }; 0074 0075 enum WaterMarkPlacementType 0076 { 0077 SpecifiedLocation = 0, 0078 SystematicRepetition, 0079 RandomRepetition 0080 }; 0081 0082 public: 0083 0084 explicit Private() 0085 : textSettingsGroupBox (nullptr), 0086 imageSettingsGroupBox (nullptr), 0087 useAbsoluteImageSizeGroupBox (nullptr), 0088 useImageRadioButton (nullptr), 0089 ignoreWatermarkAspectCheckBox (nullptr), 0090 addTransparencyToWatermarkImageCheckBox (nullptr), 0091 useAbsoluteSizeCheckBox (nullptr), 0092 useBackgroundCheckBox (nullptr), 0093 denseRepetitionCheckBox (nullptr), 0094 randomizeRotationCheckBox (nullptr), 0095 useTextRadioButton (nullptr), 0096 imageFileUrlRequester (nullptr), 0097 textEdit (nullptr), 0098 placementPositionComboBox (nullptr), 0099 placementTypeComboBox (nullptr), 0100 rotationComboBox (nullptr), 0101 sparsityFactorSpinBox (nullptr), 0102 extendedFontChooserWidget (nullptr), 0103 fontColorButton (nullptr), 0104 backgroundColorButton (nullptr), 0105 textOpacity (nullptr), 0106 backgroundOpacity (nullptr), 0107 xMarginInput (nullptr), 0108 yMarginInput (nullptr), 0109 waterMarkSizePercent (nullptr), 0110 waterMarkOpacityPercent (nullptr), 0111 changeSettings (true) 0112 { 0113 } 0114 0115 QGroupBox* textSettingsGroupBox; 0116 QGroupBox* imageSettingsGroupBox; 0117 QGroupBox* useAbsoluteImageSizeGroupBox ; 0118 QRadioButton* useImageRadioButton; 0119 QCheckBox* ignoreWatermarkAspectCheckBox; 0120 QCheckBox* addTransparencyToWatermarkImageCheckBox; 0121 QCheckBox* useAbsoluteSizeCheckBox; 0122 QCheckBox* useBackgroundCheckBox; 0123 QCheckBox* denseRepetitionCheckBox; 0124 QCheckBox* randomizeRotationCheckBox; 0125 QRadioButton* useTextRadioButton; 0126 0127 DFileSelector* imageFileUrlRequester; 0128 DTextEdit* textEdit; 0129 0130 QComboBox* placementPositionComboBox; 0131 QComboBox* placementTypeComboBox; 0132 QComboBox* rotationComboBox; 0133 QDoubleSpinBox* sparsityFactorSpinBox; 0134 DFontProperties* extendedFontChooserWidget; 0135 0136 DColorSelector* fontColorButton; 0137 DColorSelector* backgroundColorButton; 0138 0139 DIntNumInput* textOpacity; 0140 DIntNumInput* backgroundOpacity; 0141 DIntNumInput* xMarginInput; 0142 DIntNumInput* yMarginInput; 0143 DIntNumInput* waterMarkSizePercent; 0144 DIntNumInput* waterMarkOpacityPercent; 0145 0146 bool changeSettings; 0147 }; 0148 0149 WaterMark::WaterMark(QObject* const parent) 0150 : BatchTool(QLatin1String("WaterMark"), DecorateTool, parent), 0151 d (new Private) 0152 { 0153 } 0154 0155 WaterMark::~WaterMark() 0156 { 0157 delete d; 0158 } 0159 0160 BatchTool* WaterMark::clone(QObject* const parent) const 0161 { 0162 return new WaterMark(parent); 0163 } 0164 0165 void WaterMark::registerSettingsWidget() 0166 { 0167 const int spacing = qMin(QApplication::style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing), 0168 QApplication::style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing)); 0169 0170 DVBox* const vbox = new DVBox; 0171 vbox->setContentsMargins(spacing, spacing, spacing, spacing); 0172 vbox->setSpacing(spacing); 0173 0174 DHBox* const hbox = new DHBox(vbox); 0175 hbox->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); 0176 hbox->setSpacing(spacing); 0177 0178 d->useAbsoluteImageSizeGroupBox = new QGroupBox(vbox); 0179 QVBoxLayout* const useAbsoluteImageSizeGroupBoxLayout = new QVBoxLayout; 0180 useAbsoluteImageSizeGroupBoxLayout->setContentsMargins(spacing, spacing, spacing, spacing); 0181 useAbsoluteImageSizeGroupBoxLayout->addStretch(1); 0182 d->useAbsoluteImageSizeGroupBox->setLayout(useAbsoluteImageSizeGroupBoxLayout); 0183 0184 DHBox* const useAbsoluteSizeHBox = new DHBox(); 0185 useAbsoluteSizeHBox->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); 0186 useAbsoluteSizeHBox->setSpacing(spacing); 0187 d->useAbsoluteSizeCheckBox = new QCheckBox(useAbsoluteSizeHBox); 0188 d->useAbsoluteSizeCheckBox->setWhatsThis(i18n("Check this if you want the watermark to use the given size of " 0189 "the font or the image without any adjustment to the actual image.")); 0190 QLabel* const useAbsoluteSizeLabel = new QLabel(useAbsoluteSizeHBox); 0191 useAbsoluteSizeLabel->setText(i18n("Use Absolute Size")); 0192 d->useAbsoluteSizeCheckBox->setChecked(false); 0193 0194 useAbsoluteImageSizeGroupBoxLayout->addWidget(useAbsoluteSizeHBox); 0195 0196 QLabel* const watermarkTypeLabel = new QLabel(hbox); 0197 watermarkTypeLabel->setText(i18n("Watermark type: ")); 0198 0199 d->useImageRadioButton = new QRadioButton(hbox); 0200 d->useImageRadioButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); 0201 QLabel* const useImageLabel = new QLabel(hbox); 0202 useImageLabel ->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); 0203 d->useTextRadioButton = new QRadioButton(hbox); 0204 d->useTextRadioButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); 0205 QLabel* const useTextLabel = new QLabel(hbox); 0206 useTextLabel ->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); 0207 useImageLabel->setText(i18n("Image")); 0208 useTextLabel->setText(i18n("Text")); 0209 0210 useImageLabel->setAlignment(Qt::AlignLeft); 0211 useTextLabel->setAlignment(Qt::AlignLeft); 0212 d->useImageRadioButton->setChecked(true); 0213 0214 // --- 0215 0216 d->imageSettingsGroupBox = new QGroupBox(vbox); 0217 d->imageSettingsGroupBox->setTitle(i18n("Image settings")); 0218 QVBoxLayout* const imageSettingsGroupBoxLayout = new QVBoxLayout; 0219 imageSettingsGroupBoxLayout->setContentsMargins(spacing, spacing, spacing, spacing); 0220 imageSettingsGroupBoxLayout->addStretch(1); 0221 d->imageSettingsGroupBox->setLayout(imageSettingsGroupBoxLayout); 0222 0223 DHBox* const imageSelectHBox = new DHBox(); 0224 QLabel* const label = new QLabel(imageSelectHBox); 0225 d->imageFileUrlRequester = new DFileSelector(imageSelectHBox); 0226 d->imageFileUrlRequester->lineEdit()->setPlaceholderText(i18n("Click to select watermark image.")); 0227 label->setText(i18n("Watermark image: ")); 0228 imageSettingsGroupBoxLayout->addWidget(imageSelectHBox); 0229 0230 DHBox* const ignoreWatermarkAspectRatioHBox = new DHBox(); 0231 ignoreWatermarkAspectRatioHBox->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); 0232 ignoreWatermarkAspectRatioHBox->setSpacing(spacing); 0233 0234 d->ignoreWatermarkAspectCheckBox = new QCheckBox(ignoreWatermarkAspectRatioHBox); 0235 d->ignoreWatermarkAspectCheckBox->setWhatsThis(i18n("Check this if you want the watermark to ignore its own " 0236 "aspect ratio and use the image's aspect ratio instead.")); 0237 0238 QLabel* const ignoreWatermarkAspectRatioLabel = new QLabel(ignoreWatermarkAspectRatioHBox); 0239 ignoreWatermarkAspectRatioLabel->setText(i18n("Ignore Watermark aspect Ratio")); 0240 d->ignoreWatermarkAspectCheckBox->setChecked(false); 0241 imageSettingsGroupBoxLayout->addWidget(ignoreWatermarkAspectRatioHBox); 0242 0243 DHBox* const addTransparencyToWatermarkImageHBox = new DHBox(); 0244 addTransparencyToWatermarkImageHBox->setContentsMargins(QMargins()); 0245 addTransparencyToWatermarkImageHBox->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); 0246 addTransparencyToWatermarkImageHBox->setSpacing(spacing); 0247 0248 d->addTransparencyToWatermarkImageCheckBox = new QCheckBox(addTransparencyToWatermarkImageHBox); 0249 d->addTransparencyToWatermarkImageCheckBox->setWhatsThis(i18n("Check this if you want watermark to be transparent.")); 0250 d->addTransparencyToWatermarkImageCheckBox->setChecked(false); 0251 0252 QLabel* const addTransparencyToWatermarkLabel = new QLabel(addTransparencyToWatermarkImageHBox); 0253 addTransparencyToWatermarkLabel->setText(i18n("Add transparency to watermark image")); 0254 imageSettingsGroupBoxLayout->addWidget(addTransparencyToWatermarkImageHBox); 0255 0256 DHBox* const watermarkImageOpacityBox = new DHBox(); 0257 watermarkImageOpacityBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); 0258 watermarkImageOpacityBox->setSpacing(spacing); 0259 0260 QLabel* const opacityLabel = new QLabel(watermarkImageOpacityBox); 0261 d->waterMarkOpacityPercent = new DIntNumInput(watermarkImageOpacityBox); 0262 d->waterMarkOpacityPercent->setRange(0, 100, 1); 0263 d->waterMarkOpacityPercent->setDefaultValue(100); 0264 d->waterMarkOpacityPercent->setWhatsThis(i18n("Opacity of watermark")); 0265 opacityLabel->setText(i18n("Opacity (%): ")); 0266 imageSettingsGroupBoxLayout->addWidget(watermarkImageOpacityBox); 0267 0268 // --- 0269 0270 d->textSettingsGroupBox = new QGroupBox(vbox); 0271 d->textSettingsGroupBox->setTitle(i18n("Text settings")); 0272 QVBoxLayout* const textSettingsGroupBoxLayout = new QVBoxLayout; 0273 textSettingsGroupBoxLayout->setContentsMargins(spacing, spacing, spacing, spacing); 0274 textSettingsGroupBoxLayout->addStretch(1); 0275 d->textSettingsGroupBox->setLayout(textSettingsGroupBoxLayout); 0276 0277 QLabel* const textEditLabel = new QLabel(vbox); 0278 d->textEdit = new DTextEdit(vbox); 0279 d->textEdit->setPlaceholderText(i18n("Enter your watermark string here.")); 0280 textEditLabel->setText(i18n("Watermark text: ")); 0281 textSettingsGroupBoxLayout->addWidget(textEditLabel); 0282 textSettingsGroupBoxLayout->addWidget(d->textEdit); 0283 0284 d->extendedFontChooserWidget = new DFontProperties(nullptr, DFontProperties::NoDisplayFlags); 0285 d->extendedFontChooserWidget->setSampleBoxVisible(true); 0286 d->extendedFontChooserWidget->enableColumn(0x04, false); 0287 d->extendedFontChooserWidget->setWhatsThis(i18n("Choose the font type and style. Size is auto calculated.")); 0288 textSettingsGroupBoxLayout->addWidget(d->extendedFontChooserWidget); 0289 0290 DHBox* const fontColorBox = new DHBox(); 0291 QLabel* const label3 = new QLabel(fontColorBox); 0292 d->fontColorButton = new DColorSelector(fontColorBox); 0293 d->fontColorButton->setColor(Qt::black); 0294 d->fontColorButton->setWhatsThis(i18n("Set the font color to use here.")); 0295 label3->setText(i18n("Font color: ")); 0296 textSettingsGroupBoxLayout->addWidget(fontColorBox); 0297 0298 DHBox* const fontOpacityBox = new DHBox(); 0299 QLabel* const textOpacityLabel = new QLabel(fontOpacityBox); 0300 textOpacityLabel->setText(i18n("Text opacity: ")); 0301 d->textOpacity = new DIntNumInput(fontOpacityBox); 0302 d->textOpacity->setRange(0, 100, 1); 0303 d->textOpacity->setDefaultValue(100); 0304 d->textOpacity->setWhatsThis(i18n("Set the opacity of the watermark text. " 0305 "100 is fully opaque, 0 is fully transparent.")); 0306 textSettingsGroupBoxLayout->addWidget(fontOpacityBox); 0307 0308 DHBox* const useBackgroundHBox = new DHBox(); 0309 useBackgroundHBox->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); 0310 useBackgroundHBox->setSpacing(spacing); 0311 0312 d->useBackgroundCheckBox = new QCheckBox(useBackgroundHBox); 0313 d->useBackgroundCheckBox->setWhatsThis(i18n("Check this if you want a background fill behind the text.")); 0314 QLabel* const useBackgroundLabel = new QLabel(useBackgroundHBox); 0315 useBackgroundLabel->setText(i18n("Use background")); 0316 textSettingsGroupBoxLayout->addWidget(useBackgroundHBox); 0317 0318 DHBox* const useBackgroundColorHBox = new DHBox(); 0319 QLabel* const backgroundColorLabel = new QLabel(useBackgroundColorHBox); 0320 d->backgroundColorButton = new DColorSelector(useBackgroundColorHBox); 0321 d->backgroundColorButton->setColor(QColor(0xCC, 0xCC, 0xCC)); 0322 d->backgroundColorButton->setWhatsThis(i18n("Choose the color of the watermark background.")); 0323 backgroundColorLabel ->setText(i18n("Background color: ")); 0324 textSettingsGroupBoxLayout->addWidget(useBackgroundColorHBox); 0325 0326 DHBox* const useBackgroundOpacityHBox = new DHBox(); 0327 QLabel* const backgroundOpacityLabel = new QLabel(useBackgroundOpacityHBox); 0328 backgroundOpacityLabel->setText(i18n("Background opacity: ")); 0329 d->backgroundOpacity = new DIntNumInput(useBackgroundOpacityHBox); 0330 d->backgroundOpacity->setRange(0, 100, 1); 0331 d->backgroundOpacity->setDefaultValue(100); 0332 d->backgroundOpacity->setWhatsThis(i18n("Set the opacity of the watermark background. " 0333 "100 is fully opaque, 0 is fully transparent.")); 0334 textSettingsGroupBoxLayout->addWidget(useBackgroundOpacityHBox); 0335 0336 d->imageSettingsGroupBox->setVisible(true); 0337 d->textSettingsGroupBox->setVisible(false); 0338 0339 // --- 0340 0341 DHBox* const placementTypeHBox = new DHBox(vbox); 0342 QLabel* const placementTypeLabel = new QLabel(placementTypeHBox); 0343 d->placementTypeComboBox = new QComboBox(placementTypeHBox); 0344 d->placementTypeComboBox->insertItem(Private::SpecifiedLocation, i18n("Specific Location")); 0345 d->placementTypeComboBox->insertItem(Private::SystematicRepetition, i18n("Systematic Repetition")); 0346 d->placementTypeComboBox->insertItem(Private::RandomRepetition, i18n("Random Repetition")); 0347 placementTypeLabel->setText(i18n("Placement Type: ")); 0348 0349 DHBox* const placementHBox = new DHBox(vbox); 0350 placementHBox->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); 0351 placementHBox->setSpacing(spacing); 0352 0353 QLabel* const spaceLabel = new QLabel(placementHBox); 0354 d->denseRepetitionCheckBox = new QCheckBox(placementHBox); 0355 d->denseRepetitionCheckBox->setWhatsThis(i18n("When you choose to have the watermark repeated many times in the " 0356 "placement combo box, you can specify here whether the repetition.")); 0357 d->denseRepetitionCheckBox->setChecked(false); 0358 d->denseRepetitionCheckBox->setEnabled(false); 0359 spaceLabel->setText(QLatin1String(" ")); 0360 QLabel* const placementDensityLabel = new QLabel(placementHBox); 0361 placementDensityLabel->setText(i18n("Density of watermark repetition (Disabled in \"Specific Location\" mode)")); 0362 0363 DHBox* const randomizeHBox = new DHBox(vbox); 0364 randomizeHBox->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); 0365 randomizeHBox->setSpacing(spacing); 0366 0367 QLabel* const spaceLabel2 = new QLabel(randomizeHBox); 0368 d->randomizeRotationCheckBox = new QCheckBox(randomizeHBox); 0369 d->randomizeRotationCheckBox->setWhatsThis(i18n("When you choose to have the watermark repeated randomly in " 0370 "the placement combo box, you can specify here to randomly " 0371 "rotate the watermark (0, 90, 180, 270 degrees).")); 0372 d->randomizeRotationCheckBox->setChecked(true); 0373 d->denseRepetitionCheckBox->setEnabled(false); 0374 spaceLabel2->setText(QLatin1String(" ")); 0375 QLabel* const randomizeRotation = new QLabel(randomizeHBox); 0376 randomizeRotation->setText(i18n("Randomize watermark orientation (Enabled in \"Random Repetition\" mode only)")); 0377 0378 DHBox* const sparsityHBox = new DHBox(vbox); 0379 sparsityHBox->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); 0380 sparsityHBox->setSpacing(spacing); 0381 0382 QLabel* const sparsityFactorLabel = new QLabel(sparsityHBox); 0383 d->sparsityFactorSpinBox = new QDoubleSpinBox(sparsityHBox); 0384 d->sparsityFactorSpinBox->setMinimum(0.0); 0385 d->sparsityFactorSpinBox->setValue(1); 0386 d->sparsityFactorSpinBox->setSingleStep(0.1); 0387 d->sparsityFactorSpinBox->setWhatsThis(i18n("Use this to get more control over the sparsity of watermark " 0388 "repetition. The higher the value the sparser the watermarks get. " 0389 "Use floating point values, typically between 1.0 and 3.0. It can " 0390 "also be less than 1.0")); 0391 sparsityFactorLabel->setText(i18n("Sparsity Factor: ")); 0392 0393 DHBox* const placementPositionHBox = new DHBox(vbox); 0394 QLabel* const label4 = new QLabel(placementPositionHBox); 0395 d->placementPositionComboBox = new QComboBox(placementPositionHBox); 0396 d->placementPositionComboBox->insertItem(Private::TopLeft, i18nc("@item: placement position", "Top left")); 0397 d->placementPositionComboBox->insertItem(Private::TopRight, i18nc("@item: placement position", "Top right")); 0398 d->placementPositionComboBox->insertItem(Private::BottomLeft, i18nc("@item: placement position", "Bottom left")); 0399 d->placementPositionComboBox->insertItem(Private::BottomRight, i18nc("@item: placement position", "Bottom right")); 0400 d->placementPositionComboBox->insertItem(Private::Center, i18nc("@item: placement position", "Center")); 0401 d->placementPositionComboBox->insertItem(Private::TopCenter, i18nc("@item: placement position", "Top center")); 0402 d->placementPositionComboBox->insertItem(Private::BottomCenter, i18nc("@item: placement position", "Bottom center")); 0403 0404 label4->setText(i18n("Placement Position: ")); 0405 0406 DHBox* const placementRotationHBox = new DHBox(vbox); 0407 QLabel* const labelRotation = new QLabel(placementRotationHBox); 0408 d->rotationComboBox = new QComboBox(placementRotationHBox); 0409 d->rotationComboBox->insertItem(0, i18n("0 degrees")); 0410 d->rotationComboBox->insertItem(1, i18n("90 degrees CW")); 0411 d->rotationComboBox->insertItem(2, i18n("180 degrees")); 0412 d->rotationComboBox->insertItem(3, i18n("270 degrees CW")); 0413 labelRotation->setText(i18n("Rotation: ")); 0414 0415 DHBox* const placementSizeHBox = new DHBox(vbox); 0416 QLabel* const label5 = new QLabel(placementSizeHBox); 0417 d->waterMarkSizePercent = new DIntNumInput(placementSizeHBox); 0418 d->waterMarkSizePercent->setRange(0, 100, 1); 0419 d->waterMarkSizePercent->setDefaultValue(30); 0420 d->waterMarkSizePercent->setWhatsThis(i18n("Size of watermark, as a percentage of the marked image.")); 0421 label5->setText(i18n("Size (%): ")); 0422 0423 DHBox* const placementXMarginHBox = new DHBox(vbox); 0424 QLabel* const label6 = new QLabel(placementXMarginHBox); 0425 d->xMarginInput = new DIntNumInput(placementXMarginHBox); 0426 d->xMarginInput->setRange(0, 100, 1); 0427 d->xMarginInput->setDefaultValue(2); 0428 d->xMarginInput->setWhatsThis(i18n("Margin from edge in X direction, as a percentage of the marked image.")); 0429 label6->setText(i18n("X margin (%): ")); 0430 0431 DHBox* const placementYMarginHBox = new DHBox(vbox); 0432 QLabel* const label7 = new QLabel(placementYMarginHBox); 0433 d->yMarginInput = new DIntNumInput(placementYMarginHBox); 0434 d->yMarginInput->setRange(0, 100, 1); 0435 d->yMarginInput->setDefaultValue(2); 0436 d->yMarginInput->setWhatsThis(i18n("Margin from edge in Y direction, as a percentage of the marked image.")); 0437 label7->setText(i18n("Y margin (%): ")); 0438 0439 QLabel* const space = new QLabel(vbox); 0440 vbox->setStretchFactor(space, 10); 0441 0442 m_settingsWidget = vbox; 0443 0444 // ------------------------------------------------------------------------------------------------------ 0445 0446 connect(d->useImageRadioButton, SIGNAL(toggled(bool)), 0447 this, SLOT(slotSettingsChanged())); 0448 0449 connect(d->useTextRadioButton, SIGNAL(toggled(bool)), 0450 this, SLOT(slotSettingsChanged())); 0451 0452 connect(d->imageFileUrlRequester->lineEdit(), SIGNAL(textChanged(QString)), 0453 this, SLOT(slotSettingsChanged())); 0454 0455 connect(d->extendedFontChooserWidget, SIGNAL(fontSelected(QFont)), 0456 this, SLOT(slotSettingsChanged())); 0457 0458 connect(d->fontColorButton, SIGNAL(signalColorSelected(QColor)), 0459 this, SLOT(slotSettingsChanged())); 0460 0461 connect(d->textEdit, SIGNAL(textChanged()), 0462 this, SLOT(slotSettingsChanged())); 0463 0464 connect(d->textOpacity, SIGNAL(valueChanged(int)), 0465 this, SLOT(slotSettingsChanged())); 0466 0467 connect(d->useBackgroundCheckBox, SIGNAL(toggled(bool)), 0468 this, SLOT(slotSettingsChanged())); 0469 0470 connect(d->ignoreWatermarkAspectCheckBox, SIGNAL(toggled(bool)), 0471 this, SLOT(slotSettingsChanged())); 0472 0473 connect(d->addTransparencyToWatermarkImageCheckBox, SIGNAL(toggled(bool)), 0474 this, SLOT(slotSettingsChanged())); 0475 0476 connect(d->useAbsoluteSizeCheckBox, SIGNAL(toggled(bool)), 0477 this, SLOT(slotSettingsChanged())); 0478 0479 connect(d->backgroundColorButton, SIGNAL(signalColorSelected(QColor)), 0480 this, SLOT(slotSettingsChanged())); 0481 0482 connect(d->backgroundOpacity, SIGNAL(valueChanged(int)), 0483 this, SLOT(slotSettingsChanged())); 0484 0485 connect(d->placementTypeComboBox, SIGNAL(activated(int)), 0486 this, SLOT(slotSettingsChanged())); 0487 0488 connect(d->placementPositionComboBox, SIGNAL(activated(int)), 0489 this, SLOT(slotSettingsChanged())); 0490 0491 connect(d->denseRepetitionCheckBox, SIGNAL(toggled(bool)), 0492 this, SLOT(slotSettingsChanged())); 0493 0494 connect(d->randomizeRotationCheckBox, SIGNAL(toggled(bool)), 0495 this, SLOT(slotSettingsChanged())); 0496 0497 connect(d->sparsityFactorSpinBox, SIGNAL(valueChanged(double)), 0498 this, SLOT(slotSettingsChanged())); 0499 0500 connect(d->rotationComboBox, SIGNAL(activated(int)), 0501 this, SLOT(slotSettingsChanged())); 0502 0503 connect(d->waterMarkSizePercent, SIGNAL(valueChanged(int)), 0504 this, SLOT(slotSettingsChanged())); 0505 0506 connect(d->yMarginInput, SIGNAL(valueChanged(int)), 0507 this, SLOT(slotSettingsChanged())); 0508 0509 connect(d->xMarginInput, SIGNAL(valueChanged(int)), 0510 this, SLOT(slotSettingsChanged())); 0511 0512 connect(d->waterMarkOpacityPercent, SIGNAL(valueChanged(int)), 0513 this, SLOT(slotSettingsChanged())); 0514 0515 BatchTool::registerSettingsWidget(); 0516 } 0517 0518 BatchToolSettings WaterMark::defaultSettings() 0519 { 0520 BatchToolSettings settings; 0521 0522 settings.insert(QLatin1String("Use image"), true); 0523 settings.insert(QLatin1String("Watermark image"), QString()); 0524 settings.insert(QLatin1String("Text"), QString()); 0525 settings.insert(QLatin1String("Font"), QFont()); 0526 settings.insert(QLatin1String("Color"), QColor(Qt::black)); 0527 settings.insert(QLatin1String("Text opacity"), 100); 0528 settings.insert(QLatin1String("Use background"), true); 0529 settings.insert(QLatin1String("Background color"), QColor(0xCC, 0xCC, 0xCC)); 0530 settings.insert(QLatin1String("Background opacity"), 0xCC); 0531 settings.insert(QLatin1String("PlacementType"), Private::SpecifiedLocation); // specified location for the watermark 0532 settings.insert(QLatin1String("Dense Repetition"), false); 0533 settings.insert(QLatin1String("Randomize Rotation"), true); 0534 settings.insert(QLatin1String("Sparsity Factor"), 1.0); 0535 settings.insert(QLatin1String("Placement"), Private::BottomRight); 0536 settings.insert(QLatin1String("Rotation"), 0); 0537 settings.insert(QLatin1String("Watermark size"), 25); 0538 settings.insert(QLatin1String("X margin"), 2); 0539 settings.insert(QLatin1String("Y margin"), 2); 0540 settings.insert(QLatin1String("Opacity"), 100); 0541 0542 return settings; 0543 } 0544 0545 void WaterMark::slotAssignSettings2Widget() 0546 { 0547 d->changeSettings = false; 0548 d->useImageRadioButton->setChecked(settings()[QLatin1String("Use image")].toBool()); 0549 d->useTextRadioButton->setChecked(!settings()[QLatin1String("Use image")].toBool()); 0550 d->imageFileUrlRequester->setFileDlgPath(settings()[QLatin1String("Watermark image")].toString()); 0551 0552 QString txt = settings()[QLatin1String("Text")].toString(); 0553 0554 if (d->textEdit->text() != txt) 0555 { 0556 d->textEdit->setText(txt); 0557 } 0558 0559 d->extendedFontChooserWidget->setFont(qvariant_cast<QFont>(settings()[QLatin1String("Font")])); 0560 d->fontColorButton->setColor(settings()[QLatin1String("Color")].toString()); 0561 d->textOpacity->setValue(settings()[QLatin1String("Text opacity")].toInt()); 0562 d->useBackgroundCheckBox->setChecked(settings()[QLatin1String("Use background")].toBool()); 0563 d->backgroundColorButton->setColor(settings()[QLatin1String("Background color")].toString()); 0564 d->backgroundOpacity->setValue(settings()[QLatin1String("Background opacity")].toInt()); 0565 d->placementPositionComboBox->setCurrentIndex(settings()[QLatin1String("PlacementType")].toInt()); 0566 d->denseRepetitionCheckBox->setChecked(settings()[QLatin1String("Dense Repetition")].toBool()); 0567 d->randomizeRotationCheckBox->setChecked(settings()[QLatin1String("Randomize Rotation")].toBool()); 0568 d->sparsityFactorSpinBox->setValue(settings()[QLatin1String("Sparsity Factor")].toDouble()); 0569 d->placementPositionComboBox->setCurrentIndex(settings()[QLatin1String("Placement")].toInt()); 0570 d->rotationComboBox->setCurrentIndex(settings()[QLatin1String("Rotation")].toInt()); 0571 d->waterMarkSizePercent->setValue(settings()[QLatin1String("Watermark size")].toInt()); 0572 d->xMarginInput->setValue(settings()[QLatin1String("X margin")].toInt()); 0573 d->yMarginInput->setValue(settings()[QLatin1String("Y margin")].toInt()); 0574 d->waterMarkOpacityPercent->setValue(settings()[QLatin1String("Opacity")].toInt()); 0575 d->changeSettings = true; 0576 } 0577 0578 void WaterMark::slotSettingsChanged() 0579 { 0580 if (d->useImageRadioButton->isChecked()) 0581 { 0582 d->textSettingsGroupBox->setVisible(false); 0583 d->imageSettingsGroupBox->setVisible(true); 0584 } 0585 else if (d->useTextRadioButton->isChecked()) 0586 { 0587 d->imageSettingsGroupBox->setVisible(false); 0588 d->textSettingsGroupBox->setVisible(true); 0589 } 0590 0591 d->waterMarkSizePercent->setEnabled(!d->useAbsoluteSizeCheckBox->isChecked()); 0592 d->extendedFontChooserWidget->enableColumn(0x04, d->useAbsoluteSizeCheckBox->isChecked()); 0593 d->placementPositionComboBox->setEnabled(((int)d->placementTypeComboBox->currentIndex() == Private::SpecifiedLocation)); 0594 d->denseRepetitionCheckBox->setEnabled(((int)d->placementTypeComboBox->currentIndex() != Private::SpecifiedLocation)); 0595 d->sparsityFactorSpinBox->setEnabled(((int)d->placementTypeComboBox->currentIndex() != Private::SpecifiedLocation)); 0596 d->randomizeRotationCheckBox->setEnabled(((int)d->placementTypeComboBox->currentIndex() == Private::RandomRepetition)); 0597 d->rotationComboBox->setEnabled(!(d->randomizeRotationCheckBox->isEnabled() && d->randomizeRotationCheckBox->isChecked())); 0598 d->waterMarkOpacityPercent->setEnabled(d->addTransparencyToWatermarkImageCheckBox->isChecked()); 0599 0600 if (d->changeSettings) 0601 { 0602 BatchToolSettings settings; 0603 settings.insert(QLatin1String("Use image"), d->useImageRadioButton->isChecked()); 0604 settings.insert(QLatin1String("Watermark image"), d->imageFileUrlRequester->fileDlgPath()); 0605 settings.insert(QLatin1String("Text"), d->textEdit->text()); 0606 settings.insert(QLatin1String("Font"), d->extendedFontChooserWidget->font()); 0607 settings.insert(QLatin1String("Color"), d->fontColorButton->color()); 0608 settings.insert(QLatin1String("Text opacity"), d->textOpacity->value()); 0609 settings.insert(QLatin1String("Use background"), d->useBackgroundCheckBox->isChecked()); 0610 settings.insert(QLatin1String("Ignore Watermark Aspect Ratio"), d->ignoreWatermarkAspectCheckBox->isChecked()); 0611 settings.insert(QLatin1String("Use Absolute Size"), d->useAbsoluteSizeCheckBox->isChecked()); 0612 settings.insert(QLatin1String("Background color"), d->backgroundColorButton->color()); 0613 settings.insert(QLatin1String("Background opacity"), d->backgroundOpacity->value()); 0614 settings.insert(QLatin1String("Dense Repetition"), d->denseRepetitionCheckBox->isChecked()); 0615 settings.insert(QLatin1String("Randomize Rotation"), d->randomizeRotationCheckBox->isChecked()); 0616 settings.insert(QLatin1String("Sparsity Factor"), (double)d->sparsityFactorSpinBox->value()); 0617 settings.insert(QLatin1String("PlacementType"), (int)d->placementTypeComboBox->currentIndex()); 0618 settings.insert(QLatin1String("Placement"), (int)d->placementPositionComboBox->currentIndex()); 0619 settings.insert(QLatin1String("Rotation"), (int)d->rotationComboBox->currentIndex()); 0620 settings.insert(QLatin1String("Watermark size"), (int)d->waterMarkSizePercent->value()); 0621 settings.insert(QLatin1String("X margin"), (int)d->xMarginInput->value()); 0622 settings.insert(QLatin1String("Y margin"), (int)d->yMarginInput->value()); 0623 settings.insert(QLatin1String("Opacity"), (int)d->waterMarkOpacityPercent->value()); 0624 settings.insert(QLatin1String("Add transparency"), d->addTransparencyToWatermarkImageCheckBox->isChecked()); 0625 BatchTool::slotSettingsChanged(settings); 0626 } 0627 } 0628 0629 bool WaterMark::toolOperations() 0630 { 0631 if (!loadToDImg()) 0632 { 0633 return false; 0634 } 0635 0636 QString fileName = settings()[QLatin1String("Watermark image")].toString(); 0637 int placementPosition = settings()[QLatin1String("Placement")].toInt(); 0638 int placementType = settings()[QLatin1String("PlacementType")].toInt(); 0639 bool denseRepetition = settings()[QLatin1String("Dense Repetition")].toBool(); 0640 bool randomizeRotation = settings()[QLatin1String("Randomize Rotation")].toBool(); 0641 double userSparsityFactor = settings()[QLatin1String("Sparsity Factor")].toDouble(); 0642 int size = settings()[QLatin1String("Watermark size")].toInt(); 0643 int xMargin = settings()[QLatin1String("X margin")].toInt(); 0644 int yMargin = settings()[QLatin1String("Y margin")].toInt(); 0645 bool useImage = settings()[QLatin1String("Use image")].toBool(); 0646 QString text = settings()[QLatin1String("Text")].toString(); 0647 QFont font = qvariant_cast<QFont>(settings()[QLatin1String("Font")]); 0648 0649 QColor fontColor = settings()[QLatin1String("Color")].toString(); 0650 int textOpacity = settings()[QLatin1String("Text opacity")].toInt(); 0651 bool useBackground = settings()[QLatin1String("Use background")].toBool(); 0652 QColor backgroundColor = settings()[QLatin1String("Background color")].toString(); 0653 int backgroundOpacity = settings()[QLatin1String("Background opacity")].toInt(); 0654 Qt::AspectRatioMode watermarkAspectRatioMode = settings()[QLatin1String("Ignore Watermark Aspect Ratio")].toBool() ? 0655 Qt::IgnoreAspectRatio : Qt::KeepAspectRatio; 0656 bool useAbsoluteSize = settings()[QLatin1String("Use Absolute Size")].toBool(); 0657 0658 DImg watermarkImage; 0659 DColorComposer* const composer = DColorComposer::getComposer(DColorComposer::PorterDuffNone); 0660 int marginW = lround(image().width() * (xMargin / 100.0)); 0661 int marginH = lround(image().height() * (yMargin / 100.0)); 0662 int rotationIndex = settings()[QLatin1String("Rotation")].toInt(); 0663 double opacity = settings()[QLatin1String("Opacity")].toInt()/100.0; 0664 bool addTransparency = settings()[QLatin1String("Add transparency")].toBool(); 0665 0666 DImg::ANGLE rotationAngle = (rotationIndex == 1) ? DImg::ANGLE::ROT90 : 0667 (rotationIndex == 2) ? DImg::ANGLE::ROT180 : 0668 (rotationIndex == 3) ? DImg::ANGLE::ROT270 : 0669 DImg::ANGLE::ROTNONE; 0670 0671 // rotate and/or flip the image depending on the exif information to allow for the expected watermark placement. 0672 // note that this operation is reversed after proper watermark generation to leave everything as it was. 0673 0674 image().exifRotate(inputUrl().toLocalFile()); 0675 0676 float ratio = (float)image().height() / image().width(); 0677 0678 if ((rotationAngle == DImg::ANGLE::ROT90) || (rotationAngle == DImg::ANGLE::ROT270)) 0679 { 0680 size = size * ratio; 0681 } 0682 else 0683 { 0684 // For Images whose height are much larger than their width, this helps keep 0685 // the watermark size reasonable 0686 0687 if (ratio > 1.5) 0688 { 0689 int tempSize = size * ratio; 0690 0691 if (tempSize < 35) 0692 { 0693 tempSize *= 1.5; 0694 } 0695 0696 size = (tempSize < 100) ? tempSize : 100; 0697 } 0698 } 0699 0700 if (useImage) 0701 { 0702 watermarkImage = DImg(fileName); 0703 0704 if (watermarkImage.isNull()) 0705 { 0706 return false; 0707 } 0708 0709 if (!useAbsoluteSize) 0710 { 0711 DImg tempImage = watermarkImage.smoothScale(image().width() * size / 100, 0712 image().height() * size / 100, 0713 watermarkAspectRatioMode); 0714 watermarkImage = tempImage; 0715 } 0716 0717 if (addTransparency) 0718 { 0719 if (!watermarkImage.hasAlpha()) 0720 { 0721 return false; 0722 } 0723 0724 for (uint i = 0 ; i < watermarkImage.width() ; ++i) 0725 { 0726 for (uint j = 0 ; j < watermarkImage.height() ; ++j) 0727 { 0728 DColor color = watermarkImage.getPixelColor(i, j); 0729 color.setAlpha((int)(opacity*color.alpha())); 0730 watermarkImage.setPixelColor(i, j, color); 0731 } 0732 } 0733 } 0734 } 0735 else 0736 { 0737 int alignMode; 0738 const int radius = 10; 0739 0740 if (text.isEmpty()) 0741 { 0742 return false; 0743 } 0744 0745 int fontSize = queryFontSize(text, font, size); 0746 0747 if (fontSize == 0) 0748 { 0749 return false; 0750 } 0751 0752 switch (placementPosition) 0753 { 0754 case Private::TopLeft: 0755 { 0756 alignMode = Qt::AlignLeft; 0757 break; 0758 } 0759 0760 case Private::TopRight: 0761 { 0762 alignMode = Qt::AlignRight; 0763 break; 0764 } 0765 0766 case Private::BottomLeft: 0767 { 0768 alignMode = Qt::AlignLeft; 0769 break; 0770 } 0771 0772 case Private::Center: 0773 case Private::TopCenter: 0774 case Private::BottomCenter: 0775 { 0776 alignMode = Qt::AlignCenter; 0777 break; 0778 } 0779 0780 default: // BottomRight 0781 { 0782 alignMode = Qt::AlignRight; 0783 break; 0784 } 0785 } 0786 0787 if (!useAbsoluteSize) 0788 { 0789 font.setPointSizeF(fontSize); 0790 } 0791 0792 QFontMetrics fontMt(font); 0793 QRect fontRect = fontMt.boundingRect(radius, radius, image().width(), image().height(), 0, text); 0794 0795 // Add a transparent layer. 0796 0797 QRect backgroundRect(fontRect.x() - radius, fontRect.y() - radius, 0798 fontRect.width() + 2 * radius, fontRect.height() + 2 * radius); 0799 DImg backgroundLayer(backgroundRect.width(), backgroundRect.height(), image().sixteenBit(), true); 0800 DColor transparent(QColor(0, 0, 0)); 0801 transparent.setAlpha(0); 0802 0803 if (image().sixteenBit()) 0804 { 0805 transparent.convertToSixteenBit(); 0806 } 0807 0808 backgroundLayer.fill(transparent); 0809 0810 DImg grayTransLayer(fontRect.width(), fontRect.height(), image().sixteenBit(), true); 0811 0812 if (useBackground) 0813 { 0814 DColor grayTrans(backgroundColor); 0815 grayTrans.setAlpha(backgroundOpacity * 255 / 100); 0816 0817 if (image().sixteenBit()) 0818 { 0819 grayTrans.convertToSixteenBit(); 0820 } 0821 0822 grayTransLayer.fill(grayTrans); 0823 backgroundLayer.bitBlendImage(composer, &grayTransLayer, 0, 0, 0824 grayTransLayer.width(), grayTransLayer.height(), 0825 radius, radius); 0826 } 0827 0828 BlurFilter blur(&backgroundLayer, nullptr, radius); 0829 blur.startFilterDirectly(); 0830 backgroundLayer.putImageData(blur.getTargetImage().bits()); 0831 0832 // Draw text 0833 0834 QImage img = backgroundLayer.copyQImage(fontRect); 0835 QPainter p(&img); 0836 fontColor.setAlpha(textOpacity * 255 / 100); 0837 p.setPen(QPen(fontColor, 1)); 0838 p.setFont(font); 0839 p.save(); 0840 p.drawText(0, 0, fontRect.width(), fontRect.height(), alignMode, text); 0841 p.restore(); 0842 p.end(); 0843 0844 watermarkImage = DImg(img); 0845 } 0846 0847 watermarkImage.convertToDepthOfImage(&image()); 0848 0849 QRect watermarkRect(0, 0, watermarkImage.width(), watermarkImage.height()); 0850 0851 int xAdditionalValue = 0; 0852 int yAdditionalValue = 0; 0853 0854 watermarkImage.rotate(rotationAngle); 0855 0856 if (placementType == Private::SpecifiedLocation) 0857 { 0858 switch (placementPosition) 0859 { 0860 case Private::TopLeft: 0861 { 0862 watermarkRect.moveTopLeft(QPoint(marginW, marginH)); 0863 break; 0864 } 0865 0866 case Private::TopRight: 0867 { 0868 if ((rotationAngle == DImg::ANGLE::ROT270) || (rotationAngle == DImg::ANGLE::ROT90)) 0869 { 0870 xAdditionalValue += watermarkRect.width() - watermarkRect.height(); 0871 } 0872 0873 watermarkRect.moveTopRight(QPoint(image().width() + xAdditionalValue - marginW - 1, 0874 marginH)); 0875 break; 0876 } 0877 0878 case Private::BottomLeft: 0879 { 0880 if ((rotationAngle == DImg::ANGLE::ROT90) || (rotationAngle == DImg::ANGLE::ROT270)) 0881 { 0882 yAdditionalValue += watermarkRect.height() - watermarkRect.width(); 0883 } 0884 0885 watermarkRect.moveBottomLeft(QPoint(marginW, 0886 image().height() + yAdditionalValue - marginH - 1)); 0887 break; 0888 } 0889 0890 case Private::Center: 0891 { 0892 if ((rotationAngle == DImg::ANGLE::ROT90) || (rotationAngle == DImg::ANGLE::ROT270)) 0893 { 0894 xAdditionalValue += (watermarkRect.width() - watermarkRect.height()) / 2; 0895 yAdditionalValue += (watermarkRect.height() - watermarkRect.width()) / 2; 0896 } 0897 0898 watermarkRect.moveCenter(QPoint((int)(image().width() / 2 + xAdditionalValue), 0899 (int)(image().height() / 2 + yAdditionalValue))); 0900 break; 0901 } 0902 0903 case Private::TopCenter: 0904 { 0905 if ((rotationAngle == DImg::ANGLE::ROT90) || (rotationAngle == DImg::ANGLE::ROT270)) 0906 { 0907 xAdditionalValue += (watermarkRect.width() - watermarkRect.height()) / 2; 0908 } 0909 0910 watermarkRect.moveCenter(QPoint((int)(image().width() / 2 + xAdditionalValue), 0911 (watermarkRect.height() / 2) + marginH)); 0912 break; 0913 } 0914 0915 case Private::BottomCenter: 0916 { 0917 if ((rotationAngle == DImg::ANGLE::ROT90) || (rotationAngle == DImg::ANGLE::ROT270)) 0918 { 0919 xAdditionalValue += (watermarkRect.width() - watermarkRect.height()) / 2; 0920 yAdditionalValue += watermarkRect.height() - watermarkRect.width(); 0921 } 0922 0923 watermarkRect.moveCenter(QPoint((int)(image().width() / 2 + xAdditionalValue), 0924 image().height() + yAdditionalValue - 0925 (watermarkRect.height() / 2) - marginH - 1)); 0926 break; 0927 } 0928 0929 default: // BottomRight 0930 { 0931 if ((rotationAngle == DImg::ANGLE::ROT90) || (rotationAngle == DImg::ANGLE::ROT270)) 0932 { 0933 xAdditionalValue += watermarkRect.width() - watermarkRect.height(); 0934 yAdditionalValue += watermarkRect.height() - watermarkRect.width(); 0935 } 0936 0937 watermarkRect.moveBottomRight(QPoint(image().width() + xAdditionalValue - marginW - 1, 0938 image().height() + yAdditionalValue - marginH - 1)); 0939 break; 0940 } 0941 } 0942 0943 image().bitBlendImage(composer, 0944 &watermarkImage, 0, 0, watermarkImage.width(), watermarkImage.height(), 0945 watermarkRect.left(), watermarkRect.top()); 0946 } 0947 else 0948 { 0949 const float DENSE_SPACING_FACTOR = 1.2F; 0950 const float SPARSE_SPACING_FACTOR = 1.8F; 0951 float widthRatio = (float)watermarkRect.width() / image().width(); 0952 float heightRatio = (float)watermarkRect.height() / image().height(); 0953 float spacingFactor = (denseRepetition) ? DENSE_SPACING_FACTOR : SPARSE_SPACING_FACTOR; 0954 spacingFactor *= userSparsityFactor; 0955 0956 if (placementType == Private::SystematicRepetition) 0957 { 0958 if ((rotationAngle == DImg::ANGLE::ROT270) || (rotationAngle == DImg::ANGLE::ROT90)) 0959 { 0960 widthRatio = (float)watermarkRect.height() / image().width(); 0961 heightRatio = (float)watermarkRect.width() / image().height(); 0962 } 0963 0964 for (uint i = 0 ; i < image().width() ; i += spacingFactor * widthRatio * image().width()) 0965 { 0966 for (uint j = 0 ; j < image().height() ; j += spacingFactor * heightRatio * image().height()) 0967 { 0968 image().bitBlendImage(composer, &watermarkImage, 0, 0, watermarkImage.width(), watermarkImage.height(), i, j); 0969 } 0970 } 0971 } 0972 else if (placementType == Private::RandomRepetition) 0973 { 0974 widthRatio = (widthRatio > heightRatio) ? widthRatio : heightRatio; 0975 heightRatio = widthRatio; 0976 0977 auto randomGenerator = QRandomGenerator::global(); 0978 0979 for (uint i = 0 ; i < image().width() ; i += spacingFactor * widthRatio * image().width()) 0980 { 0981 for (uint j = 0 ; j < image().height() ; j += spacingFactor * heightRatio * image().height()) 0982 { 0983 int number = (denseRepetition) ? 2 : 3; 0984 0985 if (randomGenerator->bounded(number) == 0) 0986 { 0987 if (randomizeRotation) 0988 { 0989 int x = randomGenerator->bounded(4); 0990 watermarkImage.rotate((DImg::ANGLE)x); 0991 } 0992 0993 image().bitBlendImage(composer, &watermarkImage, 0, 0, watermarkImage.width(), watermarkImage.height(), i, j); 0994 } 0995 } 0996 } 0997 } 0998 } 0999 1000 // TODO: Create watermark filter, move code there, implement FilterAction 1001 1002 delete composer; 1003 image().reverseExifRotate(inputUrl().toLocalFile()); 1004 1005 return (savefromDImg()); 1006 } 1007 1008 int WaterMark::queryFontSize(const QString& text, const QFont& font, int length) const 1009 { 1010 // Find font size using relative length compared to image width. 1011 1012 QFont fnt = font; 1013 QRect fontRect; 1014 1015 for (int i = 1 ; i <= 1000 ; ++i) 1016 { 1017 fnt.setPointSizeF(i); 1018 QFontMetrics fontMt(fnt); 1019 fontRect = fontMt.boundingRect(0, 0, image().width(), image().height(), 0, text); 1020 1021 if (fontRect.width() > lround((image().width() * length) / 100.0)) 1022 { 1023 return (i - 1); 1024 } 1025 } 1026 1027 return 0; 1028 } 1029 1030 } // namespace DigikamBqmWatermarkPlugin 1031 1032 #include "moc_watermark.cpp"