1
/* ============================================================
3
* This file is a part of digiKam project
4
* http://www.digikam.org
7
* Description : White Balance settings view.
9
* Copyright (C) 2010 by Gilles Caulier <caulier dot gilles at gmail dot com>
11
* This program is free software; you can redistribute it
12
* and/or modify it under the terms of the GNU General
13
* Public License as published by the Free Software Foundation;
14
* either version 2, or (at your option)
17
* This program is distributed in the hope that it will be useful,
18
* but WITHOUT ANY WARRANTY; without even the implied warranty of
19
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20
* GNU General Public License for more details.
22
* ============================================================ */
24
#include "wbsettings.moc"
29
#include <QButtonGroup>
32
#include <QGridLayout>
34
#include <QHBoxLayout>
37
#include <QTextStream>
38
#include <QToolButton>
39
#include <QVBoxLayout>
47
#include <kapplication.h>
48
#include <kfiledialog.h>
50
#include <kglobalsettings.h>
51
#include <kmessagebox.h>
52
#include <kstandarddirs.h>
53
#include <kcombobox.h>
54
#include <kseparator.h>
55
#include <kiconloader.h>
59
#include <libkdcraw/rcombobox.h>
60
#include <libkdcraw/rnuminput.h>
61
#include <libkdcraw/rexpanderbox.h>
63
using namespace KDcrawIface;
73
enum TemperaturePreset
94
DefaultTemperature(DaylightD65),
96
autoAdjustExposure(0),
97
adjTemperatureLabel(0),
98
temperaturePresetLabel(0),
101
mainExposureLabel(0),
102
fineExposureLabel(0),
108
temperaturePresetCB(0),
112
mainExposureInput(0),
113
fineExposureInput(0),
119
static const QString configDarkInputEntry;
120
static const QString configBlackInputEntry;
121
static const QString configMainExposureEntry;
122
static const QString configFineExposureEntry;
123
static const QString configGammaInputEntry;
124
static const QString configSaturationInputEntry;
125
static const QString configGreenInputEntry;
126
static const QString configTemperatureInputEntry;
128
const int DefaultTemperature;
130
QToolButton* pickTemperature;
131
QToolButton* autoAdjustExposure;
133
QLabel* adjTemperatureLabel;
134
QLabel* temperaturePresetLabel;
137
QLabel* mainExposureLabel;
138
QLabel* fineExposureLabel;
140
QLabel* saturationLabel;
142
QLabel* exposureLabel;
143
QLabel* temperatureLabel;
145
RComboBox* temperaturePresetCB;
147
RDoubleNumInput* temperatureInput;
148
RDoubleNumInput* darkInput;
149
RDoubleNumInput* blackInput;
150
RDoubleNumInput* mainExposureInput;
151
RDoubleNumInput* fineExposureInput;
152
RDoubleNumInput* gammaInput;
153
RDoubleNumInput* saturationInput;
154
RDoubleNumInput* greenInput;
158
QString addTemperatureDescription(const QString& desc, TemperaturePreset preset)
160
int index = temperaturePresetCB->combo()->findData((int)preset);
161
QString itemText = temperaturePresetCB->combo()->itemText(index);
162
QString tempDesc = QString("<p><b>%1</b>: %2 (%3K).</p>")
169
tempDesc.remove(QRegExp("\\(.*\\)"));
175
const QString WBSettingsPriv::configDarkInputEntry("Dark");
176
const QString WBSettingsPriv::configBlackInputEntry("Black");
177
const QString WBSettingsPriv::configMainExposureEntry("MainExposure");
178
const QString WBSettingsPriv::configFineExposureEntry("FineExposure");
179
const QString WBSettingsPriv::configGammaInputEntry("Gamma");
180
const QString WBSettingsPriv::configSaturationInputEntry("Saturation");
181
const QString WBSettingsPriv::configGreenInputEntry("Green");
182
const QString WBSettingsPriv::configTemperatureInputEntry("Temperature");
184
// --------------------------------------------------------
186
WBSettings::WBSettings(QWidget* parent)
188
d(new WBSettingsPriv)
190
QGridLayout* grid = new QGridLayout(parent);
192
d->temperatureLabel = new QLabel(i18n("<a href='http://en.wikipedia.org/wiki/Color_temperature'>"
193
"Color Temperature</a> (K): "));
194
d->temperatureLabel->setOpenExternalLinks(true);
196
d->adjTemperatureLabel = new QLabel(i18n("Adjustment:"));
197
d->temperatureInput = new RDoubleNumInput;
198
d->temperatureInput->setDecimals(1);
199
d->temperatureInput->input()->setRange(1750.0, 12000.0, 10.0);
200
d->temperatureInput->setDefaultValue((double)d->DefaultTemperature);
201
d->temperatureInput->setWhatsThis( i18n("Set here the white balance color temperature in Kelvin."));
203
d->temperaturePresetLabel = new QLabel(i18n("Preset:"));
204
d->temperaturePresetCB = new RComboBox;
205
d->temperaturePresetCB->combo()->addItem(i18n("40W Lamp"), QVariant(d->Lamp40W));
206
d->temperaturePresetCB->combo()->addItem(i18n("100W Lamp"), QVariant(d->Lamp100W));
207
d->temperaturePresetCB->combo()->addItem(i18n("200W Lamp"), QVariant(d->Lamp200W));
208
d->temperaturePresetCB->combo()->addItem(i18n("Candle"), QVariant(d->Candle));
209
d->temperaturePresetCB->combo()->addItem(i18n("Daylight D50"), QVariant(d->DaylightD50));
210
d->temperaturePresetCB->combo()->addItem(i18n("Daylight D65"), QVariant(d->DaylightD65));
211
d->temperaturePresetCB->combo()->addItem(i18n("Moonlight"), QVariant(d->MoonLight));
212
d->temperaturePresetCB->combo()->addItem(i18n("Neutral"), QVariant(d->Neutral));
213
d->temperaturePresetCB->combo()->addItem(i18n("Photo Flash"), QVariant(d->Flash));
214
d->temperaturePresetCB->combo()->addItem(i18n("Studio Lamp"), QVariant(d->StudioLamp));
215
d->temperaturePresetCB->combo()->addItem(i18n("Sun"), QVariant(d->Sun));
216
d->temperaturePresetCB->combo()->addItem(i18n("Sunrise"), QVariant(d->Sunrise));
217
d->temperaturePresetCB->combo()->addItem(i18n("Xenon Lamp"), QVariant(d->XenonLamp));
218
d->temperaturePresetCB->combo()->addItem(i18nc("no temperature preset", "None"), QVariant(d->None));
219
d->temperaturePresetCB->setDefaultIndex(d->temperaturePresetCB->combo()->findData(QVariant(d->DefaultTemperature)));
221
QString toolTip = QString("<p>%1</p>").arg(i18n("Select the white balance color temperature preset to use."));
222
toolTip += d->addTemperatureDescription(i18n("40 Watt incandescent lamp"), d->Lamp40W);
223
toolTip += d->addTemperatureDescription(i18n("100 Watt incandescent lamp"), d->Lamp100W);
224
toolTip += d->addTemperatureDescription(i18n("200 Watt incandescent lamp"), d->Lamp200W);
225
toolTip += d->addTemperatureDescription(i18n("candle light"), d->Candle);
226
toolTip += d->addTemperatureDescription(i18n("sunny daylight around noon"), d->DaylightD50);
227
toolTip += d->addTemperatureDescription(i18n("overcast sky light"), d->DaylightD65);
228
toolTip += d->addTemperatureDescription(i18n("moon light"), d->MoonLight);
229
toolTip += d->addTemperatureDescription(i18n("neutral color temperature"), d->Neutral);
230
toolTip += d->addTemperatureDescription(i18n("electronic photo flash"), d->Flash);
231
toolTip += d->addTemperatureDescription(i18n("tungsten lamp used in photo studio or "
232
"light at 1 hour from dusk/dawn"), d->StudioLamp);
233
toolTip += d->addTemperatureDescription(i18n("effective sun temperature"), d->Sun);
234
toolTip += d->addTemperatureDescription(i18n("sunrise or sunset light"), d->Sunrise);
235
toolTip += d->addTemperatureDescription(i18n("xenon lamp or light arc"), d->XenonLamp);
236
toolTip += d->addTemperatureDescription(i18n("no preset value"), d->None);
237
d->temperaturePresetCB->setToolTip(toolTip);
239
d->pickTemperature = new QToolButton;
240
d->pickTemperature->setIcon(KIcon("color-picker-grey"));
241
d->pickTemperature->setCheckable(true);
242
d->pickTemperature->setToolTip( i18n( "Temperature tone color picker." ) );
243
d->pickTemperature->setWhatsThis(i18n("With this button, you can pick the color from the original "
244
"image used to set the white color balance temperature and "
245
"green component."));
247
KSeparator* line = new KSeparator(Qt::Horizontal);
249
// -------------------------------------------------------------
251
d->blackLabel = new QLabel(i18n("Black point:"));
252
d->blackInput = new RDoubleNumInput;
253
d->blackInput->setDecimals(2);
254
d->blackInput->input()->setRange(0.0, 0.05, 0.01, true);
255
d->blackInput->setWhatsThis( i18n("Set here the black level value."));
256
d->blackInput->setDefaultValue(0.0);
258
d->darkLabel = new QLabel(i18n("Shadows:"));
259
d->darkInput = new RDoubleNumInput;
260
d->darkInput->setDecimals(2);
261
d->darkInput->input()->setRange(0.0, 1.0, 0.01, true);
262
d->darkInput->setDefaultValue(0.5);
263
d->darkInput->setWhatsThis( i18n("Set here the shadow noise suppression level."));
265
d->saturationLabel = new QLabel(i18n("Saturation:"));
266
d->saturationInput = new RDoubleNumInput;
267
d->saturationInput->setDecimals(2);
268
d->saturationInput->input()->setRange(0.0, 2.0, 0.01, true);
269
d->saturationInput->setDefaultValue(1.0);
270
d->saturationInput->setWhatsThis( i18n("Set here the saturation value."));
272
d->gammaLabel = new QLabel(i18n("Gamma:"));
273
d->gammaInput = new RDoubleNumInput;
274
d->gammaInput->setDecimals(2);
275
d->gammaInput->input()->setRange(0.1, 3.0, 0.01, true);
276
d->gammaInput->setDefaultValue(1.0);
277
d->gammaInput->setWhatsThis( i18n("Set here the gamma correction value."));
279
d->greenLabel = new QLabel(i18n("Green:"));
280
d->greenInput = new RDoubleNumInput;
281
d->greenInput->setDecimals(2);
282
d->greenInput->input()->setRange(0.2, 2.5, 0.01, true);
283
d->greenInput->setDefaultValue(1.0);
284
d->greenInput->setWhatsThis(i18n("Set here the green component to control the magenta color "
285
"cast removal level."));
287
KSeparator* line2 = new KSeparator(Qt::Horizontal);
289
// -------------------------------------------------------------
291
d->exposureLabel = new QLabel(i18n("<a href='http://en.wikipedia.org/wiki/Exposure_value'>"
292
"Exposure Compensation</a> (E.V): "));
293
d->exposureLabel->setOpenExternalLinks(true);
295
d->mainExposureLabel = new QLabel(i18nc("main exposure value", "Main:"));
296
d->autoAdjustExposure = new QToolButton;
297
d->autoAdjustExposure->setIcon(KIconLoader::global()->loadIcon("system-run", KIconLoader::Toolbar));
298
d->autoAdjustExposure->setToolTip( i18n( "Auto exposure adjustments" ) );
299
d->autoAdjustExposure->setWhatsThis(i18n("With this button, you can automatically adjust Exposure "
300
"and Black Point values."));
301
d->mainExposureInput = new RDoubleNumInput;
302
d->mainExposureInput->setDecimals(2);
303
d->mainExposureInput->input()->setRange(-6.0, 8.0, 0.1, true);
304
d->mainExposureInput->setDefaultValue(0.0);
305
d->mainExposureInput->setWhatsThis( i18n("Set here the main exposure compensation value in E.V."));
307
d->fineExposureLabel = new QLabel(i18nc("fine exposure adjustment", "Fine:"));
308
d->fineExposureInput = new RDoubleNumInput;
309
d->fineExposureInput->setDecimals(2);
310
d->fineExposureInput->input()->setRange(-0.5, 0.5, 0.01, true);
311
d->fineExposureInput->setDefaultValue(0.0);
312
d->fineExposureInput->setWhatsThis(i18n("This value in E.V will be added to main exposure "
313
"compensation value to set fine exposure adjustment."));
315
// -------------------------------------------------------------
317
grid->addWidget(d->temperatureLabel, 0, 0, 1, 6);
318
grid->addWidget(d->adjTemperatureLabel, 1, 0, 1, 1);
319
grid->addWidget(d->pickTemperature, 1, 1, 1, 1);
320
grid->addWidget(d->temperatureInput, 1, 2, 1, 4);
321
grid->addWidget(d->temperaturePresetLabel, 2, 0, 1, 1);
322
grid->addWidget(d->temperaturePresetCB, 2, 2, 1, 4);
323
grid->addWidget(line, 3, 0, 1, 6);
324
grid->addWidget(d->blackLabel, 4, 0, 1, 1);
325
grid->addWidget(d->blackInput, 4, 1, 1, 5);
326
grid->addWidget(d->darkLabel, 5, 0, 1, 1);
327
grid->addWidget(d->darkInput, 5, 1, 1, 5);
328
grid->addWidget(d->saturationLabel, 6, 0, 1, 1);
329
grid->addWidget(d->saturationInput, 6, 1, 1, 5);
330
grid->addWidget(d->gammaLabel, 7, 0, 1, 1);
331
grid->addWidget(d->gammaInput, 7, 1, 1, 5);
332
grid->addWidget(d->greenLabel, 8, 0, 1, 1);
333
grid->addWidget(d->greenInput, 8, 1, 1, 5);
334
grid->addWidget(line2, 9, 0, 1, 6);
335
grid->addWidget(d->exposureLabel, 10, 0, 1, 6);
336
grid->addWidget(d->mainExposureLabel, 11, 0, 1, 1);
337
grid->addWidget(d->autoAdjustExposure, 11, 1, 1, 1);
338
grid->addWidget(d->mainExposureInput, 11, 2, 1, 4);
339
grid->addWidget(d->fineExposureLabel, 12, 0, 1, 2);
340
grid->addWidget(d->fineExposureInput, 12, 2, 1, 4);
341
grid->setRowStretch(13, 10);
342
grid->setMargin(KDialog::spacingHint());
343
grid->setSpacing(KDialog::spacingHint());
345
// -------------------------------------------------------------
347
connect(d->temperaturePresetCB, SIGNAL(activated(int)),
348
this, SLOT(slotTemperaturePresetChanged(int)));
350
connect(d->temperatureInput, SIGNAL(valueChanged(double)),
351
this, SLOT(slotTemperatureChanged(double)));
353
connect(d->darkInput, SIGNAL(valueChanged(double)),
354
this, SIGNAL(signalSettingsChanged()));
356
connect(d->blackInput, SIGNAL(valueChanged(double)),
357
this, SIGNAL(signalSettingsChanged()));
359
connect(d->mainExposureInput, SIGNAL(valueChanged(double)),
360
this, SIGNAL(signalSettingsChanged()));
362
connect(d->fineExposureInput, SIGNAL(valueChanged(double)),
363
this, SIGNAL(signalSettingsChanged()));
365
connect(d->gammaInput, SIGNAL(valueChanged(double)),
366
this, SIGNAL(signalSettingsChanged()));
368
connect(d->saturationInput, SIGNAL(valueChanged(double)),
369
this, SIGNAL(signalSettingsChanged()));
371
connect(d->greenInput, SIGNAL(valueChanged(double)),
372
this, SIGNAL(signalSettingsChanged()));
374
connect(d->autoAdjustExposure, SIGNAL(clicked()),
375
this, SIGNAL(signalAutoAdjustExposure()));
377
connect(d->pickTemperature, SIGNAL(released()),
378
this, SIGNAL(signalPickerColorButtonActived()));
381
WBSettings::~WBSettings()
386
bool WBSettings::pickTemperatureIsOn()
388
return d->pickTemperature->isChecked();
391
void WBSettings::setOnPickTemperature(bool b)
393
d->pickTemperature->setChecked(b);
396
void WBSettings::showAdvancedButtons(bool b)
398
d->pickTemperature->setVisible(b);
399
d->autoAdjustExposure->setVisible(b);
402
void WBSettings::slotTemperatureChanged(double temperature)
404
int index = d->temperaturePresetCB->combo()->findData(QVariant((int)temperature));
408
index = d->temperaturePresetCB->combo()->findData(QVariant((int)d->None));
411
d->temperaturePresetCB->setCurrentIndex(index);
413
emit signalSettingsChanged();
416
void WBSettings::slotTemperaturePresetChanged(int tempPreset)
419
int temperature = d->temperaturePresetCB->combo()->itemData(tempPreset).toInt(&ok);
423
temperature = d->DefaultTemperature;
426
if (temperature != -1)
428
d->temperatureInput->setValue((double)temperature);
431
emit signalSettingsChanged();
434
WBContainer WBSettings::settings() const
438
prm.black = d->blackInput->value();
439
prm.exposition = d->mainExposureInput->value() + d->fineExposureInput->value();
440
prm.temperature = d->temperatureInput->value();
441
prm.green = d->greenInput->value();
442
prm.dark = d->darkInput->value();
443
prm.gamma = d->gammaInput->value();
444
prm.saturation = d->saturationInput->value();
449
void WBSettings::setSettings(const WBContainer& settings)
453
d->blackInput->setValue(settings.black);
454
d->mainExposureInput->setValue(double(int(settings.exposition)));
455
d->fineExposureInput->setValue(settings.exposition - d->mainExposureInput->value());
456
d->temperatureInput->setValue(settings.temperature);
457
d->greenInput->setValue(settings.green);
458
d->darkInput->setValue(settings.dark);
459
d->gammaInput->setValue(settings.gamma);
460
d->saturationInput->setValue(settings.saturation);
461
slotTemperatureChanged(d->temperatureInput->value());
466
void WBSettings::resetToDefault()
470
// Neutral color temperature settings is D65.
471
d->blackInput->slotReset();
472
d->darkInput->slotReset();
473
d->fineExposureInput->slotReset();
474
d->gammaInput->slotReset();
475
d->greenInput->slotReset();
476
d->mainExposureInput->slotReset();
477
d->saturationInput->slotReset();
478
d->temperatureInput->slotReset();
479
d->temperaturePresetCB->slotReset();
480
slotTemperaturePresetChanged(d->temperaturePresetCB->defaultIndex());
485
WBContainer WBSettings::defaultSettings() const
489
prm.black = d->blackInput->defaultValue();
490
prm.exposition = d->mainExposureInput->defaultValue() + d->fineExposureInput->defaultValue();
491
prm.temperature = d->temperatureInput->defaultValue();
492
prm.green = d->greenInput->defaultValue();
493
prm.dark = d->darkInput->defaultValue();
494
prm.gamma = d->gammaInput->defaultValue();
495
prm.saturation = d->saturationInput->defaultValue();
500
void WBSettings::readSettings(KConfigGroup& group)
503
// WBContainer defaultPrm = defaultSettings();
505
prm.black = group.readEntry(d->configBlackInputEntry, d->blackInput->defaultValue());
506
prm.temperature = group.readEntry(d->configTemperatureInputEntry, d->temperatureInput->defaultValue());
507
prm.green = group.readEntry(d->configGreenInputEntry, d->greenInput->defaultValue());
508
prm.dark = group.readEntry(d->configDarkInputEntry, d->darkInput->defaultValue());
509
prm.gamma = group.readEntry(d->configGammaInputEntry, d->gammaInput->defaultValue());
510
prm.saturation = group.readEntry(d->configSaturationInputEntry, d->saturationInput->defaultValue());
511
double fineExpo = group.readEntry(d->configFineExposureEntry, d->fineExposureInput->defaultValue());
512
prm.exposition = group.readEntry(d->configMainExposureEntry, d->mainExposureInput->defaultValue()) + fineExpo;
517
void WBSettings::writeSettings(KConfigGroup& group)
519
// WBContainer prm = settings();
521
group.writeEntry(d->configDarkInputEntry, d->darkInput->value());
522
group.writeEntry(d->configBlackInputEntry, d->blackInput->value());
523
group.writeEntry(d->configMainExposureEntry, d->mainExposureInput->value());
524
group.writeEntry(d->configFineExposureEntry, d->fineExposureInput->value());
525
group.writeEntry(d->configGammaInputEntry, d->gammaInput->value());
526
group.writeEntry(d->configSaturationInputEntry, d->saturationInput->value());
527
group.writeEntry(d->configGreenInputEntry, d->greenInput->value());
528
group.writeEntry(d->configTemperatureInputEntry, d->temperatureInput->value());
531
void WBSettings::loadSettings()
533
KUrl loadWhiteBalanceFile = KFileDialog::getOpenUrl(KGlobalSettings::documentPath(),
534
QString( "*" ), kapp->activeWindow(),
535
QString(i18n("White Color Balance Settings File to Load")));
537
if (loadWhiteBalanceFile.isEmpty())
542
QFile file(loadWhiteBalanceFile.toLocalFile());
544
if (file.open(QIODevice::ReadOnly))
546
QTextStream stream(&file);
548
if (stream.readLine() != "# White Color Balance Configuration File V2")
550
KMessageBox::error(kapp->activeWindow(),
551
i18n("\"%1\" is not a White Color Balance settings text file.",
552
loadWhiteBalanceFile.fileName()));
558
d->temperatureInput->setValue(stream.readLine().toDouble());
559
d->darkInput->setValue(stream.readLine().toDouble());
560
d->blackInput->setValue(stream.readLine().toDouble());
561
d->mainExposureInput->setValue(stream.readLine().toDouble());
562
d->fineExposureInput->setValue(stream.readLine().toDouble());
563
d->gammaInput->setValue(stream.readLine().toDouble());
564
d->saturationInput->setValue(stream.readLine().toDouble());
565
d->greenInput->setValue(stream.readLine().toDouble());
566
slotTemperatureChanged(d->temperatureInput->value());
571
KMessageBox::error(kapp->activeWindow(),
572
i18n("Cannot load settings from the White Color Balance text file."));
578
void WBSettings::saveAsSettings()
580
KUrl saveWhiteBalanceFile = KFileDialog::getSaveUrl(KGlobalSettings::documentPath(),
581
QString( "*" ), kapp->activeWindow(),
582
QString( i18n("White Color Balance Settings File to Save")));
584
if ( saveWhiteBalanceFile.isEmpty() )
589
QFile file(saveWhiteBalanceFile.toLocalFile());
591
if ( file.open(QIODevice::WriteOnly) )
593
QTextStream stream( &file );
594
stream << "# White Color Balance Configuration File V2\n";
595
stream << d->temperatureInput->value() << "\n";
596
stream << d->darkInput->value() << "\n";
597
stream << d->blackInput->value() << "\n";
598
stream << d->mainExposureInput->value() << "\n";
599
stream << d->fineExposureInput->value() << "\n";
600
stream << d->gammaInput->value() << "\n";
601
stream << d->saturationInput->value() << "\n";
602
stream << d->greenInput->value() << "\n";
606
KMessageBox::error(kapp->activeWindow(),
607
i18n("Cannot save settings to the White Color Balance text file."));
613
} // namespace Digikam