summaryrefslogtreecommitdiffstats
path: root/src/imageplugins/noisereduction
diff options
context:
space:
mode:
Diffstat (limited to 'src/imageplugins/noisereduction')
-rw-r--r--src/imageplugins/noisereduction/Makefile.am34
-rw-r--r--src/imageplugins/noisereduction/digikamimageplugin_noisereduction.desktop53
-rw-r--r--src/imageplugins/noisereduction/digikamimageplugin_noisereduction_ui.rc20
-rw-r--r--src/imageplugins/noisereduction/imageeffect_noisereduction.cpp553
-rw-r--r--src/imageplugins/noisereduction/imageeffect_noisereduction.h82
-rw-r--r--src/imageplugins/noisereduction/imageplugin_noisereduction.cpp70
-rw-r--r--src/imageplugins/noisereduction/imageplugin_noisereduction.h56
-rw-r--r--src/imageplugins/noisereduction/noisereduction.cpp809
-rw-r--r--src/imageplugins/noisereduction/noisereduction.h257
-rw-r--r--src/imageplugins/noisereduction/noisereductiontool.cpp536
-rw-r--r--src/imageplugins/noisereduction/noisereductiontool.h92
11 files changed, 2562 insertions, 0 deletions
diff --git a/src/imageplugins/noisereduction/Makefile.am b/src/imageplugins/noisereduction/Makefile.am
new file mode 100644
index 00000000..c1b6ac08
--- /dev/null
+++ b/src/imageplugins/noisereduction/Makefile.am
@@ -0,0 +1,34 @@
+METASOURCES = AUTO
+
+INCLUDES = -I$(top_srcdir)/src/utilities/imageeditor/editor \
+ -I$(top_srcdir)/src/utilities/imageeditor/canvas \
+ -I$(top_srcdir)/src/libs/histogram \
+ -I$(top_srcdir)/src/libs/levels \
+ -I$(top_srcdir)/src/libs/curves \
+ -I$(top_srcdir)/src/libs/whitebalance \
+ -I$(top_srcdir)/src/libs/widgets/common \
+ -I$(top_srcdir)/src/libs/widgets/iccprofiles \
+ -I$(top_srcdir)/src/libs/widgets/imageplugins \
+ -I$(top_srcdir)/src/libs/dialogs \
+ -I$(top_srcdir)/src/libs/dimg \
+ -I$(top_srcdir)/src/libs/dmetadata \
+ -I$(top_srcdir)/src/libs/dimg/filters \
+ -I$(top_srcdir)/src/digikam \
+ $(LIBKDCRAW_CFLAGS) \
+ $(all_includes)
+
+digikamimageplugin_noisereduction_la_SOURCES = imageplugin_noisereduction.cpp \
+ noisereductiontool.cpp noisereduction.cpp
+
+digikamimageplugin_noisereduction_la_LIBADD = $(LIB_TDEPARTS) \
+ $(top_builddir)/src/digikam/libdigikam.la
+
+digikamimageplugin_noisereduction_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) -ltdecore -ltdeui $(LIB_TQT) -ltdefx -lkdcraw -ltdeio
+
+kde_services_DATA = digikamimageplugin_noisereduction.desktop
+
+kde_module_LTLIBRARIES = digikamimageplugin_noisereduction.la
+
+rcdir = $(kde_datadir)/digikam
+rc_DATA = digikamimageplugin_noisereduction_ui.rc
+
diff --git a/src/imageplugins/noisereduction/digikamimageplugin_noisereduction.desktop b/src/imageplugins/noisereduction/digikamimageplugin_noisereduction.desktop
new file mode 100644
index 00000000..9cf408e3
--- /dev/null
+++ b/src/imageplugins/noisereduction/digikamimageplugin_noisereduction.desktop
@@ -0,0 +1,53 @@
+[Desktop Entry]
+Name=ImagePlugin_NoiseReduction
+Name[da]=Plugin for støjreducering
+Name[el]=ΠρόσθετοΕικόνας_ΜείωσηΘορύβου
+Name[fi]=Kohinanpoisto
+Name[hr]=Uklanjanje šuma
+Name[it]=PluginImmagini_RiduzioneDisturbi
+Name[nl]=Afbeeldingsplugin_Ruisreductie
+Name[pt]=ImagePlugin_Restoration
+Name[sr]=Смањење шума
+Name[sr@Latn]=Smanjenje šuma
+Name[sv]=Insticksprogram för brusreducering
+Name[tr]=ResimEklentisi_Onarım
+Name[vi]=ImagePlugin_Restoration
+Name[xx]=xxImagePlugin_NoiseReductionxx
+Type=Service
+X-TDE-ServiceTypes=Digikam/ImagePlugin
+Encoding=UTF-8
+Comment=Noise Reduction plugin for digiKam
+Comment[bg]=Приставка на digiKam за намаляване шума в снимки
+Comment[ca]=Connector pel digiKam de reducció de soroll
+Comment[da]=Plugin til støjreduktion for DigiKam
+Comment[de]=digiKam-Modul zum Entfernen von Rauschen
+Comment[el]=Πρόσθετο μείωσης θορύβου για το digiKam
+Comment[es]=Plugin para digiKam de reducción de ruido
+Comment[et]=DigiKami müra vähendamise plugin
+Comment[fa]=وصلۀ کاهش نوفه برای digiKam
+Comment[fi]=Vähentää kuvan kohinaa
+Comment[fr]=Module externe pour réduire le bruit numérique dans digiKam
+Comment[gl]=Un plugin de digiKam para a reduzón de ruído
+Comment[hr]=digiKam dodatak za uklanjanje šuma
+Comment[is]=Íforrit fyrir digiKam sem minnkar truflanir (noise) í mynd
+Comment[it]=Plugin di riduzione dei disturbi per digiKam
+Comment[ja]=digiKam ノイズ低減プラグイン
+Comment[ms]=Plugin Pengurangan Bising untuk digiKam
+Comment[nds]=digiKam-Moduul för Ruusminnern
+Comment[nl]=Digikam-plugin voor ruisreductie
+Comment[pa]=ਡਿਜ਼ੀਕੈਮ ਲਈ ਗੜਬੜ ਘਟਾਉਣ ਲਈ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka do programu digiKam zmniejszająca szum
+Comment[pt]=Um 'plugin' do digiKam para a redução de ruído
+Comment[pt_BR]=Plugin de redução de ruidos
+Comment[ru]=Модуль уменьшения шума для digiKam
+Comment[sk]=digiKam plugin na potlačenie šumu
+Comment[sr]=digiKam-ов прикључак за смањење шума
+Comment[sr@Latn]=digiKam-ov priključak za smanjenje šuma
+Comment[sv]=Digikam insticksprogram för brusreducering
+Comment[tr]=digiKam için Parazit Azaltma eklentisi
+Comment[uk]=Втулок зменшення шуму для digiKam
+Comment[vi]=Phần bổ sung giảm nhiễu cho digiKam
+Comment[xx]=xxNoise Reduction plugin for digiKamxx
+
+X-TDE-Library=digikamimageplugin_noisereduction
+author=Caulier Gilles, caulier dot gilles at gmail dot com
diff --git a/src/imageplugins/noisereduction/digikamimageplugin_noisereduction_ui.rc b/src/imageplugins/noisereduction/digikamimageplugin_noisereduction_ui.rc
new file mode 100644
index 00000000..b6a663e3
--- /dev/null
+++ b/src/imageplugins/noisereduction/digikamimageplugin_noisereduction_ui.rc
@@ -0,0 +1,20 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui version="5" name="digikamimageplugin_noisereduction" >
+
+ <MenuBar>
+
+ <Menu name="Enhance" ><text>Enh&amp;ance</text>
+ <Action name="imageplugin_noisereduction" />
+ </Menu>
+
+ </MenuBar>
+
+ <ToolBar name="ToolBar" >
+ <text>Main Toolbar</text>
+ </ToolBar>
+
+ <ActionProperties>
+ <Action shortcut="" name="imageplugin_noisereduction" />
+ </ActionProperties>
+
+</kpartgui>
diff --git a/src/imageplugins/noisereduction/imageeffect_noisereduction.cpp b/src/imageplugins/noisereduction/imageeffect_noisereduction.cpp
new file mode 100644
index 00000000..707b05db
--- /dev/null
+++ b/src/imageplugins/noisereduction/imageeffect_noisereduction.cpp
@@ -0,0 +1,553 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-08-24
+ * Description : a plugin to reduce CCD noise.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqlabel.h>
+#include <tqwhatsthis.h>
+#include <tqtooltip.h>
+#include <tqcheckbox.h>
+#include <tqstring.h>
+#include <tqtabwidget.h>
+#include <tqimage.h>
+#include <tqlayout.h>
+#include <tqfile.h>
+#include <tqtextstream.h>
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <tdeaboutdata.h>
+#include <kiconloader.h>
+#include <tdeapplication.h>
+#include <kstandarddirs.h>
+#include <knuminput.h>
+#include <tdefiledialog.h>
+#include <tdeglobalsettings.h>
+#include <tdemessagebox.h>
+#include <tdeconfig.h>
+
+// Local includes.
+
+#include "version.h"
+#include "ddebug.h"
+#include "dimg.h"
+#include "imageiface.h"
+#include "imagewidget.h"
+#include "noisereduction.h"
+#include "imageeffect_noisereduction.h"
+#include "imageeffect_noisereduction.moc"
+
+namespace DigikamNoiseReductionImagesPlugin
+{
+
+ImageEffect_NoiseReduction::ImageEffect_NoiseReduction(TQWidget* parent)
+ : Digikam::CtrlPanelDlg(parent, i18n("Noise Reduction"),
+ "noisereduction", true, true, true,
+ Digikam::ImagePannelWidget::SeparateViewAll)
+{
+ TQString whatsThis;
+
+ TDEAboutData* about = new TDEAboutData("digikam",
+ I18N_NOOP("Noise Reduction"),
+ digikam_version,
+ I18N_NOOP("A noise reduction image filter plugin for digiKam."),
+ TDEAboutData::License_GPL,
+ "(c) 2004-2008, Gilles Caulier",
+ 0,
+ "http://www.digikam.org");
+
+ about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ about->addAuthor("Peter Heckert", I18N_NOOP("Noise Reduction algorithm. Developer"),
+ "peter dot heckert at arcor dot de");
+
+ setAboutData(about);
+
+ // -------------------------------------------------------------
+
+ TQTabWidget *mainTab = new TQTabWidget(m_imagePreviewWidget);
+
+ TQWidget* firstPage = new TQWidget( mainTab );
+ TQGridLayout* gridSettings = new TQGridLayout( firstPage, 6, 1, spacingHint());
+ mainTab->addTab( firstPage, i18n("Details") );
+
+ TQLabel *label1 = new TQLabel(i18n("Radius:"), firstPage);
+
+ m_radiusInput = new KDoubleNumInput(firstPage);
+ m_radiusInput->setPrecision(1);
+ m_radiusInput->setRange(0.0, 10.0, 0.1, true);
+ TQWhatsThis::add( m_radiusInput, i18n("<p><b>Radius</b>: this control selects the "
+ "gliding window size used for the filter. Larger values do not increase "
+ "the amount of time needed to filter each pixel in the image but "
+ "can cause blurring. This window moves across the image, and the "
+ "color in it is smoothed to remove imperfections. "
+ "In any case it must be about the same size as the noise granularity "
+ "or somewhat more. If it is set higher than necessary, then it "
+ "can cause unwanted blur."));
+
+ gridSettings->addMultiCellWidget(label1, 0, 0, 0, 0);
+ gridSettings->addMultiCellWidget(m_radiusInput, 0, 0, 1, 1);
+
+ // -------------------------------------------------------------
+
+ TQLabel *label3 = new TQLabel(i18n("Threshold:"), firstPage);
+
+ m_thresholdInput = new KDoubleNumInput(firstPage);
+ m_thresholdInput->setPrecision(2);
+ m_thresholdInput->setRange(0.0, 1.0, 0.01, true);
+ TQWhatsThis::add( m_thresholdInput, i18n("<p><b>Threshold</b>: use the slider for coarse adjustment, "
+ "and the spin control for fine adjustment to control edge detection sensitivity. "
+ "This value should be set so that edges and details are clearly visible "
+ "and noise is smoothed out. "
+ "Adjustment must be made carefully, because the gap between \"noisy\", "
+ "\"smooth\", and \"blur\" is very small. Adjust it as carefully as you would adjust "
+ "the focus of a camera."));
+
+ gridSettings->addMultiCellWidget(label3, 1, 1, 0, 0);
+ gridSettings->addMultiCellWidget(m_thresholdInput, 1, 1, 1, 1);
+
+ // -------------------------------------------------------------
+
+ TQLabel *label4 = new TQLabel(i18n("Texture:"), firstPage);
+
+ m_textureInput = new KDoubleNumInput(firstPage);
+ m_textureInput->setPrecision(2);
+ m_textureInput->setRange(-0.99, 0.99, 0.01, true);
+ TQWhatsThis::add( m_textureInput, i18n("<p><b>Texture</b>: this control sets the texture accuracy. "
+ "This value can be used, to get more or less texture accuracy. When decreased, "
+ "then noise and texture are blurred out, when increased then texture is "
+ "amplified, but also noise will increase. It has almost no effect on image edges."));
+
+ gridSettings->addMultiCellWidget(label4, 2, 2, 0, 0);
+ gridSettings->addMultiCellWidget(m_textureInput, 2, 2, 1, 1);
+
+ // -------------------------------------------------------------
+
+ TQLabel *label7 = new TQLabel(i18n("Sharpness:"), firstPage); // Filter setting "Lookahead".
+
+ m_sharpnessInput = new KDoubleNumInput(firstPage);
+ m_sharpnessInput->setPrecision(2);
+ m_sharpnessInput->setRange(0.0, 1.0, 0.1, true);
+ TQWhatsThis::add( m_sharpnessInput, i18n("<p><b>Sharpness</b>: "
+ "This value improves the frequency response for the filter. "
+ "When it is too strong then not all noise can be removed, or spike noise may appear. "
+ "Set it near to maximum, if you want to remove very weak noise or JPEG-artifacts, "
+ "without losing detail."));
+
+ gridSettings->addMultiCellWidget(label7, 3, 3, 0, 0);
+ gridSettings->addMultiCellWidget(m_sharpnessInput, 3, 3, 1, 1);
+
+ // -------------------------------------------------------------
+
+ TQLabel *label5 = new TQLabel(i18n("Edge Lookahead:"), firstPage); // Filter setting "Sharp".
+
+ m_lookaheadInput = new KDoubleNumInput(firstPage);
+ m_lookaheadInput->setPrecision(2);
+ m_lookaheadInput->setRange(0.01, 20.0, 0.01, true);
+ TQWhatsThis::add( m_lookaheadInput, i18n("<p><b>Edge</b>: "
+ "This value defines the pixel distance to which the filter looks ahead for edges. "
+ "When this value is increased, then spike noise is erased. "
+ "You can eventually re-adjust the <b>Edge</b> filter, when you have changed this setting. "
+ "When this value is too high, the adaptive filter can no longer accurately track "
+ "image details, and noise or blurring can occur."));
+
+ gridSettings->addMultiCellWidget(label5, 4, 4, 0, 0);
+ gridSettings->addMultiCellWidget(m_lookaheadInput, 4, 4, 1, 1);
+
+ // -------------------------------------------------------------
+
+ TQLabel *label10 = new TQLabel(i18n("Erosion:"), firstPage);
+
+ m_phaseInput = new KDoubleNumInput(firstPage);
+ m_phaseInput->setPrecision(1);
+ m_phaseInput->setRange(0.5, 20.0, 0.5, true);
+ TQWhatsThis::add( m_phaseInput, i18n("<p><b>Erosion</b>: "
+ "Use this to increase edge noise erosion and spike noise erosion "
+ "(noise is removed by erosion)."));
+
+ gridSettings->addMultiCellWidget(label10, 5, 5, 0, 0);
+ gridSettings->addMultiCellWidget(m_phaseInput, 5, 5, 1, 1);
+ gridSettings->setColStretch(1, 10);
+ gridSettings->setRowStretch(6, 10);
+
+ // -------------------------------------------------------------
+
+ TQWidget* secondPage = new TQWidget( mainTab );
+ TQGridLayout* gridSettings2 = new TQGridLayout( secondPage, 4, 1, spacingHint());
+ mainTab->addTab( secondPage, i18n("Advanced") );
+
+ TQLabel *label2 = new TQLabel(i18n("Luminance:"), secondPage);
+
+ m_lumToleranceInput = new KDoubleNumInput(secondPage);
+ m_lumToleranceInput->setPrecision(1);
+ m_lumToleranceInput->setRange(0.0, 1.0, 0.1, true);
+ TQWhatsThis::add( m_lumToleranceInput, i18n("<p><b>Luminance</b>: this control sets the luminance tolerance of the image."
+ "We recommend using either the <b>Color</b> or the <b>Luminance</b> tolerance settings "
+ "to make an image correction, not both at the same time. These settings "
+ "do not influence the main smoothing process controlled by the <b>Details</b> "
+ "settings."));
+
+ gridSettings2->addMultiCellWidget(label2, 0, 0, 0, 0);
+ gridSettings2->addMultiCellWidget(m_lumToleranceInput, 0, 0, 1, 1);
+
+ // -------------------------------------------------------------
+
+ TQLabel *label6 = new TQLabel(i18n("Color:"), secondPage);
+
+ m_csmoothInput = new KDoubleNumInput(secondPage);
+ m_csmoothInput->setPrecision(1);
+ m_csmoothInput->setRange(0.0, 1.0, 0.1, true);
+ TQWhatsThis::add( m_csmoothInput, i18n("<p><b>Color</b>: this control sets the color tolerance of the image. It is "
+ "recommended using either the <b>Color</b> or the <b>Luminance</b> tolerance "
+ "to make image correction, not both at the same time. These settings "
+ "do not influence the main smoothing process controlled by the <b>Details</b> "
+ "settings."));
+
+ gridSettings2->addMultiCellWidget(label6, 1, 1, 0, 0);
+ gridSettings2->addMultiCellWidget(m_csmoothInput, 1, 1, 1, 1);
+
+ // -------------------------------------------------------------
+
+ TQLabel *label8 = new TQLabel(i18n("Gamma:"), secondPage);
+
+ m_gammaInput = new KDoubleNumInput(secondPage);
+ m_gammaInput->setPrecision(1);
+ m_gammaInput->setRange(0.3, 3.0, 0.1, true);
+ TQWhatsThis::add( m_gammaInput, i18n("<p><b>Gamma</b>: this control sets the gamma tolerance of the image. This value "
+ "can be used to increase the tolerance values for darker areas (which commonly "
+ "are noisier). This results in more blur for shadow areas."));
+
+ gridSettings2->addMultiCellWidget(label8, 2, 2, 0, 0);
+ gridSettings2->addMultiCellWidget(m_gammaInput, 2, 2, 1, 1);
+
+ // -------------------------------------------------------------
+
+ TQLabel *label9 = new TQLabel(i18n("Damping:"), secondPage);
+
+ m_dampingInput = new KDoubleNumInput(secondPage);
+ m_dampingInput->setPrecision(1);
+ m_dampingInput->setRange(0.5, 20.0, 0.5, true);
+ TQWhatsThis::add( m_dampingInput, i18n("<p><b>Damping</b>: this control sets the phase-jitter damping adjustment. "
+ "This value defines how fast the adaptive filter-radius reacts to luminance "
+ "variations. If increased, then edges appear smoother; if too high, then blur "
+ "may occur. If at minimum, then noise and phase jitter at the edges can occur. It "
+ "can suppress spike noise when increased, and this is the preferred method to "
+ "remove it."));
+
+ gridSettings2->addMultiCellWidget(label9, 3, 3, 0, 0);
+ gridSettings2->addMultiCellWidget(m_dampingInput, 3, 3, 1, 1);
+ gridSettings2->setColStretch(1, 10);
+ gridSettings2->setRowStretch(4, 10);
+
+ m_imagePreviewWidget->setUserAreaWidget(mainTab);
+
+ // -------------------------------------------------------------
+
+// connect(m_radiusInput, TQ_SIGNAL(valueChanged(double)),
+// this, TQ_SLOT(slotTimer()));
+//
+// connect(m_lumToleranceInput, TQ_SIGNAL(valueChanged(double)),
+// this, TQ_SLOT(slotTimer()));
+//
+// connect(m_thresholdInput, TQ_SIGNAL(valueChanged(double)),
+// this, TQ_SLOT(slotTimer()));
+//
+// connect(m_textureInput, TQ_SIGNAL(valueChanged(double)),
+// this, TQ_SLOT(slotTimer()));
+//
+// connect(m_sharpnessInput, TQ_SIGNAL(valueChanged(double)),
+// this, TQ_SLOT(slotTimer()));
+//
+// connect(m_csmoothInput, TQ_SIGNAL(valueChanged(double)),
+// this, TQ_SLOT(slotTimer()));
+//
+// connect(m_lookaheadInput, TQ_SIGNAL(valueChanged(double)),
+// this, TQ_SLOT(slotTimer()));
+//
+// connect(m_gammaInput, TQ_SIGNAL(valueChanged(double)),
+// this, TQ_SLOT(slotTimer()));
+//
+// connect(m_dampingInput, TQ_SIGNAL(valueChanged(double)),
+// this, TQ_SLOT(slotTimer()));
+//
+// connect(m_phaseInput, TQ_SIGNAL(valueChanged(double)),
+// this, TQ_SLOT(slotTimer()));
+}
+
+ImageEffect_NoiseReduction::~ImageEffect_NoiseReduction()
+{
+}
+
+void ImageEffect_NoiseReduction::renderingFinished()
+{
+ m_radiusInput->setEnabled(true);
+ m_lumToleranceInput->setEnabled(true);
+ m_thresholdInput->setEnabled(true);
+ m_textureInput->setEnabled(true);
+ m_sharpnessInput->setEnabled(true);
+ m_csmoothInput->setEnabled(true);
+ m_lookaheadInput->setEnabled(true);
+ m_gammaInput->setEnabled(true);
+ m_dampingInput->setEnabled(true);
+ m_phaseInput->setEnabled(true);
+}
+
+void ImageEffect_NoiseReduction::readUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("noisereduction Tool Dialog");
+ m_radiusInput->setEnabled(true);
+ m_lumToleranceInput->setEnabled(true);
+ m_thresholdInput->setEnabled(true);
+ m_textureInput->setEnabled(true);
+ m_sharpnessInput->setEnabled(true);
+ m_csmoothInput->setEnabled(true);
+ m_lookaheadInput->setEnabled(true);
+ m_gammaInput->setEnabled(true);
+ m_dampingInput->setEnabled(true);
+ m_phaseInput->setEnabled(true);
+
+ m_radiusInput->setValue(config->readDoubleNumEntry("RadiusAjustment", 1.0));
+ m_lumToleranceInput->setValue(config->readDoubleNumEntry("LumToleranceAjustment", 1.0));
+ m_thresholdInput->setValue(config->readDoubleNumEntry("ThresholdAjustment", 0.08));
+ m_textureInput->setValue(config->readDoubleNumEntry("TextureAjustment", 0.0));
+ m_sharpnessInput->setValue(config->readDoubleNumEntry("SharpnessAjustment", 0.25));
+ m_csmoothInput->setValue(config->readDoubleNumEntry("CsmoothAjustment", 1.0));
+ m_lookaheadInput->setValue(config->readDoubleNumEntry("LookAheadAjustment", 2.0));
+ m_gammaInput->setValue(config->readDoubleNumEntry("GammaAjustment", 1.4));
+ m_dampingInput->setValue(config->readDoubleNumEntry("DampingAjustment", 5.0));
+ m_phaseInput->setValue(config->readDoubleNumEntry("PhaseAjustment", 1.0));
+
+ m_radiusInput->setEnabled(false);
+ m_lumToleranceInput->setEnabled(false);
+ m_thresholdInput->setEnabled(false);
+ m_textureInput->setEnabled(false);
+ m_sharpnessInput->setEnabled(false);
+ m_csmoothInput->setEnabled(false);
+ m_lookaheadInput->setEnabled(false);
+ m_gammaInput->setEnabled(false);
+ m_dampingInput->setEnabled(false);
+ m_phaseInput->setEnabled(false);
+}
+
+void ImageEffect_NoiseReduction::writeUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("noisereduction Tool Dialog");
+ config->writeEntry("RadiusAjustment", m_radiusInput->value());
+ config->writeEntry("LumToleranceAjustment", m_lumToleranceInput->value());
+ config->writeEntry("ThresholdAjustment", m_thresholdInput->value());
+ config->writeEntry("TextureAjustment", m_textureInput->value());
+ config->writeEntry("SharpnessAjustment", m_sharpnessInput->value());
+ config->writeEntry("CsmoothAjustment", m_csmoothInput->value());
+ config->writeEntry("LookAheadAjustment", m_lookaheadInput->value());
+ config->writeEntry("GammaAjustment", m_gammaInput->value());
+ config->writeEntry("DampingAjustment", m_dampingInput->value());
+ config->writeEntry("PhaseAjustment", m_phaseInput->value());
+ config->sync();
+}
+
+void ImageEffect_NoiseReduction::resetValues()
+{
+ m_radiusInput->setEnabled(true);
+ m_lumToleranceInput->setEnabled(true);
+ m_thresholdInput->setEnabled(true);
+ m_textureInput->setEnabled(true);
+ m_sharpnessInput->setEnabled(true);
+ m_csmoothInput->setEnabled(true);
+ m_lookaheadInput->setEnabled(true);
+ m_gammaInput->setEnabled(true);
+ m_dampingInput->setEnabled(true);
+ m_phaseInput->setEnabled(true);
+
+ m_radiusInput->setValue(1.0);
+ m_lumToleranceInput->setValue(1.0);
+ m_thresholdInput->setValue(0.08);
+ m_textureInput->setValue(0.0);
+ m_sharpnessInput->setValue(0.25);
+ m_csmoothInput->setValue(1.0);
+ m_lookaheadInput->setValue(2.0);
+ m_gammaInput->setValue(1.4);
+ m_dampingInput->setValue(5.0);
+ m_phaseInput->setValue(1.0);
+
+ m_radiusInput->setEnabled(false);
+ m_lumToleranceInput->setEnabled(false);
+ m_thresholdInput->setEnabled(false);
+ m_textureInput->setEnabled(false);
+ m_sharpnessInput->setEnabled(false);
+ m_csmoothInput->setEnabled(false);
+ m_lookaheadInput->setEnabled(false);
+ m_gammaInput->setEnabled(false);
+ m_dampingInput->setEnabled(false);
+ m_phaseInput->setEnabled(false);
+}
+
+void ImageEffect_NoiseReduction::prepareEffect()
+{
+ m_radiusInput->setEnabled(false);
+ m_lumToleranceInput->setEnabled(false);
+ m_thresholdInput->setEnabled(false);
+ m_textureInput->setEnabled(false);
+ m_sharpnessInput->setEnabled(false);
+ m_csmoothInput->setEnabled(false);
+ m_lookaheadInput->setEnabled(false);
+ m_gammaInput->setEnabled(false);
+ m_dampingInput->setEnabled(false);
+ m_phaseInput->setEnabled(false);
+
+ double r = m_radiusInput->value();
+ double l = m_lumToleranceInput->value();
+ double th = m_thresholdInput->value();
+ double tx = m_textureInput->value();
+ double s = m_sharpnessInput->value();
+ double c = m_csmoothInput->value();
+ double a = m_lookaheadInput->value();
+ double g = m_gammaInput->value();
+ double d = m_dampingInput->value();
+ double p = m_phaseInput->value();
+
+ Digikam::DImg image = m_imagePreviewWidget->getOriginalRegionImage();
+
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>(new NoiseReduction(&image,
+ this, r, l, th, tx, s, c, a, g, d, p));
+}
+
+void ImageEffect_NoiseReduction::prepareFinal()
+{
+ m_radiusInput->setEnabled(false);
+ m_lumToleranceInput->setEnabled(false);
+ m_thresholdInput->setEnabled(false);
+ m_textureInput->setEnabled(false);
+ m_sharpnessInput->setEnabled(false);
+ m_csmoothInput->setEnabled(false);
+ m_lookaheadInput->setEnabled(false);
+ m_gammaInput->setEnabled(false);
+ m_dampingInput->setEnabled(false);
+ m_phaseInput->setEnabled(false);
+
+ double r = m_radiusInput->value();
+ double l = m_lumToleranceInput->value();
+ double th = m_thresholdInput->value();
+ double tx = m_textureInput->value();
+ double s = m_sharpnessInput->value();
+ double c = m_csmoothInput->value();
+ double a = m_lookaheadInput->value();
+ double g = m_gammaInput->value();
+ double d = m_dampingInput->value();
+ double p = m_phaseInput->value();
+
+ Digikam::ImageIface iface(0, 0);
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>(new NoiseReduction(iface.getOriginalImg(),
+ this, r, l, th, tx, s, c, a, g, d, p));
+}
+
+void ImageEffect_NoiseReduction::putPreviewData(void)
+{
+ m_imagePreviewWidget->setPreviewImage(m_threadedFilter->getTargetImage());
+}
+
+void ImageEffect_NoiseReduction::putFinalData(void)
+{
+ Digikam::ImageIface iface(0, 0);
+ iface.putOriginalImage(i18n("Noise Reduction"), m_threadedFilter->getTargetImage().bits());
+}
+
+void ImageEffect_NoiseReduction::slotUser3()
+{
+ KURL loadRestorationFile = KFileDialog::getOpenURL(TDEGlobalSettings::documentPath(),
+ TQString( "*" ), this,
+ TQString( i18n("Photograph Noise Reduction Settings File to Load")) );
+ if ( loadRestorationFile.isEmpty() )
+ return;
+
+ TQFile file(loadRestorationFile.path());
+
+ if ( file.open(IO_ReadOnly) )
+ {
+ TQTextStream stream( &file );
+ if ( stream.readLine() != "# Photograph Noise Reduction Configuration File" )
+ {
+ KMessageBox::error(this,
+ i18n("\"%1\" is not a Photograph Noise Reduction settings text file.")
+ .arg(loadRestorationFile.fileName()));
+ file.close();
+ return;
+ }
+
+ blockSignals(true);
+ m_radiusInput->setValue( stream.readLine().toDouble() );
+ m_lumToleranceInput->setValue( stream.readLine().toDouble() );
+ m_thresholdInput->setValue( stream.readLine().toDouble() );
+ m_textureInput->setValue( stream.readLine().toDouble() );
+ m_sharpnessInput->setValue( stream.readLine().toDouble() );
+ m_csmoothInput->setValue( stream.readLine().toDouble() );
+ m_lookaheadInput->setValue( stream.readLine().toDouble() );
+ m_gammaInput->setValue( stream.readLine().toDouble() );
+ m_dampingInput->setValue( stream.readLine().toDouble() );
+ m_phaseInput->setValue( stream.readLine().toDouble() );
+ blockSignals(false);
+// slotEffect();
+ }
+ else
+ KMessageBox::error(this, i18n("Cannot load settings from the Photograph Noise Reduction text file."));
+
+ file.close();
+}
+
+void ImageEffect_NoiseReduction::slotUser2()
+{
+ KURL saveRestorationFile = KFileDialog::getSaveURL(TDEGlobalSettings::documentPath(),
+ TQString( "*" ), this,
+ TQString( i18n("Photograph Noise Reduction Settings File to Save")) );
+ if ( saveRestorationFile.isEmpty() )
+ return;
+
+ TQFile file(saveRestorationFile.path());
+
+ if ( file.open(IO_WriteOnly) )
+ {
+ TQTextStream stream( &file );
+ stream << "# Photograph Noise Reduction Configuration File\n";
+ stream << m_radiusInput->value() << "\n";
+ stream << m_lumToleranceInput->value() << "\n";
+ stream << m_thresholdInput->value() << "\n";
+ stream << m_textureInput->value() << "\n";
+ stream << m_sharpnessInput->value() << "\n";
+ stream << m_csmoothInput->value() << "\n";
+ stream << m_lookaheadInput->value() << "\n";
+ stream << m_gammaInput->value() << "\n";
+ stream << m_dampingInput->value() << "\n";
+ stream << m_phaseInput->value() << "\n";
+
+ }
+ else
+ KMessageBox::error(this, i18n("Cannot save settings to the Photograph Noise Reduction text file."));
+
+ file.close();
+}
+
+} // NameSpace DigikamNoiseReductionImagesPlugin
+
diff --git a/src/imageplugins/noisereduction/imageeffect_noisereduction.h b/src/imageplugins/noisereduction/imageeffect_noisereduction.h
new file mode 100644
index 00000000..b7ee1bb6
--- /dev/null
+++ b/src/imageplugins/noisereduction/imageeffect_noisereduction.h
@@ -0,0 +1,82 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-08-24
+ * Description : a plugin to reduce CCD noise.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEEFFECT_NOISEREDUCTION_H
+#define IMAGEEFFECT_NOISEREDUCTION_H
+
+// Local includes.
+
+#include "ctrlpaneldlg.h"
+
+class KDoubleNumInput;
+
+namespace DigikamNoiseReductionImagesPlugin
+{
+
+class ImageEffect_NoiseReduction : public Digikam::CtrlPanelDlg
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImageEffect_NoiseReduction(TQWidget* parent);
+ ~ImageEffect_NoiseReduction();
+
+private slots:
+
+ void readUserSettings();
+
+private:
+
+ void writeUserSettings();
+ void resetValues();
+ void prepareEffect();
+ void prepareFinal();
+ void putPreviewData();
+ void putFinalData();
+ void renderingFinished();
+
+private slots:
+
+ void slotUser2();
+ void slotUser3();
+
+private:
+
+ KDoubleNumInput *m_radiusInput;
+ KDoubleNumInput *m_lumToleranceInput;
+ KDoubleNumInput *m_thresholdInput;
+ KDoubleNumInput *m_textureInput;
+ KDoubleNumInput *m_sharpnessInput;
+
+ KDoubleNumInput *m_csmoothInput;
+ KDoubleNumInput *m_lookaheadInput;
+ KDoubleNumInput *m_gammaInput;
+ KDoubleNumInput *m_dampingInput;
+ KDoubleNumInput *m_phaseInput;
+};
+
+} // NameSpace DigikamNoiseReductionImagesPlugin
+
+#endif /* IMAGEEFFECT_NOISEREDUCTION_H */
diff --git a/src/imageplugins/noisereduction/imageplugin_noisereduction.cpp b/src/imageplugins/noisereduction/imageplugin_noisereduction.cpp
new file mode 100644
index 00000000..8392933d
--- /dev/null
+++ b/src/imageplugins/noisereduction/imageplugin_noisereduction.cpp
@@ -0,0 +1,70 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-08-24
+ * Description : a plugin to reduce CCD noise.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <tdeaction.h>
+#include <kcursor.h>
+#include <tdeapplication.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "noisereductiontool.h"
+#include "imageplugin_noisereduction.h"
+#include "imageplugin_noisereduction.moc"
+
+using namespace DigikamNoiseReductionImagesPlugin;
+
+K_EXPORT_COMPONENT_FACTORY(digikamimageplugin_noisereduction,
+ KGenericFactory<ImagePlugin_NoiseReduction>("digikamimageplugin_noisereduction"));
+
+ImagePlugin_NoiseReduction::ImagePlugin_NoiseReduction(TQObject *parent, const char*, const TQStringList &)
+ : Digikam::ImagePlugin(parent, "ImagePlugin_NoiseReduction")
+{
+ m_noiseReductionAction = new TDEAction(i18n("Noise Reduction..."), "noisereduction", 0,
+ this, TQ_SLOT(slotNoiseReduction()),
+ actionCollection(), "imageplugin_noisereduction");
+
+ setXMLFile("digikamimageplugin_noisereduction_ui.rc");
+
+ DDebug() << "ImagePlugin_NoiseReduction plugin loaded" << endl;
+}
+
+ImagePlugin_NoiseReduction::~ImagePlugin_NoiseReduction()
+{
+}
+
+void ImagePlugin_NoiseReduction::setEnabledActions(bool enable)
+{
+ m_noiseReductionAction->setEnabled(enable);
+}
+
+void ImagePlugin_NoiseReduction::slotNoiseReduction()
+{
+ NoiseReductionTool *tool = new NoiseReductionTool(this);
+ loadTool(tool);
+}
diff --git a/src/imageplugins/noisereduction/imageplugin_noisereduction.h b/src/imageplugins/noisereduction/imageplugin_noisereduction.h
new file mode 100644
index 00000000..3cbcb312
--- /dev/null
+++ b/src/imageplugins/noisereduction/imageplugin_noisereduction.h
@@ -0,0 +1,56 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-08-24
+ * Description : a plugin to reduce CCD noise.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEPLUGIN_NOISEREDUCTION_H
+#define IMAGEPLUGIN_NOISEREDUCTION_H
+
+// Digikam includes.
+
+#include "imageplugin.h"
+#include "digikam_export.h"
+
+class TDEAction;
+
+class DIGIKAMIMAGEPLUGINS_EXPORT ImagePlugin_NoiseReduction : public Digikam::ImagePlugin
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImagePlugin_NoiseReduction(TQObject *parent, const char* name,
+ const TQStringList &args);
+ ~ImagePlugin_NoiseReduction();
+
+ void setEnabledActions(bool enable);
+
+private slots:
+
+ void slotNoiseReduction();
+
+private:
+
+ TDEAction *m_noiseReductionAction;
+};
+
+#endif /* IMAGEPLUGIN_NOISEREDUCTION_H */
diff --git a/src/imageplugins/noisereduction/noisereduction.cpp b/src/imageplugins/noisereduction/noisereduction.cpp
new file mode 100644
index 00000000..b9be4729
--- /dev/null
+++ b/src/imageplugins/noisereduction/noisereduction.cpp
@@ -0,0 +1,809 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-05-25
+ * Description : Noise Reduction threaded image filter.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * Original Noise Filter algorithm copyright (C) 2005
+ * Peter Heckert <peter dot heckert at arcor dot de>
+ * from dcamnoise2 gimp plugin available at this url :
+ * http://home.arcor.de/peter.heckert/dcamnoise2-0.63.c
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#define IIR1(dest,src) (dest) = (d3 = ((((src) * b + d3) * b3 + d2) * b2 + d1) * b1)
+#define IIR2(dest,src) (dest) = (d2 = ((((src) * b + d2) * b3 + d1) * b2 + d3) * b1)
+#define IIR3(dest,src) (dest) = (d1 = ((((src) * b + d1) * b3 + d3) * b2 + d2) * b1)
+
+#define IIR1A(dest,src) (dest) = fabs(d3 = ((((src) * b + d3) * b3 + d2) * b2 + d1) * b1)
+#define IIR2A(dest,src) (dest) = fabs(d2 = ((((src) * b + d2) * b3 + d1) * b2 + d3) * b1)
+#define IIR3A(dest,src) (dest) = fabs(d1 = ((((src) * b + d1) * b3 + d3) * b2 + d2) * b1)
+
+#define FR 0.212671
+#define FG 0.715160
+#define FB 0.072169
+
+// Local includes.
+
+#include "ddebug.h"
+#include "dimg.h"
+#include "dimgimagefilters.h"
+#include "noisereduction.h"
+
+namespace DigikamNoiseReductionImagesPlugin
+{
+
+NoiseReduction::NoiseReduction(Digikam::DImg *orgImage, TQObject *parent,
+ double radius, double lsmooth, double effect, double texture, double sharp,
+ double csmooth, double lookahead, double gamma, double damping, double phase)
+ : Digikam::DImgThreadedFilter(orgImage, parent, "NoiseReduction")
+{
+ m_radius = radius; /* default radius default = 1.0 */
+ m_sharp = sharp; /* Sharpness factor default = 0.25 */
+ m_lsmooth = lsmooth; /* Luminance Tolerance default = 1.0 */
+ m_effect = effect; /* Adaptive filter-effect threshold default = 0.08 */
+ m_texture = texture; /* Texture Detail default = 0.0 */
+
+ m_csmooth = csmooth; /* RGB Tolerance default = 1.0 */
+ m_lookahead = lookahead; /* Lookahead default = 2.0 */
+ m_gamma = gamma; /* Filter gamma default = 1.0 */
+ m_damping = damping; /* Phase jitter Damping default = 5.0 */
+ m_phase = phase; /* Area Noise Clip default = 1.0 */
+
+ m_iir.B = 0.0;
+ m_iir.b1 = 0.0;
+ m_iir.b2 = 0.0;
+ m_iir.b3 = 0.0;
+ m_iir.b0 = 0.0;
+ m_iir.r = 0.0;
+ m_iir.q = 0.0;
+ m_iir.p = 0;
+
+ m_clampMax = m_orgImage.sixteenBit() ? 65535 : 255;
+
+ initFilter();
+}
+
+// Remove noise on the region, given a source region, dest.
+// region, width and height of the regions, and corner coordinates of
+// a subregion to act upon. Everything outside the subregion is unaffected.
+
+void NoiseReduction::filterImage(void)
+{
+ int bytes = m_orgImage.bytesDepth(); // Bytes per pixel sample
+ uchar *srcPR = m_orgImage.bits();
+ uchar *destPR = m_destImage.bits();
+ int width = m_orgImage.width();
+ int height = m_orgImage.height();
+
+ int row, col, i, progress;
+ float prob = 0.0;
+
+ int w = (int)((m_radius + m_lookahead + m_damping + m_phase) * 4.0 + 40.0);
+
+ // NOTE: commented from original implementation
+ // if (radius < m_lookahead) w = m_lookahead * 4.0 + 40.0;
+
+ float csmooth = m_csmooth;
+
+ // Raw Filter preview
+
+ if (csmooth >= 0.99) csmooth = 1.0;
+
+ // Allocate and init buffers
+
+ uchar *src = new uchar[ TQMAX (width, height) * bytes ];
+ uchar *dest = new uchar[ TQMAX (width, height) * bytes ];
+ float *data = new float[ TQMAX (width, height) + 2*w ];
+ float *data2 = new float[ TQMAX (width, height) + 2*w ];
+ float *buffer = new float[ TQMAX (width, height) + 2*w ];
+ float *rbuf = new float[ TQMAX (width, height) + 2*w ];
+ float *tbuf = new float[ TQMAX (width, height) + 2*w ];
+
+ memset (src, 0, TQMAX (width, height) * bytes);
+ memset (dest, 0, TQMAX (width, height) * bytes);
+
+ for (i=0 ; i < TQMAX(width,height)+2*w-1 ; i++)
+ data[i] = data2[i] = buffer[i] = rbuf[i] = tbuf[i] = 0.0;
+
+ // Initialize the damping filter coefficients
+
+ iir_init(m_radius);
+
+ // blur the rows
+
+ for (row = 0 ; !m_cancel && (row < height) ; row++)
+ {
+ memcpy(src, srcPR + row*width*bytes, width*bytes);
+ memcpy(dest, src, width*bytes);
+
+ blur_line (data+w, data2+w, buffer+w, rbuf+w, tbuf+w, src, dest, width);
+
+ memcpy(destPR + row*width*bytes, dest, width*bytes);
+
+ progress = (int)(((double)row * 20.0) / height);
+ if ( progress%2 == 0 )
+ postProgress( progress );
+ }
+
+ // blur the cols
+
+ for (col = 0 ; !m_cancel && (col < width) ; col++)
+ {
+ for (int n = 0 ; n < height ; n++)
+ memcpy(src + n*bytes, destPR + (col + width*n)*bytes, bytes);
+
+ for (int n = 0 ; n < height ; n++)
+ memcpy(dest + n*bytes, srcPR + (col + width*n)*bytes, bytes);
+
+ blur_line (data+w, data2+w, buffer+w, rbuf+w, tbuf+w, src, dest, height);
+
+ for (int n = 0 ; n < height ; n++)
+ memcpy(destPR + (col + width*n)*bytes, dest + n*bytes, bytes);
+
+ progress = (int)(20.0 + ((double)col * 20.0) / width);
+ if ( progress%2 == 0 )
+ postProgress( progress );
+ }
+
+ // merge the source and destination (which currently contains
+ // the blurred version) images
+
+ for (row = 0 ; !m_cancel && (row < height) ; row++)
+ {
+ uchar *s = src;
+ uchar *d = dest;
+ unsigned short *s16 = (unsigned short *)src;
+ unsigned short *d16 = (unsigned short *)dest;
+ float value;
+ int u, v;
+
+ // get source row
+
+ memcpy(src, srcPR + row*width*bytes, width*bytes);
+ memcpy(dest, destPR + row*width*bytes, width*bytes);
+
+ // get dest row and combine the two
+
+ float t = m_csmooth;
+ float t2 = m_lsmooth;
+
+ // Values are squared, so that sliders get a nonlinear chracteristic
+ // for better adjustment accuracy when values are small.
+ t*=t;
+ t2*=t2;
+
+ for (u = 0 ; !m_cancel && (u < width) ; u++)
+ {
+ float dpix[3], spix[3];
+ float lum, red, green, blue;
+ float lum2, red2, green2, blue2;
+
+ if (m_orgImage.sixteenBit()) // 16 bits image
+ {
+ red = (float) s16[2]/(float)m_clampMax;
+ green = (float) s16[1]/(float)m_clampMax;
+ blue = (float) s16[0]/(float)m_clampMax;
+ }
+ else // 8 bits image
+ {
+ red = (float) s[2]/(float)m_clampMax;
+ green = (float) s[1]/(float)m_clampMax;
+ blue = (float) s[0]/(float)m_clampMax;
+ }
+
+ spix[2] = red;
+ spix[1] = green;
+ spix[0] = blue;
+
+ lum = (FR*red + FG*green + FB*blue);
+
+ if (m_orgImage.sixteenBit()) // 16 bits image
+ {
+ red2 = (float) d16[2]/(float)m_clampMax;
+ green2 = (float) d16[1]/(float)m_clampMax;
+ blue2 = (float) d16[0]/(float)m_clampMax;
+ }
+ else // 8 bits image
+ {
+ red2 = (float) d[2]/(float)m_clampMax;
+ green2 = (float) d[1]/(float)m_clampMax;
+ blue2 = (float) d[0]/(float)m_clampMax;
+ }
+
+ lum2 = (FR*red2 + FG*green2 + FB*blue2);
+
+ // Calculate luminance error (contrast error) for filtered template.
+ // This error is biggest, where edges are. Edges anyway cannot be filtered.
+ // Therefore we can correct luminance error in edges without increasing noise.
+ // Should be adjusted carefully, or not so carefully if you intentionally want to add noise.
+ // Noise, if not colorized, /can/ look good, so this makes sense.
+
+ float dl = lum - lum2;
+
+ // Multiply dl with first derivative of gamma curve divided by derivative value for midtone 0.5
+ // So bright tones will be corrected more (get more luminance noise and -information) than
+ // darker values because bright parts of image generally are less noisy, this is what we want.
+
+ dl *= pow(lum2/0.5, m_gamma-1.0);
+
+ if (t2 > 0.0)
+ dl *= (1.0 - exp(-dl*dl/(2.0*t2*t2)));
+
+ // NOTE: commented from original implementation
+ // if (dl > p) dl = p;
+ // if (dl < -p) dl = -p;
+
+ dpix[2] = red2 + dl;
+ dpix[1] = green2 + dl;
+ dpix[0] = blue2 + dl;
+
+ for (v = 0 ; !m_cancel && (v < 3) ; v++)
+ {
+ float value = spix[v];
+ float fvalue = dpix[v];
+ float mvalue = (value + fvalue)/2.0;
+ float diff = (value) - (fvalue);
+
+ // Multiply diff with first derivative of gamma curve divided by derivative value for midtone 0.5
+ // So midtones will stay unchanged, darker values get more blur and brighter values get less blur
+ // when we increase gamma.
+
+ diff *= pow(mvalue/0.5, m_gamma-1.0);
+
+ // Calculate noise probability for pixel
+ // TODO : probably it is not probability but an arbitrary curve.
+ // Probably we should provide a GUI-interface for this!!!
+
+ if (t > 0.0)
+ prob = exp(-diff*diff/(2.0*t*t));
+ else
+ prob = 0.0;
+
+ // Allow viewing of raw filter output
+
+ if (t >= 0.99)
+ prob = 1.0;
+
+ dpix[v] = value = fvalue * prob + value * (1.0 - prob);
+ }
+
+ if (m_orgImage.sixteenBit()) // 16 bits image
+ {
+ value = dpix[0]*(float)m_clampMax+0.5;
+ d16[0] = (unsigned short)CLAMP(value, 0, m_clampMax);
+ value = dpix[1]*(float)m_clampMax+0.5;
+ d16[1] = (unsigned short)CLAMP(value, 0, m_clampMax);
+ value = dpix[2]*(float)m_clampMax+0.5;
+ d16[2] = (unsigned short)CLAMP(value, 0, m_clampMax);
+
+ d16 += 4;
+ s16 += 4;
+ }
+ else // 8 bits image
+ {
+ value = dpix[0]*(float)m_clampMax+0.5;
+ d[0] = (uchar)CLAMP(value, 0, m_clampMax);
+ value = dpix[1]*(float)m_clampMax+0.5;
+ d[1] = (uchar)CLAMP(value, 0, m_clampMax);
+ value = dpix[2]*(float)m_clampMax+0.5;
+ d[2] = (uchar)CLAMP(value, 0, m_clampMax);
+
+ d += 4;
+ s += 4;
+ }
+ }
+
+ memcpy(destPR + row*width*bytes, dest, width*bytes);
+
+ progress = (int)(40.0 + ((double)row * 60.0) / height);
+ if ( progress%2 == 0 )
+ postProgress( progress );
+ }
+
+ delete [] data;
+ delete [] data2;
+ delete [] buffer;
+ delete [] rbuf;
+ delete [] tbuf;
+ delete [] dest;
+ delete [] src;
+}
+
+// This function is written as if it is blurring a column at a time,
+// even though it can operate on rows, too. There is no difference
+// in the processing of the lines, at least to the blur_line function.
+// 'len' is the length of src and dest
+
+void NoiseReduction::blur_line(float* const data, float* const data2, float* const buffer,
+ float* rbuf, float* tbuf, const uchar *src, uchar *dest, int len)
+{
+ int b;
+ int row;
+ int idx;
+
+ unsigned short *src16 = (unsigned short *)src;
+ unsigned short *dest16 = (unsigned short *)dest;
+
+ // Calculate radius factors
+
+ for (row = 0, idx = 0 ; !m_cancel && (idx < len) ; row += 4, idx++)
+ {
+ // Color weigths are chosen proportional to Bayer Sensor pixel count
+
+ if (m_orgImage.sixteenBit()) // 16 bits image
+ {
+ data[idx] = (float) dest16[row+2] / (float)m_clampMax * 0.25; // Red color
+ data[idx] += (float) dest16[row+1] / (float)m_clampMax * 0.5; // Green color
+ data[idx] += (float) dest16[row] / (float)m_clampMax * 0.25; // Blue color
+ data[idx] = mypow(data[idx], m_gamma);
+ }
+ else // 8 bits image
+ {
+ data[idx] = (float) dest[row+2] / (float)m_clampMax * 0.25; // Red color
+ data[idx] += (float) dest[row+1] / (float)m_clampMax * 0.5; // Green color
+ data[idx] += (float) dest[row] / (float)m_clampMax * 0.25; // Blue color
+ data[idx] = mypow(data[idx], m_gamma);
+ }
+ }
+
+ filter(data, data2, buffer, rbuf, tbuf, len, -1);
+
+ // Do actual filtering
+
+ for (b = 0 ; !m_cancel && (b < 3) ; b++)
+ {
+ for (row = b, idx = 0 ; !m_cancel && (idx < len) ; row += 4, idx++)
+ {
+ if (m_orgImage.sixteenBit()) // 16 bits image
+ data[idx] = (float)src16[row] / (float)m_clampMax;
+ else // 8 bits image
+ data[idx] = (float)src[row] / (float)m_clampMax;
+ }
+
+ filter(data, data2, buffer, rbuf, tbuf, len, b);
+
+ for (row = b, idx = 0 ; !m_cancel && (idx < len) ; row += 4, idx++)
+ {
+ int value = (int)(data[idx] * (float)m_clampMax + 0.5);
+
+ if (m_orgImage.sixteenBit()) // 16 bits image
+ dest16[row] = (unsigned short)CLAMP( value, 0, m_clampMax);
+ else // 8 bits image
+ dest[row] = (uchar)CLAMP( value, 0, m_clampMax);
+ }
+ }
+}
+
+void NoiseReduction::iir_init(double r)
+{
+ if (m_iir.r == r)
+ return;
+
+ // damping settings;
+ m_iir.r = r;
+
+ double q;
+
+ if ( r >= 2.5)
+ q = 0.98711 * r - 0.96330;
+ else
+ q = 3.97156 - 4.14554 * sqrt(1.0 - 0.26891 * r);
+
+ m_iir.q = q;
+ m_iir.b0 = 1.57825 + ((0.422205 * q + 1.4281) * q + 2.44413) * q;
+ m_iir.b1 = ((1.26661 * q +2.85619) * q + 2.44413) * q / m_iir.b0;
+ m_iir.b2 = - ((1.26661*q +1.4281) * q * q ) / m_iir.b0;
+ m_iir.b3 = 0.422205 * q * q * q / m_iir.b0;
+ m_iir.B = 1.0 - (m_iir.b1 + m_iir.b2 + m_iir.b3);
+}
+
+void NoiseReduction::box_filter(double *src, double *end, double *dest, double radius)
+{
+ int boxwidth = 1;
+ float box = (*src);
+ float fbw = 2.0 * radius;
+
+ if (fbw < 1.0)
+ fbw = 1.0;
+
+ while(boxwidth+2 <= (int) fbw) boxwidth+=2, box += (src[boxwidth/2]) + (src[-boxwidth/2]);
+
+ double frac = (fbw - (double) boxwidth) / 2.0;
+ int bh = boxwidth / 2;
+ int bh1 = boxwidth / 2+1;
+
+ for ( ; src <= end ; src++, dest++)
+ {
+ *dest = (box + frac * ((src[bh1])+(src[-bh1]))) / fbw;
+ box = box - (src[-bh]) + (src[bh1]);
+ }
+}
+
+// Bidirectional IIR-filter, speed optimized
+
+void NoiseReduction::iir_filter(float* const start, float* const end, float* dstart,
+ double radius, const int type)
+{
+ if (!dstart)
+ dstart = start;
+
+ int width;
+ float *src = start;
+ float *dest = dstart;
+ float *dend = dstart + (end - start);
+
+ radius = floor((radius + 0.1) / 0.5) * 0.5;
+
+ // NOTE: commented from original implementation
+ // gfloat boxwidth = radius * 2.0;
+ // gint bw = (gint) boxwidth;
+
+ int ofs = (int)radius;
+ if (ofs < 1) ofs = 1;
+
+ double d1, d2, d3;
+
+ width = end - start + 1;
+
+ if (radius < 0.25)
+ {
+ if ( start != dest )
+ {
+ memcpy(dest, start, width*sizeof(*dest));
+ return;
+ }
+ }
+
+ iir_init(radius);
+
+ const double b1 = m_iir.b1;
+ const double b2 = m_iir.b2 / m_iir.b1;
+ const double b3 = m_iir.b3 / m_iir.b2;
+ const double b = m_iir.B / m_iir.b3;
+
+ switch(type)
+ {
+ case Gaussian:
+
+ d1 = d2 = d3 = *dest;
+ dend -= 6;
+ src--;
+ dest--;
+
+ while (dest < dend)
+ {
+ IIR1(*(++dest), *(++src));
+ IIR2(*(++dest), *(++src));
+ IIR3(*(++dest), *(++src));
+ IIR1(*(++dest), *(++src));
+ IIR2(*(++dest), *(++src));
+ IIR3(*(++dest), *(++src));
+ }
+
+ dend += 6;
+
+ while (1)
+ {
+ if (++dest > dend) break;
+ IIR1(*dest,*(++src));
+ if (++dest > dend) break;
+ IIR2(*dest,*(++src));
+ if (++dest > dend) break;
+ IIR3(*dest,*(++src));
+ }
+
+ d1 = d2 = d3 = dest[-1];
+ dstart += 6;
+
+ while (dest > dstart)
+ {
+ --dest, IIR1(*dest, *dest);
+ --dest, IIR2(*dest, *dest);
+ --dest, IIR3(*dest, *dest);
+ --dest, IIR1(*dest, *dest);
+ --dest, IIR2(*dest, *dest);
+ --dest, IIR3(*dest, *dest);
+ }
+
+ dstart -= 6;
+
+ while (1)
+ {
+ if (--dest < dstart) break;
+ IIR1(*dest, *dest);
+ if (--dest < dstart) break;
+ IIR2(*dest, *dest);
+ if (--dest < dstart) break;
+ IIR3(*dest, *dest);
+ }
+
+ break;
+
+ case SecondDerivative: // rectified and filtered second derivative, source and dest may be equal
+
+ d1 = d2 = d3 = 0.0;
+ dest[0] = dest[ofs] = 0.0;
+ dend -= 6;
+ dest--;
+ src--;
+
+ while (dest < dend)
+ {
+ ++src, IIR1(*(++dest), src[ofs]-src[0]);
+ ++src, IIR2(*(++dest), src[ofs]-src[0]);
+ ++src, IIR3(*(++dest), src[ofs]-src[0]);
+ ++src, IIR1(*(++dest), src[ofs]-src[0]);
+ ++src, IIR2(*(++dest), src[ofs]-src[0]);
+ ++src, IIR3(*(++dest), src[ofs]-src[0]);
+ }
+
+ dend += 6;
+
+ while (1)
+ {
+ if (++dest > dend) break;
+ ++src, IIR1(*dest, src[ofs]-src[0]);
+ if (++dest > dend) break;
+ ++src, IIR2(*dest, src[ofs]-src[0]);
+ if (++dest > dend) break;
+ ++src, IIR3(*dest, src[ofs]-src[0]);
+ }
+
+ d1 = d2 = d3 = 0.0;
+ dest[-1] = dest[-ofs-1] = 0.0;
+ dstart += 6;
+
+ while (dest > dstart)
+ {
+ --dest, IIR1A(*dest, dest[0]-dest[-ofs]);
+ --dest, IIR2A(*dest, dest[0]-dest[-ofs]);
+ --dest, IIR3A(*dest, dest[0]-dest[-ofs]);
+ --dest, IIR1A(*dest, dest[0]-dest[-ofs]);
+ --dest, IIR2A(*dest, dest[0]-dest[-ofs]);
+ --dest, IIR3A(*dest, dest[0]-dest[-ofs]);
+ }
+
+ dstart -= 6;
+
+ while (1)
+ {
+ if (--dest < dstart) break;
+ IIR1A(*dest, dest[0]-dest[-ofs]);
+ if (--dest < dstart) break;
+ IIR2A(*dest, dest[0]-dest[-ofs]);
+ if (--dest < dstart) break;
+ IIR3A(*dest, dest[0]-dest[-ofs]);
+ }
+
+ break;
+ }
+}
+
+// A forward-backward box filter is used here and the radius is adapted to luminance jump.
+// Radius is calculated fron 1st and 2nd derivative of intensity values.
+// (Its not exactly 2nd derivative, but something similar, optimized by experiment)
+// The radius variations are filtered. This reduces spatial phase jitter.
+
+void NoiseReduction::filter(float *buffer, float *data, float *data2, float *rbuf,
+ float */*tbuf*/, int width, int color)
+{
+ float *lp = data;
+ float *rp = data + width-1;
+ float *lp2 = data2;
+ float *blp = buffer;
+ float *brp = buffer + width-1;
+ float *rbuflp = rbuf;
+ float *rbufrp = rbuf + width-1;
+ float fboxwidth = m_radius*2.0;
+ float fradius = m_radius;
+ float *p1, *p2;
+
+ if (fboxwidth < 1.0) fboxwidth = 1.0 ;
+ if (fradius < 0.5) fradius = 0.5;
+
+ int i, pass;
+ int ofs, ofs2;
+ float maxrad;
+ float fbw;
+ float val;
+ double rfact = m_effect*m_effect;
+ double sharp = m_sharp;
+
+ ofs2 = (int)floor(m_damping * 2.0 + 0.1);
+ ofs = (int)floor(m_lookahead * 2.0 + 0.1);
+ int w = (int)(fboxwidth + m_damping + m_lookahead + m_phase + 2.0);
+
+ // Mirror image edges
+
+ for (i=1 ; i <= w ; i++)
+ blp[-i] = blp[i];
+
+ for (i=1 ; i <= w ; i++)
+ brp[i] = brp[-i];
+
+ if (color < 0) // Calc 2nd derivative
+ {
+ // boost high frequency in rbuf
+
+ for (p1 = blp, p2 = rbuflp ; p1 <= brp ; p1++, p2++)
+ {
+ *p2 = (sharp+1.0) * p1[0] - sharp * 0.5 * (p1[-ofs]+p1[ofs]);
+ }
+
+ iir_filter(rbuflp-w, rbufrp+w, blp-w, m_lookahead, SecondDerivative);
+
+ // Mirror image edges
+
+ for (i = 1 ; i <= w ; i++)
+ blp[-i] = blp[i];
+
+ for (i = 1 ; i <= w ; i++)
+ brp[i] = brp[-i];
+
+ // boost high frequency in rbuf
+
+ for (p1 = blp, p2 = rbuflp ; p1 <= brp ; p1++, p2++)
+ {
+ *p2 = ((sharp+1.0) * (p1[0]) - sharp * 0.5 * ((p1[-ofs2])+(p1[ofs2])));
+ }
+
+ // Mirror rbuf edges
+
+ for (i = 1 ; i <= w ; i++)
+ rbuflp[-i] = rbuflp[i];
+
+ for (i = 1 ; i <= w ; i++)
+ rbufrp[i] = rbufrp[-i];
+
+ // Lowpass (gauss) filter rbuf, remove phase jitter
+
+ iir_filter(rbuflp-w+5, rbufrp+w-5, rbuflp-w+5, m_damping, Gaussian);
+
+ for (i = -w+5; i < width-1+w-5 ; i++)
+ {
+ // NOTE: commented from original implementation
+ // val = rbuflp[i];
+
+ val = rbuflp[i]-rfact;
+
+ // Avoid division by zero, clip negative filter overshoot
+
+ if (val < rfact/fradius) val=rfact/fradius;
+
+ val = rfact/val;
+
+ // NOTE: commented from original implementation
+ // val = pow(val/fradius,m_phase)*fradius;
+
+ if (val < 0.5) val = 0.5;
+
+ rbuflp[i] = val*2.0;
+ }
+
+ // Mirror rbuf edges
+
+ for (i=1 ; i <= w ; i++)
+ rbuflp[-i] = rbuflp[i];
+
+ for (i=1 ; i <= w ; i++)
+ rbufrp[i] = rbufrp[-i];
+
+ return;
+ }
+
+ // Calc lowpass filtered input signal
+
+ iir_filter(blp-w+1, brp+w-1, lp2-w+1, m_radius, Gaussian);
+
+ // Subtract low frequency from input signal (aka original image data)
+ // and predistort this signal
+
+ val = m_texture + 1.0;
+
+ for (i = -w+1 ; i <= width-1+w-1 ; i++)
+ {
+ blp[i] = mypow(blp[i] - lp2[i], val);
+ }
+
+ float *src, *dest;
+ val = m_texture + 1.0;
+
+ pass = 2;
+
+ while (pass--)
+ {
+ float sum;
+ int ibw;
+ src = blp;
+ dest = lp;
+ maxrad = 0.0;
+
+ // Mirror left edge
+
+ for (i=1 ; i <= w ; i++)
+ src[-i] = src[i];
+
+ sum = (src[-1] += src[-2]);
+
+ // forward pass
+
+ for (rbuf = rbuflp-(int) m_phase ; rbuf <= rbufrp; src++, dest++, rbuf++)
+ {
+ // NOTE: commented from original implementation
+ //fbw = fabs( rbuf[-ofs2]*ll2+rbuf[-ofs2-1]*rl2);
+
+ fbw = *rbuf;
+
+ if (fbw > (maxrad += 1.0)) fbw = maxrad;
+ else if (fbw < maxrad) maxrad = fbw;
+
+ ibw = (int)fbw;
+ *src = sum += *src;
+ *dest = (sum-src[-ibw]+(src[-ibw]-src[-ibw-1])*(fbw-ibw))/fbw;
+ }
+
+ src = rp;
+ dest = brp;
+ maxrad = 0.0;
+
+ // Mirror right edge
+
+ for (i=1 ; i <= w ; i++)
+ src[i] = src[-i];
+
+ sum = (src[1] += src[2]);
+
+ // backward pass
+
+ for ( rbuf = rbufrp +(int) m_phase ; rbuf >= rbuflp; src--, dest--, rbuf--)
+ {
+ // NOTE: commented from original implementation
+ //fbw = fabs( rbuf[ofs2]*ll2+rbuf[ofs2+1]*rl2);
+
+ fbw = *rbuf;
+
+ if (fbw > (maxrad +=1.0)) fbw = maxrad;
+ else if (fbw < maxrad) maxrad = fbw;
+
+ ibw = (int)fbw;
+
+ *src = sum += *src;
+ *dest = (sum-src[ibw]+(src[ibw]-src[ibw+1])*(fbw-ibw))/fbw;
+ }
+ }
+
+ val = 1.0 / (m_texture + 1.0);
+
+ for (i = -w+1 ; i <= width-1+w-1 ; i++)
+ {
+ // Undo predistortion
+
+ blp[i]= mypow(blp[i],val);
+
+ // Add in low frequency
+
+ blp[i] += lp2[i];
+
+ // NOTE: commented from original implementation
+ // if (blp[i] >= 0.0) blp[i] = pow(blp[i],val);
+ // else blp[i] = 0.0;
+ }
+}
+
+} // NameSpace DigikamNoiseReductionImagesPlugin
diff --git a/src/imageplugins/noisereduction/noisereduction.h b/src/imageplugins/noisereduction/noisereduction.h
new file mode 100644
index 00000000..69e14123
--- /dev/null
+++ b/src/imageplugins/noisereduction/noisereduction.h
@@ -0,0 +1,257 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-05-25
+ * Description : Noise Reduction threaded image filter.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * Original Noise Filter algorithm copyright (C) 2005
+ * Peter Heckert <peter dot heckert at arcor dot de>
+ * from dcamnoise2 gimp plugin available at this url :
+ * http://home.arcor.de/peter.heckert/dcamnoise2-0.63.c
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef NOISE_REDUCTION_H
+#define NOISE_REDUCTION_H
+
+// C++ includes.
+
+#include <cmath>
+
+// Digikam includes.
+
+#include "dimgthreadedfilter.h"
+
+/**============= NOTICE TO USE THE FILTER ===============================================================
+ *
+ * Let me explain, how the filter works, some understanding is necessary to use it:
+ *
+ * Hint for the novice user:
+ * In most cases only Filter Max Radius, Filter treshold and Texture Detail are needed and the other
+ * params can be left at their default setting.
+ *
+ * Main Filter (Preprocessing)
+ * First, a filtered template is generated, using an adaptive filter.
+ * To see this template, we must set _Luminance tolerance, _Color tolerance to 1.0.
+ *------------------------------------------------------------------------------------------------------------
+ *
+ * "Filter max. Radius" is preset to 5.0
+ * This is good for most noise situations.
+ * In any case it must be about the same size as noise granularity ore somewhat more.
+ * If it is set higher than necessary, then it can cause unwanted blur.
+ *------------------------------------------------------------------------------------------------------------
+ *
+ * "Filter Threshold" should be set so that edges are clearly visible and noise is smoothed out.
+ * This threshold value is not bound to any intensity value, it is bound to the second derivative of
+ * intensity values.
+ * Simply adjust it and watch the preview. Adjustment must be made carefully, because the gap
+ * between "noisy", "smooth", and "blur" is very small. Adjust it as carefully as you would adjust
+ * the focus of a camera.
+ *------------------------------------------------------------------------------------------------------------
+ *
+ * "Lookahead" defines the pixel distance in which the filter looks ahead for luminance variations
+ * Normally the default value should do.
+ * When _Lookahead is increased, then spikenoise is erased.
+ * Eventually readjust Filter treshold, when you changed lookahead.
+ * When the value is to high, then the adaptive filter cannot longer accurately track image details, and
+ * noise can reappear or blur can occur.
+ *
+ * Minimum value is 1.0, this gives best accuracy when blurring very weak noise.
+ *
+ * I never had good success with other values than 2.0.
+ * However, for images with extemely high or low resolution another value possibly is better.
+ * Use it only as a last ressort.
+ *------------------------------------------------------------------------------------------------------------
+ *
+ * "Phase Jitter Damping" defines how fast the adaptive filter-radius reacts to luminance variations.
+ * I have preset a value, that should do in most cases.
+ * If increased, then edges appear smoother, if too high, then blur may occur.
+ * If at minimum then noise and phase jitter at edges can occur.
+ * It can suppress Spike noise when increased and this is the preferred method to remove spike noise.
+ *------------------------------------------------------------------------------------------------------------
+ *
+ * "Sharpness" does just what it says, it improves sharpness. It improves the frequency response for the filter.
+ * When it is too strong then not all noise can be removed, or spike noise may appear.
+ * Set it near to maximum, if you want to remove weak noise or JPEG-artifacts, without loosing detail.
+ *------------------------------------------------------------------------------------------------------------
+ *
+ * "Erosion". The new filter gives better sharpness and this also gives problems
+ * with spike noise. The Erosion param erodes singular spikes and it has a smooth effect to edges, and sharpens
+ * edges by erosion, so noise at edges is eroded.
+ * The effect is dependant from sharpness,phase-jitter damping and lookahead.
+ * Set it to minimum (zero), if you want to remove weak noise or JPEG-artifacts.
+ * When "Erosion" is increased, then also increasing "Phase Jitter Damping" is often useful
+ *
+ * It works nicely. Apart from removing spike noise it has a sharpening and antialiasing effect to edges
+ * (Sharpening occurs by erosion, not by deconvolution)
+ *------------------------------------------------------------------------------------------------------------
+ *
+ * "Texture Detail" can be used, to get more or less texture accuracy.
+ * When decreased, then noise and texture are blurred out, when increased then texture is
+ * amplified, but also noise will increase.
+ * It has almost no effect to image edges, opposed to Filter theshold, which would blur edges, when increased.
+ *
+ * E.g. if Threshold is adjusted in away so that edges are sharp, and there is still too much area noise, then
+ * Texture detail could be used to reduce noise without blurring edges.
+ * (Another way would be to decrease radius and to increase threshold)
+ *
+ *------------------------------------------------------------------------------------------------------------
+ *
+ * The filtered image that is now seen in the preview, is used as template for the following processing steps,
+ * therefore it is important to do this adjustment in first place and to do it as good as possible.
+ *------------------------------------------------------------------------------------------------------------
+ *
+ * Combining original image and filtered image, using tolerance thresholds (Postprocessing)
+ * This can give a final touch of sharpness to your image.
+ * It is not necessary to do this, if you want to reduce JPEG-artifacts or weak noise.
+ * It's purpose is to master strong noise without loosing too much sharpness.
+ *
+ * Note, that this all is done in one filter invocation. Preprocessing and postprocessing is done in one run,
+ * but logically and in the algorithm they are different and ordered processes.
+ *
+ *
+ * Adjust _Color tolerance or/and Luminance tolerance, (if necessary) so that you get the final image.
+ * I recommend to use only one, either _Color or _Luminance.
+ * These settings do not influence the main smoothing process. What they really do is this:
+ *
+ * The tolerance values are used as error-thresholds to compare the filtered template with the original
+ * image. The plugin algorithm uses them to combine the filtered template with the original image
+ * so that noise and filter errors (blur) are thrown out.
+ * A filtered pixel, that is too far away from the original pixel will be overridden by original image content.
+ *
+ * Hint:
+ * If you cange other sliders, like lookahead or Texture Detail, then you should set color tolerance and
+ * luminance tolerance to 1.0 (right end), because otherwise the filtered template is partially hidden
+ * and e.g. the effects for the damping filter cant be seen clearly and cant be optimized.
+ *------------------------------------------------------------------------------------------------------------
+ *
+ * _Gamma can be used to increase the tolerance values for darker areas (which commonly are more noisy)
+ * This results in more blur for shadow areas.
+ *
+ * Hint for users of previous versions:
+ * Gamma also influences the main-filter process. While the previous version did not have this feature,
+ * I have reimplemented it, however, the algorithm used is totally new.
+ *
+ *
+ * Keep in mind, how the filter works, then usage should be easy!
+ *
+ *
+ * ================ THEORY AND TECHNIC =======================================================================
+ *
+ * Some interesting things (theoretic and technic)
+ * This plugin bases on the assumption, that noise has no 2-dimensional correlation and therefore
+ * can be removed in a 1-dimensional process.
+ * To remove noise, I use a four-times boxfilter with variable radius.
+ *
+ * The radius is calculated from 2nd derivative of pixeldata.
+ * A gauss filter is used to calculte 2nd derivative.
+ * The filter has some inbuilt features to clip low amplitude noise to clip very high values that would
+ * slow down response time.
+ * The 2nd derivative is lowpassfiltered and then radius is calculated as (Filter Treshold)/2nd_derivative.
+ * The radius modulation data is precalulated and buffered an is used to steer filter radius when
+ * the actual filtering occurs.
+ *
+ * Noise and texture can be further suppressed by nonlinear distortion before adaptive filtering.
+ * To make this possible I subtract low frequency from image data before denoising, so that I get a
+ * bipolar, zerosymmetric image signal.
+ *
+ * The filter works in a /one-dimensional/ way. It is applied to x and then to y axis.
+ *
+ * After filtering a zerodimensional point operator (pixel by pixel comparison) is used, where
+ * filter-errors are thrown out.
+ * This is meant to limit and control filter errors,it can give "final touch" to the image, but it has
+ * nothing to do with the main filter process.
+ *
+ * I do not know if something like this filter already exists.
+ * It is all based on my own ideas and experiments.
+ * Possibly a separable adaptive gauss-filter is a new thing.
+ * Also it is an impossible thing, from a mathemathical point of view ;-)
+ * It is possible only for bandwidth limited images.
+ * Happyly most photographic images are bandwidth limited, or when they are noisy then we want
+ * to limit banwith locally. And this is, what the filter does: It limits bandwidth locally, dependent
+ * from (approximately) 2nd derivative of intensity.
+ *
+ * Because gauss filtering is essentially linear diffusion, and because this filter uses a variable
+ * nonlinear modulated gaussfilter (four box passes are almost gauss) we could say, that this filter
+ * implements a special subclass of nonlinear adaptive diffusion, which is separable, and indeed,
+ * results are very similar to nonlinear diffusion filters.
+ * However, because the filter is separable, it is much faster and needs less memory.
+ */
+
+namespace DigikamNoiseReductionImagesPlugin
+{
+
+class NoiseReduction : public Digikam::DImgThreadedFilter
+{
+
+public:
+
+ NoiseReduction(Digikam::DImg *orgImage, TQObject *parent,
+ double radius, double lsmooth, double effect, double texture, double sharp,
+ double csmooth, double lookahead, double gamma, double damping, double phase);
+ ~NoiseReduction(){};
+
+private:
+
+ void filterImage(void);
+
+ void iir_init(double r);
+ void box_filter(double *src, double *end, double *dest, double radius);
+ void iir_filter(float* const start, float* const end, float* dstart, double radius, const int type);
+ void filter(float *buffer, float *data, float *data2, float *rbuf, float *tbuf, int width, int color);
+ void blur_line(float* const data, float* const data2, float* const buffer,
+ float* rbuf, float* tbuf, const uchar *src, uchar *dest, int len);
+
+ inline double mypow(double val, double ex)
+ {
+ if (fabs(val) < 1e-16) return 0.0;
+ if (val > 0.0) return exp(log(val)*ex);
+ return -exp(log(-val)*ex);
+ };
+
+private:
+
+ struct iir_param
+ {
+ double B, b1, b2, b3, b0, r, q;
+ double *p;
+ } m_iir;
+
+ enum IIRFilteringMode
+ {
+ Gaussian=0,
+ SecondDerivative
+ };
+
+ int m_clampMax;
+
+ double m_radius;
+ double m_lsmooth;
+ double m_csmooth;
+ double m_effect;
+ double m_lookahead;
+ double m_gamma;
+ double m_damping;
+ double m_phase;
+ double m_texture;
+ double m_sharp;
+};
+
+} // NameSpace DigikamNoiseReductionImagesPlugin
+
+#endif /* NOISE_REDUCTION_H */
diff --git a/src/imageplugins/noisereduction/noisereductiontool.cpp b/src/imageplugins/noisereduction/noisereductiontool.cpp
new file mode 100644
index 00000000..d1e4908a
--- /dev/null
+++ b/src/imageplugins/noisereduction/noisereductiontool.cpp
@@ -0,0 +1,536 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-08-24
+ * Description : a plugin to reduce CCD noise.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqcheckbox.h>
+#include <tqfile.h>
+#include <tqimage.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqstring.h>
+#include <tqtabwidget.h>
+#include <tqtextstream.h>
+#include <tqtooltip.h>
+#include <tqwhatsthis.h>
+
+// KDE includes.
+
+#include <tdeaboutdata.h>
+#include <tdeapplication.h>
+#include <tdeconfig.h>
+#include <tdefiledialog.h>
+#include <tdeglobalsettings.h>
+#include <kiconloader.h>
+#include <tdelocale.h>
+#include <tdemessagebox.h>
+#include <kstandarddirs.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/rnuminput.h>
+
+// Local includes.
+
+#include "daboutdata.h"
+#include "ddebug.h"
+#include "dimg.h"
+#include "imageiface.h"
+#include "imagepanelwidget.h"
+#include "editortoolsettings.h"
+#include "noisereduction.h"
+#include "noisereductiontool.h"
+#include "noisereductiontool.moc"
+
+using namespace KDcrawIface;
+using namespace Digikam;
+
+namespace DigikamNoiseReductionImagesPlugin
+{
+
+NoiseReductionTool::NoiseReductionTool(TQObject* parent)
+ : EditorToolThreaded(parent)
+{
+ setName("noisereduction");
+ setToolName(i18n("Noise Reduction"));
+ setToolIcon(SmallIcon("noisereduction"));
+
+ // -------------------------------------------------------------
+
+ m_gboxSettings = new EditorToolSettings(EditorToolSettings::Default|
+ EditorToolSettings::Ok|
+ EditorToolSettings::Cancel|
+ EditorToolSettings::Load|
+ EditorToolSettings::SaveAs|
+ EditorToolSettings::Try,
+ EditorToolSettings::PanIcon);
+
+ TQGridLayout* grid = new TQGridLayout( m_gboxSettings->plainPage(), 1, 1);
+
+ TQTabWidget *mainTab = new TQTabWidget(m_gboxSettings->plainPage());
+ TQWidget* firstPage = new TQWidget( mainTab );
+ TQGridLayout* grid1 = new TQGridLayout(firstPage, 6, 1);
+
+ TQLabel *label1 = new TQLabel(i18n("Radius:"), firstPage);
+
+ m_radiusInput = new RDoubleNumInput(firstPage);
+ m_radiusInput->setPrecision(1);
+ m_radiusInput->setRange(0.0, 10.0, 0.1);
+ m_radiusInput->setDefaultValue(1.0);
+ TQWhatsThis::add( m_radiusInput, i18n("<p><b>Radius</b>: this control selects the "
+ "gliding window size used for the filter. Larger values do not increase "
+ "the amount of time needed to filter each pixel in the image but "
+ "can cause blurring. This window moves across the image, and the "
+ "color in it is smoothed to remove imperfections. "
+ "In any case it must be about the same size as the noise granularity "
+ "or somewhat more. If it is set higher than necessary, then it "
+ "can cause unwanted blur."));
+
+ // -------------------------------------------------------------
+
+ TQLabel *label3 = new TQLabel(i18n("Threshold:"), firstPage);
+
+ m_thresholdInput = new RDoubleNumInput(firstPage);
+ m_thresholdInput->setPrecision(2);
+ m_thresholdInput->setRange(0.0, 1.0, 0.01);
+ m_thresholdInput->setDefaultValue(0.08);
+ TQWhatsThis::add( m_thresholdInput, i18n("<p><b>Threshold</b>: use the slider for coarse adjustment, "
+ "and the spin control for fine adjustment to control edge detection sensitivity. "
+ "This value should be set so that edges and details are clearly visible "
+ "and noise is smoothed out. "
+ "Adjustment must be made carefully, because the gap between \"noisy\", "
+ "\"smooth\", and \"blur\" is very small. Adjust it as carefully as you would adjust "
+ "the focus of a camera."));
+
+ // -------------------------------------------------------------
+
+ TQLabel *label4 = new TQLabel(i18n("Texture:"), firstPage);
+
+ m_textureInput = new RDoubleNumInput(firstPage);
+ m_textureInput->setPrecision(2);
+ m_textureInput->setRange(-0.99, 0.99, 0.01);
+ m_textureInput->setDefaultValue(0.0);
+ TQWhatsThis::add( m_textureInput, i18n("<p><b>Texture</b>: this control sets the texture accuracy. "
+ "This value can be used, to get more or less texture accuracy. When decreased, "
+ "then noise and texture are blurred out, when increased then texture is "
+ "amplified, but also noise will increase. It has almost no effect on image edges."));
+
+ // -------------------------------------------------------------
+
+ TQLabel *label7 = new TQLabel(i18n("Sharpness:"), firstPage); // Filter setting "Lookahead".
+
+ m_sharpnessInput = new RDoubleNumInput(firstPage);
+ m_sharpnessInput->setPrecision(2);
+ m_sharpnessInput->setRange(0.0, 1.0, 0.1);
+ m_sharpnessInput->setDefaultValue(0.25);
+ TQWhatsThis::add( m_sharpnessInput, i18n("<p><b>Sharpness</b>: "
+ "This value improves the frequency response for the filter. "
+ "When it is too strong then not all noise can be removed, or spike noise may appear. "
+ "Set it near to maximum, if you want to remove very weak noise or JPEG-artifacts, "
+ "without losing detail."));
+
+ // -------------------------------------------------------------
+
+ TQLabel *label5 = new TQLabel(i18n("Edge Lookahead:"), firstPage); // Filter setting "Sharp".
+
+ m_lookaheadInput = new RDoubleNumInput(firstPage);
+ m_lookaheadInput->setPrecision(2);
+ m_lookaheadInput->setRange(0.01, 20.0, 0.01);
+ m_lookaheadInput->setDefaultValue(2.0);
+ TQWhatsThis::add( m_lookaheadInput, i18n("<p><b>Edge</b>: "
+ "This value defines the pixel distance to which the filter looks ahead for edges. "
+ "When this value is increased, then spike noise is erased. "
+ "You can eventually re-adjust the <b>Edge</b> filter, when you have changed this setting. "
+ "When this value is too high, the adaptive filter can no longer accurately track "
+ "image details, and noise or blurring can occur."));
+
+ // -------------------------------------------------------------
+
+ TQLabel *label10 = new TQLabel(i18n("Erosion:"), firstPage);
+
+ m_phaseInput = new RDoubleNumInput(firstPage);
+ m_phaseInput->setPrecision(1);
+ m_phaseInput->setRange(0.5, 20.0, 0.5);
+ m_phaseInput->setDefaultValue(1.0);
+ TQWhatsThis::add( m_phaseInput, i18n("<p><b>Erosion</b>: "
+ "Use this to increase edge noise erosion and spike noise erosion "
+ "(noise is removed by erosion)."));
+
+ grid1->addMultiCellWidget(label1, 0, 0, 0, 0);
+ grid1->addMultiCellWidget(m_radiusInput, 0, 0, 1, 1);
+ grid1->addMultiCellWidget(label3, 1, 1, 0, 0);
+ grid1->addMultiCellWidget(m_thresholdInput, 1, 1, 1, 1);
+ grid1->addMultiCellWidget(label4, 2, 2, 0, 0);
+ grid1->addMultiCellWidget(m_textureInput, 2, 2, 1, 1);
+ grid1->addMultiCellWidget(label7, 3, 3, 0, 0);
+ grid1->addMultiCellWidget(m_sharpnessInput, 3, 3, 1, 1);
+ grid1->addMultiCellWidget(label5, 4, 4, 0, 0);
+ grid1->addMultiCellWidget(m_lookaheadInput, 4, 4, 1, 1);
+ grid1->addMultiCellWidget(label10, 5, 5, 0, 0);
+ grid1->addMultiCellWidget(m_phaseInput, 5, 5, 1, 1);
+ grid1->setMargin(m_gboxSettings->spacingHint());
+ grid1->setSpacing(m_gboxSettings->spacingHint());
+ grid1->setColStretch(1, 10);
+ grid1->setRowStretch(6, 10);
+
+ mainTab->addTab( firstPage, i18n("Details") );
+
+ // -------------------------------------------------------------
+
+ TQWidget* secondPage = new TQWidget( mainTab );
+ TQGridLayout* grid2 = new TQGridLayout( secondPage, 4, 1);
+
+ TQLabel *label2 = new TQLabel(i18n("Luminance:"), secondPage);
+
+ m_lumToleranceInput = new RDoubleNumInput(secondPage);
+ m_lumToleranceInput->setPrecision(1);
+ m_lumToleranceInput->setRange(0.0, 1.0, 0.1);
+ m_lumToleranceInput->setDefaultValue(1.0);
+ TQWhatsThis::add( m_lumToleranceInput, i18n("<p><b>Luminance</b>: this control sets the luminance tolerance of the image."
+ "We recommend using either the <b>Color</b> or the <b>Luminance</b> tolerance settings "
+ "to make an image correction, not both at the same time. These settings "
+ "do not influence the main smoothing process controlled by the <b>Details</b> "
+ "settings."));
+
+ // -------------------------------------------------------------
+
+ TQLabel *label6 = new TQLabel(i18n("Color:"), secondPage);
+
+ m_csmoothInput = new RDoubleNumInput(secondPage);
+ m_csmoothInput->setPrecision(1);
+ m_csmoothInput->setRange(0.0, 1.0, 0.1);
+ m_csmoothInput->setDefaultValue(1.0);
+ TQWhatsThis::add( m_csmoothInput, i18n("<p><b>Color</b>: this control sets the color tolerance of the image. It is "
+ "recommended using either the <b>Color</b> or the <b>Luminance</b> tolerance "
+ "to make image correction, not both at the same time. These settings "
+ "do not influence the main smoothing process controlled by the <b>Details</b> "
+ "settings."));
+
+ // -------------------------------------------------------------
+
+ TQLabel *label8 = new TQLabel(i18n("Gamma:"), secondPage);
+
+ m_gammaInput = new RDoubleNumInput(secondPage);
+ m_gammaInput->setPrecision(1);
+ m_gammaInput->setRange(0.3, 3.0, 0.1);
+ m_gammaInput->setDefaultValue(1.4);
+ TQWhatsThis::add( m_gammaInput, i18n("<p><b>Gamma</b>: this control sets the gamma tolerance of the image. This value "
+ "can be used to increase the tolerance values for darker areas (which commonly "
+ "are noisier). This results in more blur for shadow areas."));
+
+ // -------------------------------------------------------------
+
+ TQLabel *label9 = new TQLabel(i18n("Damping:"), secondPage);
+
+ m_dampingInput = new RDoubleNumInput(secondPage);
+ m_dampingInput->setPrecision(1);
+ m_dampingInput->setRange(0.5, 20.0, 0.5);
+ m_dampingInput->setDefaultValue(5.0);
+ TQWhatsThis::add( m_dampingInput, i18n("<p><b>Damping</b>: this control sets the phase-jitter damping adjustment. "
+ "This value defines how fast the adaptive filter-radius reacts to luminance "
+ "variations. If increased, then edges appear smoother; if too high, then blur "
+ "may occur. If at minimum, then noise and phase jitter at the edges can occur. It "
+ "can suppress spike noise when increased, and this is the preferred method to "
+ "remove it."));
+
+ grid2->addMultiCellWidget(label2, 0, 0, 0, 0);
+ grid2->addMultiCellWidget(m_lumToleranceInput, 0, 0, 1, 1);
+ grid2->addMultiCellWidget(label6, 1, 1, 0, 0);
+ grid2->addMultiCellWidget(m_csmoothInput, 1, 1, 1, 1);
+ grid2->addMultiCellWidget(label8, 2, 2, 0, 0);
+ grid2->addMultiCellWidget(m_gammaInput, 2, 2, 1, 1);
+ grid2->addMultiCellWidget(label9, 3, 3, 0, 0);
+ grid2->addMultiCellWidget(m_dampingInput, 3, 3, 1, 1);
+ grid2->setMargin(m_gboxSettings->spacingHint());
+ grid2->setSpacing(m_gboxSettings->spacingHint());
+ grid2->setColStretch(1, 10);
+ grid2->setRowStretch(4, 10);
+
+ mainTab->addTab( secondPage, i18n("Advanced") );
+
+ grid->addMultiCellWidget(mainTab, 0, 0, 0, 1);
+ grid->setRowStretch(1, 10);
+ grid->setMargin(m_gboxSettings->spacingHint());
+ grid->setSpacing(m_gboxSettings->spacingHint());
+
+ setToolSettings(m_gboxSettings);
+
+ m_previewWidget = new ImagePanelWidget(470, 350, "noisereduction Tool", m_gboxSettings->panIconView());
+
+ setToolView(m_previewWidget);
+ init();
+}
+
+NoiseReductionTool::~NoiseReductionTool()
+{
+}
+
+void NoiseReductionTool::renderingFinished()
+{
+ m_radiusInput->setEnabled(true);
+ m_lumToleranceInput->setEnabled(true);
+ m_thresholdInput->setEnabled(true);
+ m_textureInput->setEnabled(true);
+ m_sharpnessInput->setEnabled(true);
+ m_csmoothInput->setEnabled(true);
+ m_lookaheadInput->setEnabled(true);
+ m_gammaInput->setEnabled(true);
+ m_dampingInput->setEnabled(true);
+ m_phaseInput->setEnabled(true);
+}
+
+void NoiseReductionTool::readSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("noisereduction Tool");
+
+ m_radiusInput->setEnabled(false);
+ m_lumToleranceInput->setEnabled(false);
+ m_thresholdInput->setEnabled(false);
+ m_textureInput->setEnabled(false);
+ m_sharpnessInput->setEnabled(false);
+ m_csmoothInput->setEnabled(false);
+ m_lookaheadInput->setEnabled(false);
+ m_gammaInput->setEnabled(false);
+ m_dampingInput->setEnabled(false);
+ m_phaseInput->setEnabled(false);
+
+ m_radiusInput->setValue(config->readDoubleNumEntry("RadiusAjustment", m_radiusInput->defaultValue()));
+ m_lumToleranceInput->setValue(config->readDoubleNumEntry("LumToleranceAjustment", m_lumToleranceInput->defaultValue()));
+ m_thresholdInput->setValue(config->readDoubleNumEntry("ThresholdAjustment", m_thresholdInput->defaultValue()));
+ m_textureInput->setValue(config->readDoubleNumEntry("TextureAjustment", m_textureInput->defaultValue()));
+ m_sharpnessInput->setValue(config->readDoubleNumEntry("SharpnessAjustment", m_sharpnessInput->defaultValue()));
+ m_csmoothInput->setValue(config->readDoubleNumEntry("CsmoothAjustment", m_csmoothInput->defaultValue()));
+ m_lookaheadInput->setValue(config->readDoubleNumEntry("LookAheadAjustment", m_lookaheadInput->defaultValue()));
+ m_gammaInput->setValue(config->readDoubleNumEntry("GammaAjustment", m_gammaInput->defaultValue()));
+ m_dampingInput->setValue(config->readDoubleNumEntry("DampingAjustment", m_dampingInput->defaultValue()));
+ m_phaseInput->setValue(config->readDoubleNumEntry("PhaseAjustment", m_phaseInput->defaultValue()));
+
+ m_radiusInput->setEnabled(true);
+ m_lumToleranceInput->setEnabled(true);
+ m_thresholdInput->setEnabled(true);
+ m_textureInput->setEnabled(true);
+ m_sharpnessInput->setEnabled(true);
+ m_csmoothInput->setEnabled(true);
+ m_lookaheadInput->setEnabled(true);
+ m_gammaInput->setEnabled(true);
+ m_dampingInput->setEnabled(true);
+ m_phaseInput->setEnabled(true);
+}
+
+void NoiseReductionTool::writeSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("noisereduction Tool");
+ config->writeEntry("RadiusAjustment", m_radiusInput->value());
+ config->writeEntry("LumToleranceAjustment", m_lumToleranceInput->value());
+ config->writeEntry("ThresholdAjustment", m_thresholdInput->value());
+ config->writeEntry("TextureAjustment", m_textureInput->value());
+ config->writeEntry("SharpnessAjustment", m_sharpnessInput->value());
+ config->writeEntry("CsmoothAjustment", m_csmoothInput->value());
+ config->writeEntry("LookAheadAjustment", m_lookaheadInput->value());
+ config->writeEntry("GammaAjustment", m_gammaInput->value());
+ config->writeEntry("DampingAjustment", m_dampingInput->value());
+ config->writeEntry("PhaseAjustment", m_phaseInput->value());
+ m_previewWidget->writeSettings();
+ config->sync();
+}
+
+void NoiseReductionTool::slotResetSettings()
+{
+ m_radiusInput->setEnabled(true);
+ m_lumToleranceInput->setEnabled(true);
+ m_thresholdInput->setEnabled(true);
+ m_textureInput->setEnabled(true);
+ m_sharpnessInput->setEnabled(true);
+ m_csmoothInput->setEnabled(true);
+ m_lookaheadInput->setEnabled(true);
+ m_gammaInput->setEnabled(true);
+ m_dampingInput->setEnabled(true);
+ m_phaseInput->setEnabled(true);
+
+ m_radiusInput->slotReset();
+ m_lumToleranceInput->slotReset();
+ m_thresholdInput->slotReset();
+ m_textureInput->slotReset();
+ m_sharpnessInput->slotReset();
+ m_csmoothInput->slotReset();
+ m_lookaheadInput->slotReset();
+ m_gammaInput->slotReset();
+ m_dampingInput->slotReset();
+ m_phaseInput->slotReset();
+
+ m_radiusInput->setEnabled(false);
+ m_lumToleranceInput->setEnabled(false);
+ m_thresholdInput->setEnabled(false);
+ m_textureInput->setEnabled(false);
+ m_sharpnessInput->setEnabled(false);
+ m_csmoothInput->setEnabled(false);
+ m_lookaheadInput->setEnabled(false);
+ m_gammaInput->setEnabled(false);
+ m_dampingInput->setEnabled(false);
+ m_phaseInput->setEnabled(false);
+}
+
+void NoiseReductionTool::prepareEffect()
+{
+ m_radiusInput->setEnabled(false);
+ m_lumToleranceInput->setEnabled(false);
+ m_thresholdInput->setEnabled(false);
+ m_textureInput->setEnabled(false);
+ m_sharpnessInput->setEnabled(false);
+ m_csmoothInput->setEnabled(false);
+ m_lookaheadInput->setEnabled(false);
+ m_gammaInput->setEnabled(false);
+ m_dampingInput->setEnabled(false);
+ m_phaseInput->setEnabled(false);
+
+ double r = m_radiusInput->value();
+ double l = m_lumToleranceInput->value();
+ double th = m_thresholdInput->value();
+ double tx = m_textureInput->value();
+ double s = m_sharpnessInput->value();
+ double c = m_csmoothInput->value();
+ double a = m_lookaheadInput->value();
+ double g = m_gammaInput->value();
+ double d = m_dampingInput->value();
+ double p = m_phaseInput->value();
+
+ DImg image = m_previewWidget->getOriginalRegionImage();
+
+ setFilter(dynamic_cast<DImgThreadedFilter*>(new NoiseReduction(&image, this, r, l, th, tx, s, c, a, g, d, p)));
+}
+
+void NoiseReductionTool::prepareFinal()
+{
+ m_radiusInput->setEnabled(false);
+ m_lumToleranceInput->setEnabled(false);
+ m_thresholdInput->setEnabled(false);
+ m_textureInput->setEnabled(false);
+ m_sharpnessInput->setEnabled(false);
+ m_csmoothInput->setEnabled(false);
+ m_lookaheadInput->setEnabled(false);
+ m_gammaInput->setEnabled(false);
+ m_dampingInput->setEnabled(false);
+ m_phaseInput->setEnabled(false);
+
+ double r = m_radiusInput->value();
+ double l = m_lumToleranceInput->value();
+ double th = m_thresholdInput->value();
+ double tx = m_textureInput->value();
+ double s = m_sharpnessInput->value();
+ double c = m_csmoothInput->value();
+ double a = m_lookaheadInput->value();
+ double g = m_gammaInput->value();
+ double d = m_dampingInput->value();
+ double p = m_phaseInput->value();
+
+ ImageIface iface(0, 0);
+ setFilter(dynamic_cast<DImgThreadedFilter*>(new NoiseReduction(iface.getOriginalImg(), this, r, l, th, tx, s, c, a, g, d, p)));
+}
+
+void NoiseReductionTool::putPreviewData()
+{
+ m_previewWidget->setPreviewImage(filter()->getTargetImage());
+}
+
+void NoiseReductionTool::putFinalData()
+{
+ ImageIface iface(0, 0);
+ iface.putOriginalImage(i18n("Noise Reduction"), filter()->getTargetImage().bits());
+}
+
+void NoiseReductionTool::slotLoadSettings()
+{
+ KURL loadRestorationFile = KFileDialog::getOpenURL(TDEGlobalSettings::documentPath(),
+ TQString( "*" ), kapp->activeWindow(),
+ TQString( i18n("Photograph Noise Reduction Settings File to Load")) );
+ if ( loadRestorationFile.isEmpty() )
+ return;
+
+ TQFile file(loadRestorationFile.path());
+
+ if ( file.open(IO_ReadOnly) )
+ {
+ TQTextStream stream( &file );
+ if ( stream.readLine() != "# Photograph Noise Reduction Configuration File" )
+ {
+ KMessageBox::error(kapp->activeWindow(),
+ i18n("\"%1\" is not a Photograph Noise Reduction settings text file.")
+ .arg(loadRestorationFile.fileName()));
+ file.close();
+ return;
+ }
+
+ blockSignals(true);
+ m_radiusInput->setValue( stream.readLine().toDouble() );
+ m_lumToleranceInput->setValue( stream.readLine().toDouble() );
+ m_thresholdInput->setValue( stream.readLine().toDouble() );
+ m_textureInput->setValue( stream.readLine().toDouble() );
+ m_sharpnessInput->setValue( stream.readLine().toDouble() );
+ m_csmoothInput->setValue( stream.readLine().toDouble() );
+ m_lookaheadInput->setValue( stream.readLine().toDouble() );
+ m_gammaInput->setValue( stream.readLine().toDouble() );
+ m_dampingInput->setValue( stream.readLine().toDouble() );
+ m_phaseInput->setValue( stream.readLine().toDouble() );
+ blockSignals(false);
+ }
+ else
+ KMessageBox::error(kapp->activeWindow(), i18n("Cannot load settings from the Photograph Noise Reduction text file."));
+
+ file.close();
+}
+
+void NoiseReductionTool::slotSaveAsSettings()
+{
+ KURL saveRestorationFile = KFileDialog::getSaveURL(TDEGlobalSettings::documentPath(),
+ TQString( "*" ), kapp->activeWindow(),
+ TQString( i18n("Photograph Noise Reduction Settings File to Save")) );
+ if ( saveRestorationFile.isEmpty() )
+ return;
+
+ TQFile file(saveRestorationFile.path());
+
+ if ( file.open(IO_WriteOnly) )
+ {
+ TQTextStream stream( &file );
+ stream << "# Photograph Noise Reduction Configuration File\n";
+ stream << m_radiusInput->value() << "\n";
+ stream << m_lumToleranceInput->value() << "\n";
+ stream << m_thresholdInput->value() << "\n";
+ stream << m_textureInput->value() << "\n";
+ stream << m_sharpnessInput->value() << "\n";
+ stream << m_csmoothInput->value() << "\n";
+ stream << m_lookaheadInput->value() << "\n";
+ stream << m_gammaInput->value() << "\n";
+ stream << m_dampingInput->value() << "\n";
+ stream << m_phaseInput->value() << "\n";
+
+ }
+ else
+ KMessageBox::error(kapp->activeWindow(), i18n("Cannot save settings to the Photograph Noise Reduction text file."));
+
+ file.close();
+}
+
+} // NameSpace DigikamNoiseReductionImagesPlugin
diff --git a/src/imageplugins/noisereduction/noisereductiontool.h b/src/imageplugins/noisereduction/noisereductiontool.h
new file mode 100644
index 00000000..8d7d5828
--- /dev/null
+++ b/src/imageplugins/noisereduction/noisereductiontool.h
@@ -0,0 +1,92 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-08-24
+ * Description : a plugin to reduce CCD noise.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef NOISEREDUCTIONTOOL_H
+#define NOISEREDUCTIONTOOL_H
+
+// Local includes.
+
+#include "editortool.h"
+
+namespace KDcrawIface
+{
+class RDoubleNumInput;
+}
+
+namespace Digikam
+{
+class EditorToolSettings;
+class ImagePanelWidget;
+}
+
+namespace DigikamNoiseReductionImagesPlugin
+{
+
+class NoiseReductionTool : public Digikam::EditorToolThreaded
+{
+ TQ_OBJECT
+
+
+public:
+
+ NoiseReductionTool(TQObject* parent);
+ ~NoiseReductionTool();
+
+private:
+
+ void readSettings();
+ void writeSettings();
+ void prepareEffect();
+ void prepareFinal();
+ void putPreviewData();
+ void putFinalData();
+ void renderingFinished();
+
+private slots:
+
+ void slotSaveAsSettings();
+ void slotLoadSettings();
+ void slotResetSettings();
+
+private:
+
+ KDcrawIface::RDoubleNumInput *m_radiusInput;
+ KDcrawIface::RDoubleNumInput *m_lumToleranceInput;
+ KDcrawIface::RDoubleNumInput *m_thresholdInput;
+ KDcrawIface::RDoubleNumInput *m_textureInput;
+ KDcrawIface::RDoubleNumInput *m_sharpnessInput;
+
+ KDcrawIface::RDoubleNumInput *m_csmoothInput;
+ KDcrawIface::RDoubleNumInput *m_lookaheadInput;
+ KDcrawIface::RDoubleNumInput *m_gammaInput;
+ KDcrawIface::RDoubleNumInput *m_dampingInput;
+ KDcrawIface::RDoubleNumInput *m_phaseInput;
+
+ Digikam::ImagePanelWidget *m_previewWidget;
+
+ Digikam::EditorToolSettings *m_gboxSettings;
+};
+
+} // NameSpace DigikamNoiseReductionImagesPlugin
+
+#endif /* NOISEREDUCTIONTOOL_H */