1 /* ============================================================
2  *
3  * This file is a part of digiKam project
4  * https://www.digikam.org
5  *
6  * Date        : 2012-02-05
7  * Description : film color negative inverter tool
8  *
9  * Copyright (C) 2012 by Matthias Welwarsky <matthias at welwarsky dot de>
10  *
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)
15  * any later version.
16  *
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.
21  *
22  * ============================================================ */
23 
24 #include "filmtool.h"
25 
26 // C++ includes
27 
28 #include <cmath>
29 
30 // Qt includes
31 
32 #include <QButtonGroup>
33 #include <QColor>
34 #include <QGridLayout>
35 #include <QGroupBox>
36 #include <QHBoxLayout>
37 #include <QLabel>
38 #include <QPushButton>
39 #include <QTimer>
40 #include <QToolButton>
41 #include <QListWidget>
42 #include <QCheckBox>
43 #include <QIcon>
44 
45 // KDE includes
46 
47 #include <klocalizedstring.h>
48 #include <ksharedconfig.h>
49 #include <kconfiggroup.h>
50 
51 // Local includes
52 
53 #include "dnuminput.h"
54 #include "dgradientslider.h"
55 #include "dimg.h"
56 #include "editortoolsettings.h"
57 #include "histogrambox.h"
58 #include "histogramwidget.h"
59 #include "imagehistogram.h"
60 #include "imageiface.h"
61 #include "imagelevels.h"
62 #include "imageregionwidget.h"
63 #include "filmfilter_p.h"
64 
65 namespace DigikamEditorFilmToolPlugin
66 {
67 
68 class Q_DECL_HIDDEN FilmTool::Private
69 {
70 
71 public:
72 
73     enum ColorPicker
74     {
75         NoPicker   = 0,
76         OrangeMask = 1
77     };
78 
79 public:
80 
Private()81     explicit Private()
82       : histoSegments(0),
83         resetButton(nullptr),
84         pickWhitePoint(nullptr),
85         autoButton(nullptr),
86         exposureInput(nullptr),
87         gammaInput(nullptr),
88         cnType(nullptr),
89         colorBalanceInput(nullptr),
90         levelsHistogramWidget(nullptr),
91         redInputLevels(nullptr),
92         greenInputLevels(nullptr),
93         blueInputLevels(nullptr),
94         previewWidget(nullptr),
95         levels(nullptr),
96         originalImage(nullptr),
97         gboxSettings(nullptr)
98     {
99     }
100 
101     static const QString configGroupName;
102     static const QString configGammaInputEntry;
103     static const QString configExposureEntry;
104     static const QString configFilmProfileEntry;
105     static const QString configFilmProfileName;
106     static const QString configWhitePointEntry;
107     static const QString configHistogramChannelEntry;
108     static const QString configHistogramScaleEntry;
109     static const QString configApplyColorBalance;
110 
111     int                  histoSegments;
112 
113     QPushButton*         resetButton;
114     QToolButton*         pickWhitePoint;
115     QToolButton*         autoButton;
116 
117     FilmContainer        filmContainer;
118 
119     DDoubleNumInput*     exposureInput;
120     DDoubleNumInput*     gammaInput;
121     QListWidget*         cnType;
122     QCheckBox*           colorBalanceInput;
123 
124     HistogramWidget*     levelsHistogramWidget;
125 
126     DGradientSlider*     redInputLevels;
127     DGradientSlider*     greenInputLevels;
128     DGradientSlider*     blueInputLevels;
129 
130     ImageRegionWidget*   previewWidget;
131 
132     ImageLevels*         levels;
133 
134     DImg*                originalImage;
135 
136     EditorToolSettings*  gboxSettings;
137 };
138 
139 const QString FilmTool::Private::configGroupName(QLatin1String("film Tool"));
140 const QString FilmTool::Private::configGammaInputEntry(QLatin1String("GammaInput"));
141 const QString FilmTool::Private::configExposureEntry(QLatin1String("Exposure"));
142 const QString FilmTool::Private::configFilmProfileEntry(QLatin1String("FilmProfile"));
143 const QString FilmTool::Private::configFilmProfileName(QLatin1String("FilmProfileName"));
144 const QString FilmTool::Private::configWhitePointEntry(QLatin1String("WhitePoint_%1"));
145 const QString FilmTool::Private::configHistogramChannelEntry(QLatin1String("Histogram Channel"));
146 const QString FilmTool::Private::configHistogramScaleEntry(QLatin1String("Histogram Scale"));
147 const QString FilmTool::Private::configApplyColorBalance(QLatin1String("Apply Color Balance"));
148 
149 // --------------------------------------------------------
150 
FilmTool(QObject * const parent)151 FilmTool::FilmTool(QObject* const parent)
152     : EditorToolThreaded(parent),
153       d(new Private)
154 {
155     setObjectName(QLatin1String("film"));
156     setToolName(i18n("Color Negative Film"));
157     setToolIcon(QIcon::fromTheme(QLatin1String("colorneg")));
158     setInitPreview(true);
159 
160     ImageIface iface;
161     d->originalImage = iface.original();
162 
163     d->histoSegments = d->originalImage->sixteenBit() ? 65535 : 255;
164     d->levels        = new ImageLevels(d->originalImage->sixteenBit());
165 
166     // -------------------------------------------------------------
167 
168     d->previewWidget = new ImageRegionWidget;
169     setToolView(d->previewWidget);
170     setPreviewModeMask(PreviewToolBar::AllPreviewModes);
171 
172     // -------------------------------------------------------------
173 
174     d->gboxSettings = new EditorToolSettings(nullptr);
175     d->gboxSettings->setButtons(EditorToolSettings::Default|
176                                 EditorToolSettings::Ok|
177                                 EditorToolSettings::Cancel);
178 
179     d->gboxSettings->setTools(EditorToolSettings::Histogram);
180     d->gboxSettings->setHistogramType(LRGBC);
181 
182     // we don't need to use the Gradient in this tool
183 
184     d->gboxSettings->histogramBox()->setGradientVisible(false);
185     d->gboxSettings->histogramBox()->setChannel(ColorChannels);
186 
187     // -------------------------------------------------------------
188 
189     d->levelsHistogramWidget = new HistogramWidget(256, 140, d->gboxSettings->plainPage(), false);
190     d->levelsHistogramWidget->updateData(*d->originalImage);
191 
192     d->levelsHistogramWidget->setWhatsThis(i18n("This is the histogram drawing of the selected channel "
193                                            "from the original image."));
194     d->levelsHistogramWidget->setChannelType(ColorChannels);
195     QHBoxLayout* const inputLevelsLayout = new QHBoxLayout;
196     inputLevelsLayout->addWidget(d->levelsHistogramWidget);
197 
198     // -------------------------------------------------------------
199 
200     d->redInputLevels = new DGradientSlider();
201     d->redInputLevels->setColors(QColor("Red"), QColor("White"));
202     d->redInputLevels->setToolTip( i18n( "Input range of red color channel." ) );
203     d->redInputLevels->installEventFilter(this);
204 
205     d->greenInputLevels = new DGradientSlider();
206     d->greenInputLevels->setColors(QColor("Green"), QColor("White"));
207     d->greenInputLevels->setToolTip( i18n( "Input range of green color channel." ) );
208     d->greenInputLevels->installEventFilter(this);
209 
210     d->blueInputLevels = new DGradientSlider();
211     d->blueInputLevels->setColors(QColor("Blue"), QColor("White"));
212     d->blueInputLevels->setToolTip( i18n( "Input range of blue color channel." ) );
213     d->blueInputLevels->installEventFilter(this);
214 
215     d->gboxSettings->histogramBox()->setHistogramMargin(d->redInputLevels->gradientOffset());
216 
217     inputLevelsLayout->setContentsMargins(d->redInputLevels->gradientOffset(), 0,
218                                           d->redInputLevels->gradientOffset(), 0);
219 
220     // -------------------------------------------------------------
221 
222     d->cnType = new QListWidget();
223     QList<FilmContainer::ListItem*> profiles = d->filmContainer.profileItemList(d->cnType);
224     QList<FilmContainer::ListItem*>::ConstIterator it;
225 
226     for (it = profiles.constBegin(); it != profiles.constEnd(); ++it)
227         d->cnType->addItem(*it);
228 
229     // -------------------------------------------------------------
230 
231     d->colorBalanceInput = new QCheckBox(i18n("Color Balance"));
232     d->colorBalanceInput->setCheckState(Qt::Checked);
233     d->colorBalanceInput->setToolTip(i18n("Check to apply the built-in color balance of the film profile. "
234                                           "Un-check if you want to apply color balance yourself."));
235 
236     // -------------------------------------------------------------
237 
238     d->pickWhitePoint = new QToolButton();
239     d->pickWhitePoint->setIcon(QIcon::fromTheme(QLatin1String("color-picker-white")));
240     d->pickWhitePoint->setCheckable(true);
241     d->pickWhitePoint->setToolTip( i18n( "White point color picker" ) );
242     d->pickWhitePoint->setWhatsThis(i18n("With this button, you can pick the color of the orange mask "
243             "of the scanned color negative. It represents white point of the negative, "
244             "or the darkest black tone of the positive image "
245             "after inversion. It is also the reference point for applying the film profile."));
246 
247     d->resetButton = new QPushButton(i18n("&Reset"));
248     d->resetButton->setIcon(QIcon::fromTheme(QLatin1String("document-revert")));
249     d->resetButton->setToolTip( i18n( "Reset white point." ) );
250     d->resetButton->setWhatsThis(i18n("If you press this button, the white point is "
251                                       "reset to pure white."));
252 
253     d->autoButton = new QToolButton();
254     d->autoButton->setIcon(QIcon::fromTheme(QLatin1String("system-run")));
255     d->autoButton->setToolTip( i18n( "Adjust white point automatically." ) );
256     d->autoButton->setWhatsThis(i18n("If you press this button, the white point is calculated "
257                                      "from the image data automatically. This function requires to have some residual "
258                                      "orange mask around the exposed area of the negative."));
259 
260     QLabel* const space   = new QLabel();
261     space->setFixedWidth(d->gboxSettings->spacingHint());
262 
263     QHBoxLayout* const l3 = new QHBoxLayout();
264     l3->addWidget(d->pickWhitePoint);
265     l3->addWidget(d->autoButton);
266     l3->addWidget(space);
267     l3->addWidget(d->resetButton);
268     l3->addStretch(10);
269 
270     // -------------------------------------------------------------
271 
272     d->exposureInput = new DDoubleNumInput();
273     d->exposureInput->setDecimals(2);
274     d->exposureInput->setRange(0.0, 40.0, 0.01);
275     d->exposureInput->setDefaultValue(1.0);
276     d->exposureInput->setToolTip( i18n( "Exposure correction." ) );
277     d->exposureInput->setWhatsThis(i18n("Move the slider to higher values until maximum brightness is achieved "
278                                         "without clipping any color channel. Use the output histogram to evaluate each channel."));
279 
280     d->gammaInput = new DDoubleNumInput();
281     d->gammaInput->setDecimals(2);
282     d->gammaInput->setRange(0.1, 3.0, 0.01);
283     d->gammaInput->setDefaultValue(1.8);
284     d->gammaInput->setToolTip(i18n( "Gamma input value." ));
285     d->gammaInput->setWhatsThis(i18n("Linear raw scans of film negatives require application of a gamma curve. "
286                                      "Standard values are 1.8 or 2.2."));
287 
288     // -------------------------------------------------------------
289 
290     QGridLayout* const grid = new QGridLayout();
291     grid->addLayout(inputLevelsLayout,    0, 0, 1, 4);
292     grid->addWidget(d->redInputLevels,    1, 0, 1, 4);
293     grid->addWidget(d->greenInputLevels,  2, 0, 1, 4);
294     grid->addWidget(d->blueInputLevels,   3, 0, 1, 4);
295     grid->addWidget(d->cnType,            4, 0, 1, 4);
296     grid->addWidget(d->exposureInput,     5, 0, 1, 4);
297     grid->addWidget(d->gammaInput,        6, 0, 1, 4);
298     grid->addLayout(l3,                   7, 0, 1, 2);
299     grid->addWidget(d->colorBalanceInput, 7, 2, 1, 2, Qt::AlignRight);
300 
301     // TODO: fill in rest of settings elements
302     //grid->setRowStretch(7, 10);
303     //grid->setColumnStretch(2, 10);
304     //grid->setColumnStretch(4, 10);
305 
306     grid->setContentsMargins(QMargins());
307     grid->setSpacing(d->gboxSettings->spacingHint());
308     d->gboxSettings->plainPage()->setLayout(grid);
309 
310     // -------------------------------------------------------------
311 
312     d->filmContainer.setSixteenBit(d->originalImage->sixteenBit());
313     d->filmContainer.setWhitePoint(DColor(QColor(QLatin1String("white")), d->originalImage->sixteenBit()));
314 
315     // -------------------------------------------------------------
316 
317     setToolSettings(d->gboxSettings);
318 
319     // Button Slots -------------------------------------------------
320 
321     connect(d->autoButton, SIGNAL(clicked()),
322             this, SLOT(slotAutoWhitePoint()));
323 
324     connect(d->pickWhitePoint, SIGNAL(toggled(bool)),
325             this, SLOT(slotPickerColorButtonActived(bool)));
326 
327     // Slots --------------------------------------------------------
328 
329     connect(d->previewWidget, SIGNAL(signalCapturedPointFromOriginal(Digikam::DColor,QPoint)),
330             this, SLOT(slotColorSelectedFromTarget(Digikam::DColor,QPoint)));
331 
332     connect(d->exposureInput, SIGNAL(valueChanged(double)),
333             this, SLOT(slotExposureChanged(double)));
334 
335     connect(d->gammaInput, SIGNAL(valueChanged(double)),
336             this, SLOT(slotGammaInputChanged(double)));
337 
338     connect(d->resetButton, SIGNAL(clicked()),
339             this, SLOT(slotResetWhitePoint()));
340 
341     connect(d->cnType, SIGNAL(itemActivated(QListWidgetItem*)),
342             this, SLOT(slotFilmItemActivated(QListWidgetItem*)));
343 
344     connect(d->colorBalanceInput, SIGNAL(stateChanged(int)),
345             this, SLOT(slotColorBalanceStateChanged(int)));
346 }
347 
~FilmTool()348 FilmTool::~FilmTool()
349 {
350     delete d->levels;
351     delete d;
352 }
353 
slotResetSettings()354 void FilmTool::slotResetSettings()
355 {
356     bool sb = d->originalImage->sixteenBit();
357     int max = sb ? 65535 : 255;
358 
359     FilmContainer::CNFilmProfile cnType = FilmContainer::CNNeutral;
360 
361     QString profileName                   = QLatin1String("Neutral");
362     QList<QListWidgetItem*> matchingItems = d->cnType->findItems(profileName, Qt::MatchExactly);
363     d->cnType->setCurrentItem(matchingItems.first());
364 
365     double gamma     = 1.8;
366     d->gammaInput->setValue(gamma);
367     gammaInputChanged(gamma);
368 
369     double exposure  = 1.0;
370     d->exposureInput->setValue(exposure);
371 
372     d->filmContainer = FilmContainer(cnType, gamma, d->originalImage->sixteenBit());
373     d->filmContainer.setExposure(exposure);
374 
375     int red   = max;
376     int green = max;
377     int blue  = max;
378 
379     red       = sb ? red   : red   / 256;
380     green     = sb ? green : green / 256;
381     blue      = sb ? blue  : blue  / 256;
382 
383     DColor whitePoint = DColor(red, green, blue, max, sb);
384     d->filmContainer.setWhitePoint(whitePoint);
385     setLevelsFromFilm();
386 
387     d->levelsHistogramWidget->reset();
388     d->gboxSettings->histogramBox()->histogram()->reset();
389     d->gboxSettings->histogramBox()->setChannel(ColorChannels);
390     d->gboxSettings->histogramBox()->setScale(LogScaleHistogram);
391 
392     slotAdjustSliders();
393     slotChannelChanged();
394     slotScaleChanged();
395 }
396 
slotChannelChanged()397 void FilmTool::slotChannelChanged()
398 {
399     d->levelsHistogramWidget->setChannelType(d->gboxSettings->histogramBox()->channel());
400 }
401 
slotScaleChanged()402 void FilmTool::slotScaleChanged()
403 {
404    d->levelsHistogramWidget->setScaleType(d->gboxSettings->histogramBox()->scale());
405 }
406 
slotAdjustSliders()407 void FilmTool::slotAdjustSliders()
408 {
409     // adjust all Levels sliders
410 
411     d->redInputLevels->setLeftValue(
412             (double)d->levels->getLevelLowInputValue(RedChannel) / d->histoSegments);
413     d->redInputLevels->setRightValue(
414             (double)d->levels->getLevelHighInputValue(RedChannel) / d->histoSegments);
415 
416     d->greenInputLevels->setLeftValue(
417             (double)d->levels->getLevelLowInputValue(GreenChannel) / d->histoSegments);
418     d->greenInputLevels->setRightValue(
419             (double)d->levels->getLevelHighInputValue(GreenChannel) / d->histoSegments);
420 
421     d->blueInputLevels->setLeftValue(
422             (double)d->levels->getLevelLowInputValue(BlueChannel) / d->histoSegments);
423     d->blueInputLevels->setRightValue(
424             (double)d->levels->getLevelHighInputValue(BlueChannel) / d->histoSegments);
425 }
426 
setLevelsFromFilm()427 void FilmTool::setLevelsFromFilm()
428 {
429     LevelsContainer l = d->filmContainer.toLevels();
430 
431     for (int i = RedChannel ; i <= BlueChannel ; ++i)
432     {
433         d->levels->setLevelLowInputValue(i, l.lInput[i]);
434         d->levels->setLevelHighInputValue(i, l.hInput[i]);
435         d->levels->setLevelLowOutputValue(i, l.lOutput[i]);
436         d->levels->setLevelHighOutputValue(i, l.hOutput[i]);
437         d->levels->setLevelGammaValue(i, l.gamma[i]);
438     }
439 
440     slotAdjustSliders();
441 }
442 
slotExposureChanged(double val)443 void FilmTool::slotExposureChanged(double val)
444 {
445     d->filmContainer.setExposure(val);
446     setLevelsFromFilm();
447     slotTimer();
448 }
449 
gammaInputChanged(double val)450 void FilmTool::gammaInputChanged(double val)
451 {
452     d->filmContainer.setGamma(val);
453     setLevelsFromFilm();
454 }
455 
slotGammaInputChanged(double val)456 void FilmTool::slotGammaInputChanged(double val)
457 {
458     gammaInputChanged(val);
459     slotTimer();
460 }
461 
slotFilmItemActivated(QListWidgetItem * item)462 void FilmTool::slotFilmItemActivated(QListWidgetItem* item)
463 {
464     double gamma    = d->filmContainer.gamma();
465     double strength = d->filmContainer.exposure();
466     DColor wp       = d->filmContainer.whitePoint();
467 
468     FilmContainer::CNFilmProfile type = (FilmContainer::CNFilmProfile)(item->type()-QListWidgetItem::UserType);
469     d->filmContainer                  = FilmContainer(type, gamma, d->originalImage->sixteenBit());
470     d->filmContainer.setExposure(strength);
471     d->filmContainer.setApplyBalance(d->colorBalanceInput->checkState() == Qt::Checked);
472     d->filmContainer.setWhitePoint(wp);
473     setLevelsFromFilm();
474     slotTimer();
475 }
476 
slotColorSelectedFromTarget(const Digikam::DColor & color,const QPoint & p)477 void FilmTool::slotColorSelectedFromTarget(const Digikam::DColor& color, const QPoint& p)
478 {
479     DColor wp00 = color;
480     DColor wp01 = d->originalImage->getPixelColor(p.x(), p.y()+1);
481     DColor wp10 = d->originalImage->getPixelColor(p.x()+1, p.y());
482     DColor wp11 = d->originalImage->getPixelColor(p.x()+1, p.y()+1);
483 
484     wp00.blendAdd(wp01);
485     wp00.blendAdd(wp10);
486     wp00.blendAdd(wp11);
487     wp00.multiply(0.25);
488 
489     d->filmContainer.setWhitePoint(wp00);
490     d->previewWidget->setCapturePointMode(false);
491     d->pickWhitePoint->setChecked(false);
492 
493     setLevelsFromFilm();
494     slotTimer();
495 }
496 
slotPickerColorButtonActived(bool checked)497 void FilmTool::slotPickerColorButtonActived(bool checked)
498 {
499     if (checked)
500     {
501         d->previewWidget->setCapturePointMode(true);
502     }
503 }
504 
slotAutoWhitePoint()505 void FilmTool::slotAutoWhitePoint()
506 {
507     ImageHistogram* const hist = d->levelsHistogramWidget->currentHistogram();
508     bool sixteenBit            = d->originalImage->sixteenBit();
509     int high_input[4];
510 
511     for (int channel = RedChannel ; channel <= BlueChannel ; ++channel)
512     {
513         double new_count = 0.0;
514         double percentage;
515         double next_percentage;
516         double count     = hist->getCount(channel, 0, sixteenBit ? 65535 : 255);
517 
518         for (int i = (sixteenBit ? 65535 : 255) ; i > 0 ; --i)
519         {
520             new_count      += hist->getValue(channel, i);
521             percentage      = new_count / count;
522             next_percentage = (new_count + hist->getValue(channel, i - 1)) / count;
523 
524             if (fabs(percentage - 0.006) < fabs(next_percentage - 0.006))
525             {
526                 high_input[channel] = i - 1;
527                 break;
528             }
529         }
530     }
531 
532     DColor wp = DColor(high_input[RedChannel],
533                        high_input[GreenChannel],
534                        high_input[BlueChannel],
535                        0,
536                        sixteenBit);
537 
538     d->filmContainer.setWhitePoint(wp);
539 
540     setLevelsFromFilm();
541     slotPreview();
542 }
543 
slotResetWhitePoint()544 void FilmTool::slotResetWhitePoint()
545 {
546     d->filmContainer.setSixteenBit(d->originalImage->sixteenBit());
547     d->filmContainer.setWhitePoint(DColor(QColor(QLatin1String("white")), d->originalImage->sixteenBit()));
548 
549     setLevelsFromFilm();
550     slotPreview();
551 }
552 
slotColorBalanceStateChanged(int state)553 void FilmTool::slotColorBalanceStateChanged(int state)
554 {
555     bool apply = (state == Qt::Checked);
556     d->filmContainer.setApplyBalance(apply);
557 
558     slotPreview();
559 }
560 
readSettings()561 void FilmTool::readSettings()
562 {
563     KSharedConfig::Ptr config = KSharedConfig::openConfig();
564     KConfigGroup group        = config->group(d->configGroupName);
565 
566     bool sb = d->originalImage->sixteenBit();
567     int max = sb ? 65535 : 255;
568 
569     FilmContainer::CNFilmProfile cnType   = (FilmContainer::CNFilmProfile)
570                                             group.readEntry(d->configFilmProfileEntry, (int)FilmContainer::CNNeutral);
571 
572     QString profileName                   = group.readEntry(d->configFilmProfileName, "Neutral");
573     QList<QListWidgetItem*> matchingItems = d->cnType->findItems(profileName, Qt::MatchExactly);
574     d->cnType->setCurrentItem(matchingItems.first());
575 
576     double gamma      = group.readEntry(d->configGammaInputEntry, 1.8);
577     d->gammaInput->setValue(gamma);
578     gammaInputChanged(gamma);
579 
580     double exposure   = group.readEntry(d->configExposureEntry, 1.0);
581     d->exposureInput->setValue(exposure);
582 
583     d->filmContainer  = FilmContainer(cnType, gamma, d->originalImage->sixteenBit());
584     d->filmContainer.setExposure(exposure);
585 
586     int red   = group.readEntry(d->configWhitePointEntry.arg(1), max);
587     int green = group.readEntry(d->configWhitePointEntry.arg(2), max);
588     int blue  = group.readEntry(d->configWhitePointEntry.arg(3), max);
589 
590     red       = sb ? red   : red   / 256;
591     green     = sb ? green : green / 256;
592     blue      = sb ? blue  : blue  / 256;
593 
594     DColor whitePoint = DColor(red, green, blue, max, sb);
595     d->filmContainer.setWhitePoint(whitePoint);
596     setLevelsFromFilm();
597 
598     bool apply = group.readEntry(d->configApplyColorBalance, true);
599     d->filmContainer.setApplyBalance(apply);
600     d->colorBalanceInput->setCheckState(apply? Qt::Checked : Qt::Unchecked);
601 
602     d->levelsHistogramWidget->reset();
603     d->gboxSettings->histogramBox()->histogram()->reset();
604 
605     ChannelType ch = (ChannelType)group.readEntry(d->configHistogramChannelEntry, (int)ColorChannels);
606 
607     // restore the previous channel
608     d->gboxSettings->histogramBox()->setChannel(ch);
609 
610     d->gboxSettings->histogramBox()->setScale((HistogramScale)group.readEntry(d->configHistogramScaleEntry,
611                                               (int)LogScaleHistogram));
612 
613     slotAdjustSliders();
614     slotChannelChanged();
615     slotScaleChanged();
616 }
617 
writeSettings()618 void FilmTool::writeSettings()
619 {
620     KSharedConfig::Ptr config = KSharedConfig::openConfig();
621     KConfigGroup group        = config->group(d->configGroupName);
622     bool sb                   = d->originalImage->sixteenBit();
623 
624     group.writeEntry(d->configHistogramChannelEntry, (int)d->gboxSettings->histogramBox()->channel());
625     group.writeEntry(d->configHistogramScaleEntry,   (int)d->gboxSettings->histogramBox()->scale());
626 
627     double gamma    = d->gammaInput->value();
628     group.writeEntry(d->configGammaInputEntry, gamma);
629 
630     double exposure = d->exposureInput->value();
631     group.writeEntry(d->configExposureEntry, exposure);
632 
633     int cnType      = (int)d->filmContainer.cnType();
634     group.writeEntry(d->configFilmProfileEntry, cnType);
635 
636     group.writeEntry(d->configFilmProfileName, d->cnType->currentItem()->text());
637 
638     int red    = d->filmContainer.whitePoint().red();
639     int green  = d->filmContainer.whitePoint().green();
640     int blue   = d->filmContainer.whitePoint().blue();
641 
642     group.writeEntry(d->configWhitePointEntry.arg(1), sb ? red   : red   * 256);
643     group.writeEntry(d->configWhitePointEntry.arg(2), sb ? green : green * 256);
644     group.writeEntry(d->configWhitePointEntry.arg(3), sb ? blue  : blue  * 256);
645 
646     bool apply = d->colorBalanceInput->checkState() == Qt::Checked;
647     group.writeEntry(d->configApplyColorBalance, apply);
648     config->sync();
649 }
650 
preparePreview()651 void FilmTool::preparePreview()
652 {
653     d->gboxSettings->histogramBox()->histogram()->stopHistogramComputation();
654 
655     DImg preview = d->previewWidget->getOriginalRegionImage(true);
656     setFilter(new FilmFilter(&preview, this, d->filmContainer));
657 }
658 
prepareFinal()659 void FilmTool::prepareFinal()
660 {
661     ImageIface iface;
662     setFilter(new FilmFilter(iface.original(), this, d->filmContainer));
663 }
664 
setPreviewImage()665 void FilmTool::setPreviewImage()
666 {
667     DImg preview = filter()->getTargetImage();
668     d->previewWidget->setPreviewImage(preview);
669 
670     // Update histogram.
671 
672     d->gboxSettings->histogramBox()->histogram()->updateData(preview.copy(), DImg(), false);
673 }
674 
setFinalImage()675 void FilmTool::setFinalImage()
676 {
677     ImageIface iface;
678     iface.setOriginal(i18n("Film"), filter()->filterAction(), filter()->getTargetImage());
679 }
680 
eventFilter(QObject * obj,QEvent * ev)681 bool FilmTool::eventFilter(QObject* obj, QEvent* ev)
682 {
683     // Swallow mouse evens for level sliders to make them immutable
684 
685     if ((obj == d->redInputLevels) || (obj == d->greenInputLevels) || (obj == d->blueInputLevels))
686     {
687         if ((ev->type() == QEvent::MouseButtonPress)   ||
688             (ev->type() == QEvent::MouseButtonRelease) ||
689             (ev->type() == QEvent::MouseMove)          ||
690             (ev->type() == QEvent::MouseButtonDblClick))
691         {
692             return true;
693         }
694     }
695 
696     // pass all other events to the parent class
697 
698     return EditorToolThreaded::eventFilter(obj, ev);
699 }
700 
701 } // namespace DigikamEditorFilmToolPlugin
702