File indexing completed on 2025-01-19 03:53:17
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2008-08-11 0007 * Description : Raw import settings box 0008 * 0009 * SPDX-FileCopyrightText: 2008-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0010 * 0011 * SPDX-License-Identifier: GPL-2.0-or-later 0012 * 0013 * ============================================================ */ 0014 0015 #include "rawsettingsbox.h" 0016 0017 // Qt includes 0018 0019 #include <QButtonGroup> 0020 #include <QLabel> 0021 #include <QLayout> 0022 #include <QPushButton> 0023 #include <QString> 0024 #include <QToolBox> 0025 #include <QToolButton> 0026 #include <QIcon> 0027 #include <QTabWidget> 0028 0029 // KDE includes 0030 0031 #include <kconfiggroup.h> 0032 #include <ksharedconfig.h> 0033 #include <klocalizedstring.h> 0034 0035 // Local includes 0036 0037 #include "dlayoutbox.h" 0038 #include "dexpanderbox.h" 0039 #include "dnuminput.h" 0040 #include "colorgradientwidget.h" 0041 #include "histogrambox.h" 0042 #include "histogramwidget.h" 0043 #include "iccpreviewwidget.h" 0044 #include "imagecurves.h" 0045 #include "imagedialog.h" 0046 #include "imagehistogram.h" 0047 #include "digikam_globals.h" 0048 #include "digikam_debug.h" 0049 #include "drawdecoderwidget.h" 0050 0051 namespace DigikamRawImportNativePlugin 0052 { 0053 0054 class Q_DECL_HIDDEN RawSettingsBox::Private 0055 { 0056 public: 0057 0058 enum AllColorsColorType 0059 { 0060 AllColorsRed = 0, 0061 AllColorsGreen, 0062 AllColorsBlue 0063 }; 0064 0065 public: 0066 0067 explicit Private() 0068 : optionGroupName (QLatin1String("RAW Import Settings")), 0069 optionHistogramChannelEntry (QLatin1String("Histogram Channel")), 0070 optionHistogramScaleEntry (QLatin1String("Histogram Scale")), 0071 optionBrightnessEntry (QLatin1String("Brightness")), 0072 optionContrastEntry (QLatin1String("Contrast")), 0073 optionGammaEntry (QLatin1String("Gamma")), 0074 optionSaturationEntry (QLatin1String("Saturation")), 0075 optionMainExposureEntry (QLatin1String("MainExposure")), 0076 optionCurvePrefix (QLatin1String("RawCurve")), 0077 optionSettingsPageEntry (QLatin1String("Settings Page")), 0078 optionDecodingSettingsTabEntry (QLatin1String("Decoding Settings Tab")) 0079 { 0080 infoBox = nullptr; 0081 advExposureBox = nullptr; 0082 gammaLabel = nullptr; 0083 gammaInput = nullptr; 0084 saturationLabel = nullptr; 0085 saturationInput = nullptr; 0086 fineExposureLabel = nullptr; 0087 mainExposureInput = nullptr; 0088 contrastInput = nullptr; 0089 contrastLabel = nullptr; 0090 curveBox = nullptr; 0091 curveWidget = nullptr; 0092 resetCurveBtn = nullptr; 0093 decodingSettingsBox = nullptr; 0094 postProcessSettingsBox = nullptr; 0095 tabView = nullptr; 0096 abortBtn = nullptr; 0097 updateBtn = nullptr; 0098 rawdecodingBox = nullptr; 0099 brightnessLabel = nullptr; 0100 brightnessInput = nullptr; 0101 } 0102 0103 const QString optionGroupName; 0104 const QString optionHistogramChannelEntry; 0105 const QString optionHistogramScaleEntry; 0106 const QString optionBrightnessEntry; 0107 const QString optionContrastEntry; 0108 const QString optionGammaEntry; 0109 const QString optionSaturationEntry; 0110 const QString optionMainExposureEntry; 0111 const QString optionCurvePrefix; 0112 const QString optionSettingsPageEntry; 0113 const QString optionDecodingSettingsTabEntry; 0114 0115 QWidget* advExposureBox; 0116 QWidget* curveBox; 0117 QWidget* rawdecodingBox; 0118 0119 QLabel* brightnessLabel; 0120 QLabel* contrastLabel; 0121 QLabel* gammaLabel; 0122 QLabel* saturationLabel; 0123 QLabel* fineExposureLabel; 0124 0125 QPushButton* abortBtn; 0126 QPushButton* updateBtn; 0127 QPushButton* resetCurveBtn; 0128 0129 QTabWidget* tabView; 0130 0131 CurvesWidget* curveWidget; 0132 0133 ImageDialogPreview* infoBox; 0134 0135 DExpanderBox* postProcessSettingsBox; 0136 0137 DIntNumInput* contrastInput; 0138 DIntNumInput* brightnessInput; 0139 0140 DDoubleNumInput* gammaInput; 0141 DDoubleNumInput* saturationInput; 0142 DDoubleNumInput* mainExposureInput; 0143 0144 DRawDecoderWidget* decodingSettingsBox; 0145 }; 0146 0147 RawSettingsBox::RawSettingsBox(const QUrl& url, QWidget* const parent) 0148 : EditorToolSettings(parent), 0149 d (new Private) 0150 { 0151 setButtons(Default | Ok | Cancel); 0152 setTools(Histogram); 0153 setHistogramType(LRGBC); 0154 0155 QGridLayout* const gridSettings = new QGridLayout(plainPage()); 0156 d->tabView = new QTabWidget(plainPage()); 0157 0158 // - RAW Decoding view -------------------------------------------------------------- 0159 0160 d->rawdecodingBox = new QWidget(d->tabView); 0161 QGridLayout* const rawGrid = new QGridLayout(d->rawdecodingBox); 0162 d->decodingSettingsBox = new DRawDecoderWidget(d->rawdecodingBox, 0163 DRawDecoderWidget::SIXTEENBITS | 0164 DRawDecoderWidget::COLORSPACE); 0165 d->decodingSettingsBox->setObjectName(QLatin1String("RawSettingsBox Expander")); 0166 0167 // Note: do not touch the url edit's fileDialog() here. 0168 // This creates the file dialog, which involved an event loop, which is evil. 0169 // Adjust file dialog in slotFileDialogAboutToOpen 0170 0171 d->abortBtn = new QPushButton(d->rawdecodingBox); 0172 d->abortBtn->setText(i18n("Abort")); 0173 d->abortBtn->setIcon(QIcon::fromTheme(QLatin1String("dialog-cancel"))); 0174 d->abortBtn->setEnabled(false); 0175 d->abortBtn->setToolTip(i18n("Abort the current Raw image preview.")); 0176 0177 d->updateBtn = new QPushButton(d->rawdecodingBox); 0178 d->updateBtn->setText(i18nc("@action: refresh RAW preview", "Update")); 0179 d->updateBtn->setIcon(QIcon::fromTheme(QLatin1String("view-refresh"))); 0180 d->updateBtn->setEnabled(false); 0181 d->updateBtn->setToolTip(i18n("Generate a Raw image preview using current settings.")); 0182 0183 const int spacing = spacingHint(); 0184 0185 rawGrid->addWidget(d->decodingSettingsBox, 0, 0, 1, 3); 0186 rawGrid->addWidget(d->abortBtn, 1, 0, 1, 1); 0187 rawGrid->addWidget(d->updateBtn, 1, 2, 1, 1); 0188 rawGrid->setColumnStretch(1, 10); 0189 rawGrid->setContentsMargins(spacing, spacing, spacing, spacing); 0190 rawGrid->setSpacing(spacing); 0191 0192 // - Post-processing view -------------------------------------------------------------- 0193 0194 d->postProcessSettingsBox = new DExpanderBox(d->tabView); 0195 d->postProcessSettingsBox->setObjectName(QLatin1String("PostProcessingSettingsBox Expander")); 0196 0197 d->advExposureBox = new QWidget(d->postProcessSettingsBox); 0198 QGridLayout* const advExposureLayout = new QGridLayout(d->advExposureBox); 0199 0200 d->brightnessLabel = new QLabel(i18n("Brightness:"), d->advExposureBox); 0201 d->brightnessInput = new DIntNumInput(d->advExposureBox); 0202 d->brightnessInput->setRange(-100, 100, 1); 0203 d->brightnessInput->setDefaultValue(0); 0204 d->brightnessInput->setWhatsThis(i18n("Set here the brightness adjustment of the image.")); 0205 0206 d->contrastLabel = new QLabel(i18n("Contrast:"), d->advExposureBox); 0207 d->contrastInput = new DIntNumInput(d->advExposureBox); 0208 d->contrastInput->setRange(-100, 100, 1); 0209 d->contrastInput->setDefaultValue(0); 0210 d->contrastInput->setWhatsThis(i18n("Set here the contrast adjustment of the image.")); 0211 0212 d->gammaLabel = new QLabel(i18n("Gamma:"), d->advExposureBox); 0213 d->gammaInput = new DDoubleNumInput(d->advExposureBox); 0214 d->gammaInput->setDecimals(2); 0215 d->gammaInput->setRange(0.1, 3.0, 0.01); 0216 d->gammaInput->setDefaultValue(1.0); 0217 d->gammaInput->setWhatsThis(i18n("Set here the gamma adjustment of the image")); 0218 0219 d->saturationLabel = new QLabel(i18n("Saturation:"), d->advExposureBox); 0220 d->saturationInput = new DDoubleNumInput(d->advExposureBox); 0221 d->saturationInput->setDecimals(2); 0222 d->saturationInput->setRange(0.0, 2.0, 0.01); 0223 d->saturationInput->setDefaultValue(1.0); 0224 d->saturationInput->setWhatsThis(i18n("Set here the color saturation correction.")); 0225 0226 d->fineExposureLabel = new QLabel(i18n("Exposure (E.V):"), d->advExposureBox); 0227 d->mainExposureInput = new DDoubleNumInput(d->advExposureBox); 0228 d->mainExposureInput->setDecimals(2); 0229 d->mainExposureInput->setRange(-3.0, 3.0, 0.1); 0230 d->mainExposureInput->setDefaultValue(0.0); 0231 d->mainExposureInput->setWhatsThis(i18n("This value in E.V will be used to perform " 0232 "an exposure compensation of the image.")); 0233 0234 advExposureLayout->addWidget(d->brightnessLabel, 0, 0, 1, 1); 0235 advExposureLayout->addWidget(d->brightnessInput, 0, 1, 1, 2); 0236 advExposureLayout->addWidget(d->contrastLabel, 1, 0, 1, 1); 0237 advExposureLayout->addWidget(d->contrastInput, 1, 1, 1, 2); 0238 advExposureLayout->addWidget(d->gammaLabel, 2, 0, 1, 1); 0239 advExposureLayout->addWidget(d->gammaInput, 2, 1, 1, 2); 0240 advExposureLayout->addWidget(d->saturationLabel, 3, 0, 1, 1); 0241 advExposureLayout->addWidget(d->saturationInput, 3, 1, 1, 2); 0242 advExposureLayout->addWidget(d->fineExposureLabel, 4, 0, 1, 1); 0243 advExposureLayout->addWidget(d->mainExposureInput, 4, 1, 1, 2); 0244 advExposureLayout->setRowStretch(5, 10); 0245 advExposureLayout->setContentsMargins(spacing, spacing, spacing, spacing); 0246 advExposureLayout->setSpacing(0); 0247 0248 // --------------------------------------------------------------- 0249 0250 d->curveBox = new QWidget(d->postProcessSettingsBox); 0251 QGridLayout* const curveLayout = new QGridLayout(d->curveBox); 0252 0253 ColorGradientWidget* const vGradient = new ColorGradientWidget(Qt::Vertical, 10, d->curveBox); 0254 vGradient->setColors(QColor("white"), QColor("black")); 0255 0256 QLabel* const spacev = new QLabel(d->curveBox); 0257 spacev->setFixedWidth(1); 0258 0259 d->curveWidget = new CurvesWidget(256, 192, d->curveBox); 0260 d->curveWidget->setWhatsThis(i18n("This is the curve adjustment of the image luminosity")); 0261 0262 d->resetCurveBtn = new QPushButton(i18n("Reset"), d->curveBox); 0263 d->resetCurveBtn->setIcon(QIcon::fromTheme(QLatin1String("document-revert"))); 0264 d->resetCurveBtn->setToolTip(i18n("Reset curve to linear")); 0265 0266 QLabel* const spaceh = new QLabel(d->curveBox); 0267 spaceh->setFixedHeight(1); 0268 0269 ColorGradientWidget* const hGradient = new ColorGradientWidget(Qt::Horizontal, 10, d->curveBox); 0270 hGradient->setColors(QColor("black"), QColor("white")); 0271 0272 curveLayout->addWidget(vGradient, 0, 0, 1, 1); 0273 curveLayout->addWidget(spacev, 0, 1, 1, 1); 0274 curveLayout->addWidget(d->curveWidget, 0, 2, 1, 2); 0275 curveLayout->addWidget(spaceh, 1, 2, 1, 2); 0276 curveLayout->addWidget(hGradient, 2, 2, 1, 2); 0277 curveLayout->addWidget(d->resetCurveBtn, 3, 3, 1, 1); 0278 curveLayout->setRowStretch(4, 10); 0279 curveLayout->setColumnStretch(2, 10); 0280 curveLayout->setContentsMargins(spacing, spacing, spacing, spacing); 0281 curveLayout->setSpacing(0); 0282 0283 // --------------------------------------------------------------- 0284 0285 d->postProcessSettingsBox->addItem(d->advExposureBox, i18n("Exposure"), QLatin1String("exposure"), true); 0286 d->postProcessSettingsBox->addItem(d->curveBox, i18n("Luminosity Curve"), QLatin1String("luminositycurve"), false); 0287 d->postProcessSettingsBox->setItemIcon(0, QIcon::fromTheme(QLatin1String("contrast"))); 0288 d->postProcessSettingsBox->setItemIcon(1, QIcon::fromTheme(QLatin1String("adjustcurves"))); 0289 d->postProcessSettingsBox->addStretch(); 0290 0291 // - Image info view -------------------------------------------------------------- 0292 0293 d->infoBox = new ImageDialogPreview(d->postProcessSettingsBox); 0294 d->infoBox->slotShowPreview(url); 0295 0296 // --------------------------------------------------------------- 0297 0298 d->decodingSettingsBox->setItemIcon(DRawDecoderWidget::DEMOSAICING, 0299 QIcon::fromTheme(QLatin1String("image-x-adobe-dng"))); 0300 d->decodingSettingsBox->setItemIcon(DRawDecoderWidget::WHITEBALANCE, 0301 QIcon::fromTheme(QLatin1String("bordertool"))); 0302 d->decodingSettingsBox->setItemIcon(DRawDecoderWidget::CORRECTIONS, 0303 QIcon::fromTheme(QLatin1String("zoom-draw"))); 0304 d->decodingSettingsBox->setItemIcon(DRawDecoderWidget::COLORMANAGEMENT, 0305 QIcon::fromTheme(QLatin1String("preferences-desktop-display-color"))); 0306 d->decodingSettingsBox->updateMinimumWidth(); 0307 0308 d->tabView->insertTab(0, d->rawdecodingBox, i18n("Raw Decoding")); 0309 d->tabView->insertTab(1, d->postProcessSettingsBox, i18n("Post Processing")); 0310 d->tabView->insertTab(2, d->infoBox, i18n("Info")); 0311 0312 // --------------------------------------------------------------- 0313 0314 button(Default)->setText(i18n("Reset")); 0315 button(Default)->setIcon(QIcon::fromTheme(QLatin1String("document-revert"))); 0316 button(Default)->setToolTip(i18n("Reset all settings to default values.")); 0317 0318 button(Ok)->setText(i18n("Import")); 0319 button(Ok)->setIcon(QIcon::fromTheme(QLatin1String("dialog-ok-apply"))); 0320 button(Ok)->setToolTip(i18n("Import image to editor using current settings.")); 0321 0322 button(Cancel)->setText(i18n("Use Default")); 0323 button(Cancel)->setIcon(QIcon::fromTheme(QLatin1String("go-home"))); 0324 button(Cancel)->setToolTip(i18n("Use general Raw decoding settings to load this image in editor.")); 0325 0326 // --------------------------------------------------------------- 0327 0328 gridSettings->addWidget(d->tabView, 0, 0, 1, 5); 0329 gridSettings->setColumnStretch(2, 10); 0330 gridSettings->setContentsMargins(QMargins()); 0331 gridSettings->setSpacing(spacing); 0332 0333 // --------------------------------------------------------------- 0334 0335 connect(d->resetCurveBtn, SIGNAL(clicked()), 0336 this, SLOT(slotResetCurve())); 0337 0338 connect(d->updateBtn, SIGNAL(clicked()), 0339 this, SIGNAL(signalUpdatePreview())); 0340 0341 connect(d->abortBtn, SIGNAL(clicked()), 0342 this, SIGNAL(signalAbortPreview())); 0343 0344 connect(d->decodingSettingsBox, SIGNAL(signalSettingsChanged()), 0345 this, SLOT(slotDemosaicingChanged())); 0346 0347 connect(d->curveWidget, SIGNAL(signalCurvesChanged()), 0348 this, SIGNAL(signalPostProcessingChanged())); 0349 0350 connect(d->brightnessInput, SIGNAL(valueChanged(int)), 0351 this, SIGNAL(signalPostProcessingChanged())); 0352 0353 connect(d->contrastInput, SIGNAL(valueChanged(int)), 0354 this, SIGNAL(signalPostProcessingChanged())); 0355 0356 connect(d->gammaInput, SIGNAL(valueChanged(double)), 0357 this, SIGNAL(signalPostProcessingChanged())); 0358 0359 connect(d->saturationInput, SIGNAL(valueChanged(double)), 0360 this, SIGNAL(signalPostProcessingChanged())); 0361 0362 connect(d->mainExposureInput, SIGNAL(valueChanged(double)), 0363 this, SIGNAL(signalPostProcessingChanged())); 0364 0365 connect(d->decodingSettingsBox->inputProfileUrlEdit(), SIGNAL(signalOpenFileDialog()), 0366 this, SLOT(slotFileDialogAboutToOpen())); 0367 0368 connect(d->decodingSettingsBox->outputProfileUrlEdit(), SIGNAL(signalOpenFileDialog()), 0369 this, SLOT(slotFileDialogAboutToOpen())); 0370 } 0371 0372 RawSettingsBox::~RawSettingsBox() 0373 { 0374 delete d->curveWidget; 0375 delete d; 0376 } 0377 0378 void RawSettingsBox::slotDemosaicingChanged() 0379 { 0380 enableUpdateBtn(true); 0381 } 0382 0383 void RawSettingsBox::enableUpdateBtn(bool b) 0384 { 0385 d->updateBtn->setEnabled(b); 0386 } 0387 0388 bool RawSettingsBox::updateBtnEnabled() const 0389 { 0390 return d->updateBtn->isEnabled(); 0391 } 0392 0393 void RawSettingsBox::setBusy(bool b) 0394 { 0395 d->decodingSettingsBox->setEnabled(!b); 0396 d->abortBtn->setEnabled(b); 0397 } 0398 0399 void RawSettingsBox::setDemosaicedImage(DImg& img) 0400 { 0401 d->curveWidget->stopHistogramComputation(); 0402 d->curveWidget->updateData(img); 0403 } 0404 0405 void RawSettingsBox::setPostProcessedImage(const DImg& img) 0406 { 0407 histogramBox()->histogram()->stopHistogramComputation(); 0408 histogramBox()->histogram()->updateData(img); 0409 } 0410 0411 void RawSettingsBox::resetSettings() 0412 { 0413 d->decodingSettingsBox->resetToDefault(); 0414 d->brightnessInput->slotReset(); 0415 d->contrastInput->slotReset(); 0416 d->gammaInput->slotReset(); 0417 d->saturationInput->slotReset(); 0418 d->mainExposureInput->slotReset(); 0419 slotResetCurve(); 0420 } 0421 0422 void RawSettingsBox::slotResetCurve() 0423 { 0424 d->curveWidget->reset(); 0425 Q_EMIT signalPostProcessingChanged(); 0426 } 0427 0428 CurvesWidget* RawSettingsBox::curvesWidget() const 0429 { 0430 return d->curveWidget; 0431 } 0432 0433 void RawSettingsBox::readSettings() 0434 { 0435 KSharedConfig::Ptr config = KSharedConfig::openConfig(); 0436 KConfigGroup group = config->group(d->optionGroupName); 0437 0438 histogramBox()->setChannel((ChannelType)group.readEntry(d->optionHistogramChannelEntry, 0439 (int) LuminosityChannel)); 0440 histogramBox()->setScale((HistogramScale)group.readEntry(d->optionHistogramScaleEntry, 0441 (int) LogScaleHistogram)); 0442 curvesWidget()->setScaleType((HistogramScale)group.readEntry(d->optionHistogramScaleEntry, 0443 (int) LogScaleHistogram)); 0444 0445 d->decodingSettingsBox->readSettings(group); 0446 0447 d->brightnessInput->setValue(group.readEntry(d->optionBrightnessEntry, 0)); 0448 d->contrastInput->setValue(group.readEntry(d->optionContrastEntry, 0)); 0449 d->gammaInput->setValue(group.readEntry(d->optionGammaEntry, 1.0)); 0450 d->saturationInput->setValue(group.readEntry(d->optionSaturationEntry, 1.0)); 0451 d->mainExposureInput->setValue(group.readEntry(d->optionMainExposureEntry, 0.0)); 0452 0453 d->curveWidget->restoreCurve(group, d->optionCurvePrefix); 0454 0455 d->tabView->setCurrentIndex(group.readEntry(d->optionSettingsPageEntry, 0)); 0456 0457 d->postProcessSettingsBox->readSettings(group); 0458 } 0459 0460 void RawSettingsBox::writeSettings() 0461 { 0462 KSharedConfig::Ptr config = KSharedConfig::openConfig(); 0463 KConfigGroup group = config->group(d->optionGroupName); 0464 0465 group.writeEntry(d->optionHistogramChannelEntry, (int)histogramBox()->channel()); 0466 group.writeEntry(d->optionHistogramScaleEntry, (int)histogramBox()->scale()); 0467 0468 d->decodingSettingsBox->writeSettings(group); 0469 0470 group.writeEntry(d->optionBrightnessEntry, d->brightnessInput->value()); 0471 group.writeEntry(d->optionContrastEntry, d->contrastInput->value()); 0472 group.writeEntry(d->optionGammaEntry, d->gammaInput->value()); 0473 group.writeEntry(d->optionSaturationEntry, d->saturationInput->value()); 0474 group.writeEntry(d->optionMainExposureEntry, d->mainExposureInput->value()); 0475 0476 d->curveWidget->saveCurve(group, d->optionCurvePrefix); 0477 0478 group.writeEntry(d->optionSettingsPageEntry, d->tabView->currentIndex()); 0479 0480 d->postProcessSettingsBox->writeSettings(group); 0481 0482 group.sync(); 0483 } 0484 0485 DRawDecoding RawSettingsBox::settings() const 0486 { 0487 DRawDecoding settings(d->decodingSettingsBox->settings()); 0488 0489 settings.bcg.brightness = (double)d->brightnessInput->value() / 250.0; 0490 settings.bcg.contrast = (double)(d->contrastInput->value() / 100.0) + 1.00; 0491 settings.bcg.gamma = d->gammaInput->value(); 0492 settings.wb.saturation = d->saturationInput->value(); 0493 settings.wb.expositionMain = d->mainExposureInput->value(); 0494 0495 if (d->curveWidget->curves()->isDirty()) 0496 { 0497 d->curveWidget->curves()->curvesCalculateAllCurves(); 0498 settings.curvesAdjust = d->curveWidget->curves()->getContainer(); 0499 } 0500 0501 return settings; 0502 } 0503 0504 void RawSettingsBox::slotFileDialogAboutToOpen() 0505 { 0506 //TODO : port to Qt5 0507 //requester->fileDialog()->setPreviewWidget(new ICCPreviewWidget(requester)); 0508 } 0509 0510 } // namespace DigikamRawImportNativePlugin 0511 0512 #include "moc_rawsettingsbox.cpp"