summaryrefslogtreecommitdiffstats
path: root/src/imageplugins/hotpixels
diff options
context:
space:
mode:
Diffstat (limited to 'src/imageplugins/hotpixels')
-rw-r--r--src/imageplugins/hotpixels/Makefile.am36
-rw-r--r--src/imageplugins/hotpixels/TODO4
-rw-r--r--src/imageplugins/hotpixels/blackframelistview.cpp176
-rw-r--r--src/imageplugins/hotpixels/blackframelistview.h127
-rw-r--r--src/imageplugins/hotpixels/blackframeparser.cpp211
-rw-r--r--src/imageplugins/hotpixels/blackframeparser.h102
-rw-r--r--src/imageplugins/hotpixels/digikamimageplugin_hotpixels.desktop50
-rw-r--r--src/imageplugins/hotpixels/digikamimageplugin_hotpixels_ui.rc20
-rw-r--r--src/imageplugins/hotpixels/hotpixel.h74
-rw-r--r--src/imageplugins/hotpixels/hotpixelfixer.cpp302
-rw-r--r--src/imageplugins/hotpixels/hotpixelfixer.h98
-rw-r--r--src/imageplugins/hotpixels/hotpixelstool.cpp276
-rw-r--r--src/imageplugins/hotpixels/hotpixelstool.h113
-rw-r--r--src/imageplugins/hotpixels/imageeffect_hotpixels.cpp279
-rw-r--r--src/imageplugins/hotpixels/imageeffect_hotpixels.h104
-rw-r--r--src/imageplugins/hotpixels/imageplugin_hotpixels.cpp72
-rw-r--r--src/imageplugins/hotpixels/imageplugin_hotpixels.h56
-rw-r--r--src/imageplugins/hotpixels/weights.cpp283
-rw-r--r--src/imageplugins/hotpixels/weights.h90
19 files changed, 2473 insertions, 0 deletions
diff --git a/src/imageplugins/hotpixels/Makefile.am b/src/imageplugins/hotpixels/Makefile.am
new file mode 100644
index 00000000..711fe84e
--- /dev/null
+++ b/src/imageplugins/hotpixels/Makefile.am
@@ -0,0 +1,36 @@
+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/threadimageio \
+ -I$(top_srcdir)/src/libs/dmetadata \
+ -I$(top_srcdir)/src/libs/dimg/filters \
+ -I$(top_srcdir)/src/digikam \
+ $(LIBKDCRAW_CFLAGS) \
+ $(all_includes)
+
+digikamimageplugin_hotpixels_la_SOURCES = blackframeparser.cpp weights.cpp \
+ hotpixelfixer.cpp imageplugin_hotpixels.cpp \
+ blackframelistview.cpp hotpixelstool.cpp
+
+digikamimageplugin_hotpixels_la_LIBADD = $(LIB_TDEPARTS) \
+ $(top_builddir)/src/digikam/libdigikam.la
+
+digikamimageplugin_hotpixels_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) -ltdecore -ltdeui $(LIB_TQT) -ltdefx -lkdcraw -ltdeio
+
+kde_services_DATA = digikamimageplugin_hotpixels.desktop
+
+kde_module_LTLIBRARIES = digikamimageplugin_hotpixels.la
+
+rcdir = $(kde_datadir)/digikam
+rc_DATA = digikamimageplugin_hotpixels_ui.rc
+
diff --git a/src/imageplugins/hotpixels/TODO b/src/imageplugins/hotpixels/TODO
new file mode 100644
index 00000000..880e1a36
--- /dev/null
+++ b/src/imageplugins/hotpixels/TODO
@@ -0,0 +1,4 @@
+- Store black frames. Include the fullsize image to be able to reedit it if necessary.
+- Add a hand hot-pixel editor for the hot pixels on the black frame
+- Use the same hot-pixel editor from the image view, to edit a new black frame with the added data
+
diff --git a/src/imageplugins/hotpixels/blackframelistview.cpp b/src/imageplugins/hotpixels/blackframelistview.cpp
new file mode 100644
index 00000000..1202b094
--- /dev/null
+++ b/src/imageplugins/hotpixels/blackframelistview.cpp
@@ -0,0 +1,176 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-07-05
+ * Description : a ListView to display black frames
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2005-2006 by Unai Garro <ugarro at users dot sourceforge dot net>
+ *
+ * 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 THUMB_WIDTH 150
+
+// TQt includes.
+
+#include <tqpainter.h>
+#include <tqtooltip.h>
+
+// Local includes.
+
+#include "blackframelistview.h"
+#include "blackframelistview.moc"
+
+namespace DigikamHotPixelsImagesPlugin
+{
+
+BlackFrameListView::BlackFrameListView(TQWidget* parent)
+ : TQListView(parent)
+{
+ addColumn(i18n("Preview"));
+ addColumn(i18n("Size"));
+ addColumn(i18n("This is a column which will contain the amount of HotPixels "
+ "found in the black frame file", "HP"));
+ setAllColumnsShowFocus(true);
+ setResizeMode(TQListView::LastColumn);
+ setSelectionMode(TQListView::Single);
+}
+
+// --------------------------------------------------------------------------
+
+BlackFrameListViewItem::BlackFrameListViewItem(BlackFrameListView* parent, const KURL &url)
+ : TQObject(parent), TQListViewItem(parent)
+{
+ m_parent = parent;
+ m_blackFrameURL = url;
+ m_parser = new BlackFrameParser(parent);
+ m_parser->parseBlackFrame(url);
+
+ connect(m_parser, TQ_SIGNAL(parsed(TQValueList<HotPixel>)),
+ this, TQ_SLOT(slotParsed(TQValueList<HotPixel>)));
+
+ connect(this, TQ_SIGNAL(parsed(TQValueList<HotPixel>, const KURL&)),
+ parent, TQ_SLOT(slotParsed(TQValueList<HotPixel>, const KURL&)));
+
+ connect(m_parser, TQ_SIGNAL(signalLoadingProgress(float)),
+ this, TQ_SIGNAL(signalLoadingProgress(float)));
+
+ connect(m_parser, TQ_SIGNAL(signalLoadingComplete()),
+ this, TQ_SIGNAL(signalLoadingComplete()));
+}
+
+void BlackFrameListViewItem::activate()
+{
+ TQToolTip::add( m_parent, m_blackFrameDesc);
+ emit parsed(m_hotPixels, m_blackFrameURL);
+}
+
+TQString BlackFrameListViewItem::text(int column)const
+{
+ switch (column)
+ {
+ case 0:
+ {
+ // First column includes the pixmap
+ break;
+ }
+ case 1:
+ {
+ // The image size.
+ if (!m_imageSize.isEmpty())
+ return (TQString("%1x%2").arg(m_imageSize.width()).arg(m_imageSize.height()));
+ break;
+ }
+ case 2:
+ {
+ // The amount of hot pixels found in the black frame.
+ return (TQString::number(m_hotPixels.count()));
+ break;
+ }
+ }
+
+ return TQString();
+}
+
+void BlackFrameListViewItem::paintCell(TQPainter* p, const TQColorGroup& cg, int column, int width, int align)
+{
+ //Let the normal listview item draw it all for now
+ TQListViewItem::paintCell(p, cg, column, width, align);
+}
+
+void BlackFrameListViewItem::slotParsed(TQValueList<HotPixel> hotPixels)
+{
+ m_hotPixels = hotPixels;
+ m_image = m_parser->image();
+ m_imageSize = m_image.size();
+ m_thumb = thumb(TQSize(THUMB_WIDTH, THUMB_WIDTH/3*2));
+ setPixmap(0, m_thumb);
+
+ m_blackFrameDesc = TQString("<p><b>" + m_blackFrameURL.fileName() + "</b>:<p>");
+ TQValueList <HotPixel>::Iterator end(m_hotPixels.end());
+ for (TQValueList <HotPixel>::Iterator it = m_hotPixels.begin() ; it != end ; ++it)
+ m_blackFrameDesc.append( TQString("[%1,%2] ").arg((*it).x()).arg((*it).y()) );
+
+ emit parsed(m_hotPixels, m_blackFrameURL);
+}
+
+TQPixmap BlackFrameListViewItem::thumb(const TQSize& size)
+{
+ TQPixmap thumb;
+
+ //First scale it down to the size
+ thumb = m_image.smoothScale(size, TQImage::ScaleMin);
+
+ //And draw the hot pixel positions on the thumb
+ TQPainter p(&thumb);
+
+ //Take scaling into account
+ float xRatio, yRatio;
+ float hpThumbX, hpThumbY;
+ TQRect hpRect;
+
+ xRatio = (float)size.width()/(float)m_image.width();
+ yRatio = (float)size.height()/(float)m_image.height();
+
+ //Draw hot pixels one by one
+ TQValueList <HotPixel>::Iterator it;
+ TQValueList <HotPixel>::Iterator end(m_hotPixels.end());
+ for (it=m_hotPixels.begin() ; it!=end ; ++it)
+ {
+ hpRect = (*it).rect;
+ hpThumbX = (hpRect.x()+hpRect.width()/2)*xRatio;
+ hpThumbY = (hpRect.y()+hpRect.height()/2)*yRatio;
+
+ p.setPen(TQPen(TQt::black));
+ p.drawLine((int)hpThumbX, (int)hpThumbY-1, (int)hpThumbX, (int)hpThumbY+1);
+ p.drawLine((int)hpThumbX-1, (int)hpThumbY, (int)hpThumbX+1, (int)hpThumbY);
+ p.setPen(TQPen(TQt::white));
+ p.drawPoint((int)hpThumbX-1, (int)hpThumbY-1);
+ p.drawPoint((int)hpThumbX+1, (int)hpThumbY+1);
+ p.drawPoint((int)hpThumbX-1, (int)hpThumbY+1);
+ p.drawPoint((int)hpThumbX+1, (int)hpThumbY-1);
+ }
+
+ return thumb;
+}
+
+int BlackFrameListViewItem::width(const TQFontMetrics& fm,const TQListView* lv,int c)const
+{
+ if (c==0) return THUMB_WIDTH;
+ else return TQListViewItem::width(fm,lv,c);
+}
+
+} // NameSpace DigikamHotPixelsImagesPlugin
diff --git a/src/imageplugins/hotpixels/blackframelistview.h b/src/imageplugins/hotpixels/blackframelistview.h
new file mode 100644
index 00000000..977d226d
--- /dev/null
+++ b/src/imageplugins/hotpixels/blackframelistview.h
@@ -0,0 +1,127 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-07-05
+ * Description : a ListView to display black frames
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2005-2006 by Unai Garro <ugarro at users dot sourceforge dot net>
+ *
+ * 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 BLACKFRAMELISTVIEW_H
+#define BLACKFRAMELISTVIEW_H
+
+// TQt includes.
+
+#include <tqimage.h>
+#include <tqstring.h>
+#include <tqsize.h>
+#include <tqpoint.h>
+#include <tqvaluelist.h>
+#include <tqlistview.h>
+
+// KDE includes.
+
+#include <kurl.h>
+#include <tdelocale.h>
+
+// Local includes.
+
+#include "blackframeparser.h"
+#include "hotpixel.h"
+
+namespace DigikamHotPixelsImagesPlugin
+{
+
+class BlackFrameListView : public TQListView
+{
+ TQ_OBJECT
+
+
+public:
+
+ BlackFrameListView(TQWidget* parent=0);
+ ~BlackFrameListView(){};
+
+signals:
+
+ void blackFrameSelected(TQValueList<HotPixel>, const KURL&);
+
+private slots:
+
+ void slotParsed(TQValueList<HotPixel> hotPixels, const KURL& blackFrameURL)
+ {
+ emit blackFrameSelected(hotPixels, blackFrameURL);
+ };
+};
+
+// --------------------------------------------------------------------------
+
+class BlackFrameListViewItem : public TQObject, TQListViewItem
+{
+TQ_OBJECT
+
+
+public:
+
+ BlackFrameListViewItem(BlackFrameListView* parent, const KURL &url);
+ ~BlackFrameListViewItem(){};
+
+ virtual TQString text(int column)const;
+ virtual void paintCell(TQPainter* p, const TQColorGroup& cg, int column, int width, int align);
+ virtual int width(const TQFontMetrics& fm, const TQListView* lv, int c)const;
+
+signals:
+
+ void parsed(TQValueList<HotPixel>, const KURL&);
+ void signalLoadingProgress(float);
+ void signalLoadingComplete();
+
+protected:
+
+ void activate();
+
+private:
+
+ TQPixmap thumb(const TQSize& size);
+
+private slots:
+
+ void slotParsed(TQValueList<HotPixel>);
+
+private:
+
+ // Data contained within each listview item
+ TQImage m_thumb;
+ TQImage m_image;
+
+ TQSize m_imageSize;
+
+ TQValueList <HotPixel> m_hotPixels;
+
+ TQString m_blackFrameDesc;
+
+ KURL m_blackFrameURL;
+
+ BlackFrameParser *m_parser;
+
+ BlackFrameListView *m_parent;
+};
+
+} // NameSpace DigikamHotPixelsImagesPlugin
+
+#endif // BLACKFRAMELISTVIEW_H
diff --git a/src/imageplugins/hotpixels/blackframeparser.cpp b/src/imageplugins/hotpixels/blackframeparser.cpp
new file mode 100644
index 00000000..7306f4e6
--- /dev/null
+++ b/src/imageplugins/hotpixels/blackframeparser.cpp
@@ -0,0 +1,211 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-27
+ * Description : black frames parser
+ *
+ * Copyright (C) 2005-2006 by Unai Garro <ugarro at users dot sourceforge dot net>
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * Part of the algorithm for finding the hot pixels was based on
+ * the code of jpegpixi, which was released under the GPL license,
+ * and is Copyright (C) 2003, 2004 Martin Dickopp
+ *
+ * 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.
+ *
+ * ============================================================ */
+
+// Denominator for relative quantities.
+#define DENOM (DENOM_STQRT * DENOM_STQRT)
+
+// Square root of denominator for relative quantities.
+#define DENOM_STQRT 10000
+
+// Convert relative to absolute numbers. Care must be taken not to overflow integers.
+#define REL_TO_ABS(n,m) \
+ ((((n) / DENOM_STQRT) * (m) + ((n) % DENOM_STQRT) * (m) / DENOM_STQRT) / DENOM_STQRT)
+
+// TQt includes.
+
+#include <tqimage.h>
+#include <tqstringlist.h>
+
+// KDE includes.
+
+#include <tdeapplication.h>
+#include <tdeversion.h>
+#include <tdeio/netaccess.h>
+#include <tdeio/job.h>
+
+// Local includes.
+
+#include "blackframeparser.h"
+#include "blackframeparser.moc"
+
+namespace DigikamHotPixelsImagesPlugin
+{
+
+BlackFrameParser::BlackFrameParser(TQObject *parent)
+ : TQObject(parent)
+{
+ m_imageLoaderThread = 0;
+}
+
+BlackFrameParser::~BlackFrameParser()
+{
+ delete m_imageLoaderThread;
+}
+
+void BlackFrameParser::parseHotPixels(const TQString &file)
+{
+ parseBlackFrame(KURL(file));
+}
+
+void BlackFrameParser::parseBlackFrame(const KURL &url)
+{
+#if KDE_IS_VERSION(3,2,0)
+ TDEIO::NetAccess::download(url, m_localFile, kapp->activeWindow());
+#else
+ TDEIO::NetAccess::download(url, m_localFile);
+#endif
+
+ if (!m_imageLoaderThread)
+ {
+ m_imageLoaderThread = new LoadSaveThread();
+
+ connect(m_imageLoaderThread, TQ_SIGNAL(signalLoadingProgress(const LoadingDescription&, float)),
+ this, TQ_SLOT(slotLoadingProgress(const LoadingDescription&, float)));
+
+ connect(m_imageLoaderThread, TQ_SIGNAL(signalImageLoaded(const LoadingDescription&, const DImg&)),
+ this, TQ_SLOT(slotLoadImageFromUrlComplete(const LoadingDescription&, const DImg&)));
+ }
+
+ LoadingDescription desc = LoadingDescription(m_localFile, DRawDecoding());
+ m_imageLoaderThread->load(desc);
+}
+
+void BlackFrameParser::slotLoadingProgress(const LoadingDescription&, float v)
+{
+ emit signalLoadingProgress(v);
+}
+
+void BlackFrameParser::slotLoadImageFromUrlComplete(const LoadingDescription&, const DImg& img)
+{
+ DImg image(img);
+ m_Image = image.copyTQImage();
+ blackFrameParsing();
+ emit signalLoadingComplete();
+}
+
+void BlackFrameParser::parseBlackFrame(TQImage& img)
+{
+ m_Image = img;
+ blackFrameParsing();
+}
+
+// Parses black frames
+
+void BlackFrameParser::blackFrameParsing()
+{
+ // Now find the hot pixels and store them in a list
+ TQValueList<HotPixel> hpList;
+
+ for (int y=0 ; y < m_Image.height() ; ++y)
+ {
+ for (int x=0 ; x < m_Image.width() ; ++x)
+ {
+ //Get each point in the image
+ TQRgb pixrgb = m_Image.pixel(x,y);
+ TQColor color; color.setRgb(pixrgb);
+
+ // Find maximum component value.
+ int maxValue;
+ int threshold = DENOM/10;
+ const int threshold_value = REL_TO_ABS(threshold, 255);
+ maxValue = (color.red()>color.blue()) ? color.red() : color.blue();
+ if (color.green() > maxValue) maxValue = color.green();
+
+ // If the component is bigger than the threshold, add the point
+ if (maxValue > threshold_value)
+ {
+ HotPixel point;
+ point.rect = TQRect (x, y, 1, 1);
+ //TODO:check this
+ point.luminosity = ((2 * DENOM) / 255 ) * maxValue / 2;
+
+ hpList.append(point);
+ }
+ }
+ }
+
+ //Now join points together into groups
+ consolidatePixels (hpList);
+
+ //And notify
+ emit parsed(hpList);
+}
+
+// Consolidate adjacent points into larger points.
+
+void BlackFrameParser::consolidatePixels (TQValueList<HotPixel>& list)
+{
+ if (list.isEmpty())
+ return;
+
+ /* Consolidate horizontally. */
+
+ TQValueList<HotPixel>::iterator it, prevPointIt;
+
+ prevPointIt = list.begin();
+ it = list.begin();
+ ++it;
+
+ HotPixel tmp;
+ HotPixel point;
+ HotPixel point_below;
+ TQValueList<HotPixel>::iterator end(list.end());
+ for (; it != end; ++it )
+ {
+ while (1)
+ {
+ point = (*it);
+ tmp = point;
+
+ TQValueList<HotPixel>::Iterator point_below_it;
+ point_below_it = list.find (tmp); //find any intersecting hotp below tmp
+ if (point_below_it != list.end())
+ {
+ point_below =* point_below_it;
+ validateAndConsolidate (&point, &point_below);
+
+ point.rect.setX(MIN(point.x(), point_below.x()));
+ point.rect.setWidth(MAX(point.x() + point.width(),
+ point_below.x() + point_below.width()) - point.x());
+ point.rect.setHeight(MAX(point.y() + point.height(),
+ point_below.y() + point_below.height()) - point.y());
+ *it = point;
+ list.remove (point_below_it); //TODO: Check! this could remove it++?
+ }
+ else
+ break;
+ }
+ }
+}
+
+void BlackFrameParser::validateAndConsolidate (HotPixel *a, HotPixel *b)
+{
+ a->luminosity = MAX (a->luminosity, b->luminosity);
+}
+
+} // NameSpace DigikamHotPixelsImagesPlugin
diff --git a/src/imageplugins/hotpixels/blackframeparser.h b/src/imageplugins/hotpixels/blackframeparser.h
new file mode 100644
index 00000000..f13ebdc4
--- /dev/null
+++ b/src/imageplugins/hotpixels/blackframeparser.h
@@ -0,0 +1,102 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-27
+ * Description : black frames parser
+ *
+ * Copyright (C) 2005-2006 by Unai Garro <ugarro at users dot sourceforge dot net>
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * Part of the algorithm for finding the hot pixels was based on
+ * the code of jpegpixi, which was released under the GPL license,
+ * and is Copyright (C) 2003, 2004 Martin Dickopp
+ *
+ * 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 BLACKFRAMEPARSER_H
+#define BLACKFRAMEPARSER_H
+
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+
+// TQt includes.
+
+#include <tqimage.h>
+#include <tqobject.h>
+#include <tqvaluelist.h>
+#include <tqstring.h>
+#include <tqrect.h>
+
+// KDE includes.
+
+#include <kurl.h>
+
+// Local includes.
+
+#include "dimg.h"
+#include "loadsavethread.h"
+#include "hotpixel.h"
+
+using namespace Digikam;
+
+namespace DigikamHotPixelsImagesPlugin
+{
+
+class BlackFrameParser: public TQObject
+{
+ TQ_OBJECT
+
+
+public:
+
+ BlackFrameParser(TQObject *parent);
+ ~BlackFrameParser();
+
+ void parseHotPixels(const TQString &file);
+ void parseBlackFrame(const KURL &url);
+ void parseBlackFrame(TQImage& img);
+ TQImage image(){return m_Image;}
+
+signals:
+
+ void parsed(TQValueList<HotPixel>);
+ void signalLoadingProgress(float);
+ void signalLoadingComplete();
+
+private slots:
+
+ void slotLoadingProgress(const LoadingDescription&, float);
+ void slotLoadImageFromUrlComplete(const LoadingDescription&, const DImg&);
+
+private:
+
+ void blackFrameParsing();
+ void consolidatePixels(TQValueList<HotPixel>& list);
+ void validateAndConsolidate(HotPixel *a, HotPixel *b);
+
+private:
+
+ TQString m_OutputString;
+ TQString m_localFile;
+
+ TQImage m_Image;
+
+ LoadSaveThread *m_imageLoaderThread;
+};
+
+} // NameSpace DigikamHotPixelsImagesPlugin
+
+#endif // BLACKFRAMEPARSER_H
diff --git a/src/imageplugins/hotpixels/digikamimageplugin_hotpixels.desktop b/src/imageplugins/hotpixels/digikamimageplugin_hotpixels.desktop
new file mode 100644
index 00000000..5b12fe2c
--- /dev/null
+++ b/src/imageplugins/hotpixels/digikamimageplugin_hotpixels.desktop
@@ -0,0 +1,50 @@
+[Desktop Entry]
+Name=ImagePlugin_HotPixels
+Name[bg]=Приставка за снимки - Горещи пиксели
+Name[el]=ΠρόσθετοΕικόνας_ΈντοναΕικονοστοιχεία
+Name[fi]=KuumatPikselit
+Name[hr]=Vrući pikseli
+Name[it]=PluginImmagini_PixelBruciati
+Name[ms]=ImagePlugin_PikselPanas
+Name[nl]=Afbeeldingsplugin_HotPixels
+Name[sr]=Врући пиксели
+Name[sr@Latn]=Vrući pikseli
+Name[sv]=Insticksprogram för heta bildpunkter
+Name[tr]=ResimEklentisi_Çekirdek
+Name[xx]=xxImagePlugin_HotPixelsxx
+Type=Service
+X-TDE-ServiceTypes=Digikam/ImagePlugin
+Encoding=UTF-8
+Comment=Hot pixel correction plugin for digiKam
+Comment[ca]=Connector per al digiKam de correcció de píxels cremats
+Comment[da]=Hot pixel rettelsesplugin for Digikam
+Comment[de]=digiKam-Modul zur Korrektur von heißen (defekten) Pixeln
+Comment[el]=Πρόσθετο διόρθωσης έντονων εικονοστοιχείων για το digiKam
+Comment[es]=Plugin para digiKampara corregir los píxeles quemados de la imagen
+Comment[et]=DigiKami kuumade pikslite korrigeerimise plugin
+Comment[fa]=وصلۀ اصلاح تصویردانۀ Hot برای digiKam
+Comment[fi]=Digitaalisen rakeisuushäiriön korjaus
+Comment[gl]=Un plugin de digiKam para corrixir os pixels queimados da imaxe
+Comment[hr]=digiKam dodatak za ispravljanje vrućih piksela
+Comment[is]=Íforrit fyrir digiKam sem fjarlægir skemmda díla (hot pixels)
+Comment[it]=Plugin di correzione dei pixel bruciati per digiKam
+Comment[ja]=digiKam ホットピクセル除去プラグイン
+Comment[ms]=Plugin pembetulan piksel panas untuk digiKam
+Comment[nds]=digiKam-Moduul för't Richten vun hitte Pixels
+Comment[nl]=Digikam-plugin voor het corrigeren van de hotpixels
+Comment[pa]=ਡਿਜ਼ੀਕੈਮ ਲਈ ਹਾਟ ਪਿਕਸਲ ਸੋਧ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka do programu digiKam usuwająca "gorące piksele"
+Comment[pt]=Um 'plugin' do digiKam para corrigir os pixels queimados da imagem
+Comment[pt_BR]=Plugin de Correção de hot pixel para o digiKam
+Comment[ru]=Модуль коррекции ярких пикселей для digiKam
+Comment[sk]=digiKam plugin pre korekciu vypálených pixelov
+Comment[sr]=digiKam-ов прикључак исправку врућих пиксела
+Comment[sr@Latn]=digiKam-ov priključak ispravku vrućih piksela
+Comment[sv]=Digikam insticksprogram för korrigering av heta bildpunkter
+Comment[tr]=digiKam için beyaz dengesini düzeltme eklentisi
+Comment[uk]=Втулок виправлення гарячих пікселів для Digikam
+Comment[vi]=Phần bổ sung sửa điểm ảnh nóng cho digiKam
+Comment[xx]=xxHot pixel correction plugin for digiKamxx
+
+X-TDE-Library=digikamimageplugin_hotpixels
+author=Unai Garro, ugarro at sourceforge dot net
diff --git a/src/imageplugins/hotpixels/digikamimageplugin_hotpixels_ui.rc b/src/imageplugins/hotpixels/digikamimageplugin_hotpixels_ui.rc
new file mode 100644
index 00000000..b80d7f5a
--- /dev/null
+++ b/src/imageplugins/hotpixels/digikamimageplugin_hotpixels_ui.rc
@@ -0,0 +1,20 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui version="4" name="digikamimageplugin_hotpixels" >
+
+ <MenuBar>
+
+ <Menu name="Enhance" ><text>Enh&amp;ance</text>
+ <Action name="imageplugin_hotpixels" />
+ </Menu>
+
+ </MenuBar>
+
+ <ToolBar name="ToolBar" >
+ <text>Main Toolbar</text>
+ </ToolBar>
+
+ <ActionProperties>
+ <Action shortcut="" name="imageplugin_hotpixels" />
+ </ActionProperties>
+
+</kpartgui>
diff --git a/src/imageplugins/hotpixels/hotpixel.h b/src/imageplugins/hotpixels/hotpixel.h
new file mode 100644
index 00000000..bceb539f
--- /dev/null
+++ b/src/imageplugins/hotpixels/hotpixel.h
@@ -0,0 +1,74 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-27
+ * Description : Threaded image filter to fix hot pixels
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2005-2006 by Unai Garro <ugarro at users dot sourceforge dot net>
+ *
+ * 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 HOTPIXEL_H
+#define HOTPIXEL_H
+
+// TQt includes.
+
+#include <tqrect.h>
+
+namespace DigikamHotPixelsImagesPlugin
+{
+
+class HotPixel
+{
+
+public:
+
+ TQRect rect;
+ int luminosity;
+ int y() const {return rect.y(); };
+ int x() const {return rect.x(); };
+ int width()const {return rect.width(); };
+ int height()const {return rect.height();};
+
+ bool operator==(const HotPixel p) const
+ {
+ //we can say they're same hotpixel spot if they
+ //touch(next to) each other horizontally or vertically, not diagonal corners
+ //return (rect.intersects(p.rect));
+ return (rect != p.rect) && (x() + width() >= p.x() && x() <= p.x() + p.width()
+ && y() + height() >= p.y() && y() <= p.y() + p.height())
+ && !diagonal(rect, p.rect);
+ }
+
+private:
+
+ bool diagonal(TQRect r1,TQRect r2) const
+ {
+ //locate next-to positions
+
+ bool top = r1.y() + height()-1 == r2.y()-1; //r1 is on the top of r2
+ bool left = r1.x() + width()-1 == r2.x()-1; //r1 is on the left of r2
+ bool right = r1.x() == r2.x() + r2.width();
+ bool bottom = r1.y() == r2.y() + r2.height();
+
+ return ((top && left) || (top && right) || (bottom && left) || (bottom && right));
+ }
+};
+
+} // NameSpace DigikamHotPixelsImagesPlugin
+
+#endif // HOTPIXEL_H
diff --git a/src/imageplugins/hotpixels/hotpixelfixer.cpp b/src/imageplugins/hotpixels/hotpixelfixer.cpp
new file mode 100644
index 00000000..d29b8525
--- /dev/null
+++ b/src/imageplugins/hotpixels/hotpixelfixer.cpp
@@ -0,0 +1,302 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-27
+ * Description : Threaded image filter to fix hot pixels
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2005-2006 by Unai Garro <ugarro at users dot sourceforge dot net>
+ *
+ * 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.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cmath>
+#include <cstdlib>
+
+// TQt includes.
+
+#include <tqcolor.h>
+#include <tqregexp.h>
+#include <tqstringlist.h>
+
+// Local includes.
+
+#include "dimg.h"
+#include "ddebug.h"
+#include "hotpixelfixer.h"
+
+#ifdef HAVE_FLOAT_H
+#if HAVE_FLOAT_H
+# include <float.h>
+#endif
+#endif
+
+#ifndef DBL_MIN
+# define DBL_MIN 1e-37
+#endif
+#ifndef DBL_MAX
+# define DBL_MAX 1e37
+#endif
+
+namespace DigikamHotPixelsImagesPlugin
+{
+
+HotPixelFixer::HotPixelFixer(Digikam::DImg *orgImage, TQObject *parent, const TQValueList<HotPixel>& hpList,
+ int interpolationMethod)
+ : Digikam::DImgThreadedFilter(orgImage, parent, "HotPixels")
+{
+ m_hpList = hpList;
+ m_interpolationMethod = interpolationMethod;
+ mWeightList.clear();
+
+ initFilter();
+}
+
+HotPixelFixer::~HotPixelFixer()
+{
+}
+
+void HotPixelFixer::filterImage(void)
+{
+ TQValueList <HotPixel>::ConstIterator it;
+ TQValueList <HotPixel>::ConstIterator end(m_hpList.end());
+ for (it = m_hpList.begin() ; it != end ; ++it)
+ {
+ HotPixel hp = *it;
+ interpolate(m_orgImage, hp, m_interpolationMethod);
+ }
+
+ m_destImage = m_orgImage;
+}
+
+// Interpolates a pixel block
+void HotPixelFixer::interpolate (Digikam::DImg &img, HotPixel &hp, int method)
+{
+ const int xPos = hp.x();
+ const int yPos = hp.y();
+ bool sixtBits = img.sixteenBit();
+
+ // Interpolate pixel.
+ switch (method)
+ {
+ case AVERAGE_INTERPOLATION:
+ {
+ // We implement the bidimendional one first.
+ // TODO: implement the rest of directions (V & H) here
+
+ //case twodim:
+ // {
+ int sum_weight = 0;
+ double vr=0.0,vg=0.0,vb=0.0;
+ int x, y;
+ Digikam::DColor col;
+
+ for (x = xPos; x < xPos+hp.width(); ++x)
+ {
+ if (validPoint(img,TQPoint(x,yPos-1)))
+ {
+ col=img.getPixelColor(x,yPos-1);
+ vr += col.red();
+ vg += col.green();
+ vb += col.blue();
+ ++sum_weight;
+ }
+ if (validPoint(img,TQPoint(x,yPos+hp.height())))
+ {
+ col=img.getPixelColor(x,yPos+hp.height());
+ vr += col.red();
+ vg += col.green();
+ vb += col.blue();
+ ++sum_weight;
+ }
+ }
+
+ for (y = yPos; y < hp.height(); ++y)
+ {
+ if (validPoint(img,TQPoint(xPos-1,y)))
+ {
+ col=img.getPixelColor(xPos,y);
+ vr += col.red();
+ vg += col.green();
+ vb += col.blue();
+ ++sum_weight;
+ }
+ if (validPoint(img,TQPoint(xPos+hp.width(),y)))
+ {
+ col=img.getPixelColor(xPos+hp.width(),y);
+ vr += col.red();
+ vg += col.green();
+ vb += col.blue();
+ ++sum_weight;
+ }
+ }
+
+ if (sum_weight > 0)
+ {
+ vr /= (double)sum_weight;
+ vg /= (double)sum_weight;
+ vb /= (double)sum_weight;
+
+
+ for (x = 0; x < hp.width(); ++x)
+ for (y = 0; y < hp.height(); ++y)
+ if (validPoint(img,TQPoint(xPos+x,yPos+y)))
+ {
+ int alpha=sixtBits ? 65535 : 255;
+ int ir=(int )round(vr),ig=(int) round(vg),ib=(int) round(vb);
+ img.setPixelColor(xPos+x,yPos+y,Digikam::DColor(ir,ig,ib,alpha,sixtBits));
+ }
+ }
+ break;
+ } //Case average
+
+ case LINEAR_INTERPOLATION:
+ //(Bi)linear interpolation.
+ weightPixels (img,hp,LINEAR_INTERPOLATION,TWODIM_DIRECTION,sixtBits ? 65535: 255);
+ break;
+
+ case QUADRATIC_INTERPOLATION:
+ // (Bi)quadratic interpolation.
+ weightPixels (img,hp,QUADRATIC_INTERPOLATION,TWODIM_DIRECTION,sixtBits ? 65535 : 255);
+ break;
+
+ case CUBIC_INTERPOLATION:
+ // (Bi)cubic interpolation.
+ weightPixels (img,hp,CUBIC_INTERPOLATION,TWODIM_DIRECTION,sixtBits ? 65535 : 255);
+ break;
+ } //switch
+}
+
+void HotPixelFixer::weightPixels (Digikam::DImg &img, HotPixel &px, int method, Direction dir,int maxComponent)
+{
+ //TODO: implement direction here too
+
+ for (int iComp = 0; iComp < 3; ++iComp)
+ {
+ // Obtain weight data block.
+
+ Weights w;
+ int polynomeOrder=-1;
+
+ switch (method)
+ {
+ case AVERAGE_INTERPOLATION: // Gilles: to prevent warnings from compiler.
+ break;
+ case LINEAR_INTERPOLATION:
+ polynomeOrder=1;
+ break;
+ case QUADRATIC_INTERPOLATION:
+ polynomeOrder=2;
+ break;
+ case CUBIC_INTERPOLATION:
+ polynomeOrder=3;
+ break;
+ }
+ if (polynomeOrder<0) return;
+
+ // In the one-dimensional case, the width must be 1,
+ // and the size must be stored in height
+
+ w.setWidth(dir == TWODIM_DIRECTION ? px.width() : 1);
+ w.setHeight(dir == HORIZONTAL_DIRECTION ? px.width() : px.height());
+ w.setPolynomeOrder(polynomeOrder);
+ w.setTwoDim(dir == TWODIM_DIRECTION);
+
+ //TODO: check this, it must not recalculate existing calculated weights
+ //for now I don't think it is finding the duplicates fine, so it uses
+ //the previous one always...
+
+ //if (mWeightList.find(w)==mWeightList.end())
+ //{
+ w.calculateWeights();
+
+ // mWeightList.append(w);
+
+ //}
+
+ // Calculate weighted pixel sum.
+ for (int y = 0; y<px.height(); ++y)
+ {
+ for (int x = 0; x < px.width(); ++x)
+ {
+ if (validPoint (img,TQPoint(px.x()+x,px.y()+y)))
+ {
+ double sum_weight = 0.0, v = 0.0;
+ size_t i;
+
+ for (i = 0; i < w.positions().count(); ++i)
+ {
+ // In the one-dimensional case, only the y coordinate is used.
+ const int xx = px.x()+(dir == VERTICAL_DIRECTION ? x :
+ dir== HORIZONTAL_DIRECTION ? w.positions()[i].y() : w.positions()[i].x());
+ const int yy = px.y()+(dir == HORIZONTAL_DIRECTION ? y :
+ w.positions()[i].y());
+
+ if (validPoint (img,TQPoint(xx, yy)))
+ {
+ //TODO: check this. I think it is broken
+ double weight;
+ if (dir==VERTICAL_DIRECTION)
+ {
+ weight = w[i][y][0];
+ }
+ else if (dir==HORIZONTAL_DIRECTION)
+ {
+ weight=w[i][0][x];
+ }
+ else
+ {
+ weight=w[i][y][x];
+ }
+
+ if (iComp==0) v += weight * img.getPixelColor(xx, yy).red();
+ else if (iComp==1) v += weight * img.getPixelColor(xx, yy).green();
+ else v += weight * img.getPixelColor(xx, yy).blue();
+
+ sum_weight += weight;
+ }
+ }
+
+ Digikam::DColor color=img.getPixelColor(px.x()+x,px.y()+y);
+ int component;
+ if (fabs (v) <= DBL_MIN)
+ component=0;
+ else if (sum_weight >= DBL_MIN)
+ {
+ component=(int) (v/sum_weight);
+ //Clamp value
+ if (component<0) component=0;
+ if (component>maxComponent) component=maxComponent;
+ }
+ else if (v >= 0.0)
+ component=maxComponent;
+ else
+ component=0;
+
+ if (iComp==0) color.setRed(component);
+ else if (iComp==1) color.setGreen(component);
+ else color.setBlue(component);
+
+
+ img.setPixelColor(px.x()+x,px.y()+y,color);
+ }
+ }
+ }
+ }
+}
+
+} // NameSpace DigikamHotPixelsImagesPlugin
diff --git a/src/imageplugins/hotpixels/hotpixelfixer.h b/src/imageplugins/hotpixels/hotpixelfixer.h
new file mode 100644
index 00000000..2bf8131c
--- /dev/null
+++ b/src/imageplugins/hotpixels/hotpixelfixer.h
@@ -0,0 +1,98 @@
+/* ============================================================
+ * Authors: Unai Garro <ugarro at users dot sourceforge dot net>
+ * Gilles Caulier <caulier dot gilles at free dot fr>
+ * Date : 2005-03-27
+ * Description : Threaded image filter to fix hot pixels
+ *
+ * Copyright 2005-2007 by Unai Garro and Gilles Caulier
+ *
+ * The algorithm for fixing the hot pixels was based on
+ * the code of jpegpixi, which was released under the GPL license,
+ * and is Copyright (C) 2003, 2004 Martin Dickopp
+ *
+ * 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 HOTPIXELFIXER_H
+#define HOTPIXELFIXER_H
+
+// TQt includes.
+
+#include <tqimage.h>
+#include <tqobject.h>
+#include <tqvaluelist.h>
+#include <tqrect.h>
+#include <tqstring.h>
+
+// Digikam includes.
+
+#include "dimgthreadedfilter.h"
+
+// Local includes.
+
+#include "hotpixel.h"
+#include "weights.h"
+
+namespace DigikamHotPixelsImagesPlugin
+{
+
+class HotPixelFixer : public Digikam::DImgThreadedFilter
+{
+
+public:
+
+ enum InterpolationMethod
+ {
+ AVERAGE_INTERPOLATION = 0,
+ LINEAR_INTERPOLATION = 1,
+ QUADRATIC_INTERPOLATION = 2,
+ CUBIC_INTERPOLATION = 3
+ };
+
+ enum Direction
+ {
+ TWODIM_DIRECTION = 0,
+ VERTICAL_DIRECTION = 1,
+ HORIZONTAL_DIRECTION = 2
+ };
+
+public:
+
+ HotPixelFixer(Digikam::DImg *orgImage, TQObject *parent,
+ const TQValueList<HotPixel>& hpList, int interpolationMethod);
+ ~HotPixelFixer();
+
+private:
+
+ virtual void filterImage(void);
+
+ void interpolate (Digikam::DImg &img,HotPixel &hp, int method);
+ void weightPixels (Digikam::DImg &img, HotPixel &px, int method, Direction dir, int maxComponent);
+
+ inline bool validPoint(Digikam::DImg &img, TQPoint p)
+ {
+ return (p.x()>=0 && p.y()>=0 && p.x()<(long) img.width() && p.y()<(long) img.height());
+ };
+
+ TQValueList <Weights> mWeightList;
+
+private:
+
+ int m_interpolationMethod;
+
+ TQValueList<HotPixel> m_hpList;
+};
+
+} // NameSpace DigikamHotPixelsImagesPlugin
+
+#endif // HOTPIXELFIXER_H
diff --git a/src/imageplugins/hotpixels/hotpixelstool.cpp b/src/imageplugins/hotpixels/hotpixelstool.cpp
new file mode 100644
index 00000000..fbcc6c9f
--- /dev/null
+++ b/src/imageplugins/hotpixels/hotpixelstool.cpp
@@ -0,0 +1,276 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-27
+ * Description : a digiKam image plugin for fixing dots produced by
+ * hot/stuck/dead pixels from a CCD.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2005-2006 by Unai Garro <ugarro at users dot sourceforge dot net>
+ *
+ * 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 <tqcombobox.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqwhatsthis.h>
+#include <tqpushbutton.h>
+#include <tqpointarray.h>
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <tdeconfig.h>
+#include <kimageio.h>
+#include <tdeaboutdata.h>
+#include <tdeapplication.h>
+#include <kstandarddirs.h>
+#include <tdefiledialog.h>
+#include <kprogress.h>
+#include <kiconloader.h>
+#include <kpushbutton.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/rcombobox.h>
+
+// Local includes.
+
+#include "daboutdata.h"
+#include "ddebug.h"
+#include "dimg.h"
+#include "imageiface.h"
+#include "imagepanelwidget.h"
+#include "editortooliface.h"
+#include "editortoolsettings.h"
+#include "imagedialog.h"
+#include "blackframelistview.h"
+#include "hotpixelstool.h"
+#include "hotpixelstool.moc"
+
+using namespace KDcrawIface;
+using namespace Digikam;
+
+namespace DigikamHotPixelsImagesPlugin
+{
+
+HotPixelsTool::HotPixelsTool(TQObject* parent)
+ : EditorToolThreaded(parent)
+{
+ setName("hotpixels");
+ setToolName(i18n("Hot Pixels"));
+ setToolIcon(SmallIcon("hotpixels"));
+
+ // -------------------------------------------------------------
+
+ m_gboxSettings = new EditorToolSettings(EditorToolSettings::Ok|
+ EditorToolSettings::Try|
+ EditorToolSettings::Cancel,
+ EditorToolSettings::PanIcon);
+
+ TQGridLayout* grid = new TQGridLayout(m_gboxSettings->plainPage(), 3, 2);
+
+ TQLabel *filterMethodLabel = new TQLabel(i18n("Filter:"), m_gboxSettings->plainPage());
+ m_filterMethodCombo = new RComboBox(m_gboxSettings->plainPage());
+ m_filterMethodCombo->insertItem(i18n("Average"));
+ m_filterMethodCombo->insertItem(i18n("Linear"));
+ m_filterMethodCombo->insertItem(i18n("Quadratic"));
+ m_filterMethodCombo->insertItem(i18n("Cubic"));
+ m_filterMethodCombo->setDefaultItem(HotPixelFixer::QUADRATIC_INTERPOLATION);
+
+ m_blackFrameButton = new TQPushButton(i18n("Black Frame..."), m_gboxSettings->plainPage());
+ TQWhatsThis::add(m_blackFrameButton, i18n("<p>Use this button to "
+ "add a new black frame file which will be used by the hot pixels removal filter."));
+
+ m_blackFrameListView = new BlackFrameListView(m_gboxSettings->plainPage());
+
+ grid->addMultiCellWidget(filterMethodLabel, 0, 0, 0, 0);
+ grid->addMultiCellWidget(m_filterMethodCombo, 0, 0, 1, 1);
+ grid->addMultiCellWidget(m_blackFrameButton, 0, 0, 2, 2);
+ grid->addMultiCellWidget(m_blackFrameListView, 1, 2, 0, 2);
+ grid->setRowStretch(3, 10);
+ grid->setMargin(m_gboxSettings->spacingHint());
+ grid->setSpacing(m_gboxSettings->spacingHint());
+
+ setToolSettings(m_gboxSettings);
+
+ // -------------------------------------------------------------
+
+ m_previewWidget = new ImagePanelWidget(470, 350, "hotpixels Tool", m_gboxSettings->panIconView(),
+ 0, ImagePanelWidget::SeparateViewDuplicate);
+
+ setToolView(m_previewWidget);
+ init();
+
+ // -------------------------------------------------------------
+
+ connect(m_filterMethodCombo, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotEffect()));
+
+ connect(m_blackFrameButton, TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(slotAddBlackFrame()));
+
+ connect(m_blackFrameListView, TQ_SIGNAL(blackFrameSelected(TQValueList<HotPixel>, const KURL&)),
+ this, TQ_SLOT(slotBlackFrame(TQValueList<HotPixel>, const KURL&)));
+}
+
+HotPixelsTool::~HotPixelsTool()
+{
+}
+
+void HotPixelsTool::readSettings()
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup("hotpixels Tool");
+ m_blackFrameURL = KURL(config->readEntry("Last Black Frame File", TQString()));
+ m_filterMethodCombo->setCurrentItem(config->readNumEntry("Filter Method",
+ m_filterMethodCombo->defaultItem()));
+
+ if (m_blackFrameURL.isValid())
+ {
+ EditorToolIface::editorToolIface()->setToolStartProgress(i18n("Loading: "));
+ BlackFrameListViewItem *item = new BlackFrameListViewItem(m_blackFrameListView, m_blackFrameURL);
+
+ connect(item, TQ_SIGNAL(signalLoadingProgress(float)),
+ this, TQ_SLOT(slotLoadingProgress(float)));
+
+ connect(item, TQ_SIGNAL(signalLoadingComplete()),
+ this, TQ_SLOT(slotLoadingComplete()));
+ }
+}
+
+void HotPixelsTool::slotLoadingProgress(float v)
+{
+ EditorToolIface::editorToolIface()->setToolProgress((int)(v*100));
+}
+
+void HotPixelsTool::slotLoadingComplete()
+{
+ EditorToolIface::editorToolIface()->setToolStopProgress();
+}
+
+void HotPixelsTool::writeSettings()
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup("hotpixels Tool");
+ config->writeEntry("Last Black Frame File", m_blackFrameURL.url());
+ config->writeEntry("Filter Method", m_filterMethodCombo->currentItem());
+ m_previewWidget->writeSettings();
+ config->sync();
+}
+
+void HotPixelsTool::slotResetSettings()
+{
+ m_filterMethodCombo->blockSignals(true);
+ m_filterMethodCombo->slotReset();
+ m_filterMethodCombo->blockSignals(false);
+}
+
+void HotPixelsTool::slotAddBlackFrame()
+{
+ KURL url = ImageDialog::getImageURL(kapp->activeWindow(), m_blackFrameURL, i18n("Select Black Frame Image"));
+
+ if (!url.isEmpty())
+ {
+ // Load the selected file and insert into the list.
+
+ m_blackFrameURL = url;
+ m_blackFrameListView->clear();
+ BlackFrameListViewItem *item = new BlackFrameListViewItem(m_blackFrameListView, m_blackFrameURL);
+
+ connect(item, TQ_SIGNAL(signalLoadingProgress(float)),
+ this, TQ_SLOT(slotLoadingProgress(float)));
+
+ connect(item, TQ_SIGNAL(signalLoadingComplete()),
+ this, TQ_SLOT(slotLoadingComplete()));
+ }
+}
+
+void HotPixelsTool::renderingFinished()
+{
+ m_filterMethodCombo->setEnabled(true);
+ m_blackFrameListView->setEnabled(true);
+}
+
+void HotPixelsTool::prepareEffect()
+{
+ m_filterMethodCombo->setEnabled(false);
+ m_blackFrameListView->setEnabled(false);
+
+ DImg image = m_previewWidget->getOriginalRegionImage();
+ int interpolationMethod = m_filterMethodCombo->currentItem();
+
+ TQValueList<HotPixel> hotPixelsRegion;
+ TQRect area = m_previewWidget->getOriginalImageRegionToRender();
+ TQValueList<HotPixel>::Iterator end(m_hotPixelsList.end());
+
+ for (TQValueList<HotPixel>::Iterator it = m_hotPixelsList.begin() ; it != end ; ++it )
+ {
+ HotPixel hp = (*it);
+
+ if ( area.contains( hp.rect ) )
+ {
+ hp.rect.moveTopLeft(TQPoint( hp.rect.x()-area.x(), hp.rect.y()-area.y() ));
+ hotPixelsRegion.append(hp);
+ }
+ }
+
+ setFilter(dynamic_cast<DImgThreadedFilter*>(new HotPixelFixer(&image, this, hotPixelsRegion, interpolationMethod)));
+}
+
+void HotPixelsTool::prepareFinal()
+{
+ m_filterMethodCombo->setEnabled(false);
+ m_blackFrameListView->setEnabled(false);
+
+ int interpolationMethod = m_filterMethodCombo->currentItem();
+
+ ImageIface iface(0, 0);
+ setFilter(dynamic_cast<DImgThreadedFilter*>(new HotPixelFixer(iface.getOriginalImg(), this,m_hotPixelsList,interpolationMethod)));
+}
+
+void HotPixelsTool::putPreviewData()
+{
+ m_previewWidget->setPreviewImage(filter()->getTargetImage());
+}
+
+void HotPixelsTool::putFinalData()
+{
+ ImageIface iface(0, 0);
+ iface.putOriginalImage(i18n("Hot Pixels Correction"), filter()->getTargetImage().bits());
+}
+
+void HotPixelsTool::slotBlackFrame(TQValueList<HotPixel> hpList, const KURL& blackFrameURL)
+{
+ m_blackFrameURL = blackFrameURL;
+ m_hotPixelsList = hpList;
+
+ TQPointArray pointList(m_hotPixelsList.size());
+ TQValueList <HotPixel>::Iterator it;
+ int i = 0;
+ TQValueList <HotPixel>::Iterator end(m_hotPixelsList.end());
+
+ for (it = m_hotPixelsList.begin() ; it != end ; ++it, i++)
+ pointList.setPoint(i, (*it).rect.center());
+
+ m_previewWidget->setPanIconHighLightPoints(pointList);
+
+ slotEffect();
+}
+
+} // NameSpace DigikamHotPixelsImagesPlugin
diff --git a/src/imageplugins/hotpixels/hotpixelstool.h b/src/imageplugins/hotpixels/hotpixelstool.h
new file mode 100644
index 00000000..727c6387
--- /dev/null
+++ b/src/imageplugins/hotpixels/hotpixelstool.h
@@ -0,0 +1,113 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-27
+ * Description : a digiKam image plugin for fixing dots produced by
+ * hot/stuck/dead pixels from a CCD.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2005-2006 by Unai Garro <ugarro at users dot sourceforge dot net>
+ *
+ * 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_HOTPIXELS_H
+#define IMAGEEFFECT_HOTPIXELS_H
+
+#define MAX_PIXEL_DEPTH 4
+
+// TQt includes.
+
+#include <tqvaluelist.h>
+
+// KDE includes.
+
+#include <kurl.h>
+
+// Digikam includes.
+
+#include "editortool.h"
+
+// Local includes.
+
+#include "hotpixelfixer.h"
+
+class TQPushButton;
+
+namespace KDcrawIface
+{
+class RComboBox;
+}
+
+namespace Digikam
+{
+class EditorToolSettings;
+class ImagePanelWidget;
+}
+
+namespace DigikamHotPixelsImagesPlugin
+{
+
+class BlackFrameListView;
+
+class HotPixelsTool : public Digikam::EditorToolThreaded
+{
+ TQ_OBJECT
+
+
+public:
+
+ HotPixelsTool(TQObject *parent);
+ ~HotPixelsTool();
+
+private slots:
+
+ void slotBlackFrame(TQValueList<HotPixel> hpList, const KURL& blackFrameURL);
+ void slotResetSettings();
+ void slotAddBlackFrame();
+ void slotLoadingProgress(float);
+ void slotLoadingComplete();
+
+private:
+
+ void readSettings();
+ void writeSettings();
+ void prepareEffect();
+ void prepareFinal();
+ void abortPreview();
+ void putPreviewData();
+ void putFinalData();
+ void renderingFinished();
+
+private:
+
+ TQPushButton *m_blackFrameButton;
+
+ TQValueList<HotPixel> m_hotPixelsList;
+
+ KURL m_blackFrameURL;
+
+ BlackFrameListView *m_blackFrameListView;
+
+ KDcrawIface::RComboBox *m_filterMethodCombo;
+
+ Digikam::ImagePanelWidget *m_previewWidget;
+
+ Digikam::EditorToolSettings *m_gboxSettings;
+};
+
+} // NameSpace DigikamHotPixelsImagesPlugin
+
+#endif /* IMAGEEFFECT_HOTPIXELS_H */
diff --git a/src/imageplugins/hotpixels/imageeffect_hotpixels.cpp b/src/imageplugins/hotpixels/imageeffect_hotpixels.cpp
new file mode 100644
index 00000000..67e9a1b2
--- /dev/null
+++ b/src/imageplugins/hotpixels/imageeffect_hotpixels.cpp
@@ -0,0 +1,279 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-27
+ * Description : a digiKam image plugin for fixing dots produced by
+ * hot/stuck/dead pixels from a CCD.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2005-2006 by Unai Garro <ugarro at users dot sourceforge dot net>
+ *
+ * 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 <tqcombobox.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqwhatsthis.h>
+#include <tqpushbutton.h>
+#include <tqpointarray.h>
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <tdeconfig.h>
+#include <kimageio.h>
+#include <tdeaboutdata.h>
+#include <tdeapplication.h>
+#include <kstandarddirs.h>
+#include <tdefiledialog.h>
+#include <kprogress.h>
+
+// Local includes.
+
+#include "version.h"
+#include "ddebug.h"
+#include "dimg.h"
+#include "imageiface.h"
+#include "imagewidget.h"
+#include "imagedialog.h"
+#include "blackframelistview.h"
+#include "imageeffect_hotpixels.h"
+#include "imageeffect_hotpixels.moc"
+
+namespace DigikamHotPixelsImagesPlugin
+{
+
+ImageEffect_HotPixels::ImageEffect_HotPixels(TQWidget* parent)
+ : CtrlPanelDlg(parent, i18n("Hot Pixels Correction"),
+ "hotpixels", false, false, false,
+ Digikam::ImagePannelWidget::SeparateViewDuplicate)
+{
+ // No need Abort button action.
+ showButton(User1, false);
+
+ TQString whatsThis;
+
+ TDEAboutData* about = new TDEAboutData("digikam",
+ I18N_NOOP("Hot Pixels Correction"),
+ digikam_version,
+ I18N_NOOP("A digiKam image plugin for fixing dots produced by "
+ "hot/stuck/dead pixels from a CCD."),
+ TDEAboutData::License_GPL,
+ "(c) 2005-2006, Unai Garro\n(c) 2005-2008, Gilles Caulier",
+ 0,
+ "http://www.digikam.org");
+
+ about->addAuthor("Unai Garro", I18N_NOOP("Author and maintainer"),
+ "ugarro at sourceforge dot net");
+
+ about->addAuthor("Gilles Caulier", I18N_NOOP("Developer"),
+ "caulier dot gilles at gmail dot com");
+
+ setAboutData(about);
+
+ // -------------------------------------------------------------
+
+ TQWidget *gboxSettings = new TQWidget(m_imagePreviewWidget);
+ TQGridLayout* gridSettings = new TQGridLayout(gboxSettings, 3, 2, 0, spacingHint());
+
+ TQLabel *filterMethodLabel = new TQLabel(i18n("Filter:"), gboxSettings);
+ m_filterMethodCombo = new TQComboBox(gboxSettings);
+ m_filterMethodCombo->insertItem(i18n("Average"));
+ m_filterMethodCombo->insertItem(i18n("Linear"));
+ m_filterMethodCombo->insertItem(i18n("Quadratic"));
+ m_filterMethodCombo->insertItem(i18n("Cubic"));
+
+ m_blackFrameButton = new TQPushButton(i18n("Black Frame..."), gboxSettings);
+ setButtonWhatsThis( Apply, i18n("<p>Use this button to add a new black frame file which will "
+ "be used by the hot pixels removal filter.") );
+
+ m_blackFrameListView = new BlackFrameListView(gboxSettings);
+ m_progressBar = new KProgress(100, gboxSettings);
+ m_progressBar->setValue(0);
+ m_progressBar->hide();
+
+ gridSettings->addMultiCellWidget(filterMethodLabel, 0, 0, 0, 0);
+ gridSettings->addMultiCellWidget(m_filterMethodCombo, 0, 0, 1, 1);
+ gridSettings->addMultiCellWidget(m_blackFrameButton, 0, 0, 2, 2);
+ gridSettings->addMultiCellWidget(m_blackFrameListView, 1, 2, 0, 2);
+ gridSettings->addMultiCellWidget(m_progressBar, 3, 3, 0, 2);
+
+ m_imagePreviewWidget->setUserAreaWidget(gboxSettings);
+
+ // -------------------------------------------------------------
+
+ connect(m_filterMethodCombo, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotEffect()));
+
+ connect(m_blackFrameButton, TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(slotAddBlackFrame()));
+
+ connect(m_blackFrameListView, TQ_SIGNAL(blackFrameSelected(TQValueList<HotPixel>, const KURL&)),
+ this, TQ_SLOT(slotBlackFrame(TQValueList<HotPixel>, const KURL&)));
+}
+
+ImageEffect_HotPixels::~ImageEffect_HotPixels()
+{
+}
+
+void ImageEffect_HotPixels::readUserSettings()
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup("hotpixels Tool Dialog");
+ m_blackFrameURL = KURL(config->readEntry("Last Black Frame File", TQString()));
+ m_filterMethodCombo->setCurrentItem(config->readNumEntry("Filter Method",
+ HotPixelFixer::QUADRATIC_INTERPOLATION));
+
+ if (m_blackFrameURL.isValid())
+ {
+ BlackFrameListViewItem *item = new BlackFrameListViewItem(m_blackFrameListView, m_blackFrameURL);
+
+ connect(item, TQ_SIGNAL(signalLoadingProgress(float)),
+ this, TQ_SLOT(slotLoadingProgress(float)));
+
+ connect(item, TQ_SIGNAL(signalLoadingComplete()),
+ this, TQ_SLOT(slotLoadingComplete()));
+ }
+}
+
+void ImageEffect_HotPixels::writeUserSettings()
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup("hotpixels Tool Dialog");
+ config->writeEntry("Last Black Frame File", m_blackFrameURL.url());
+ config->writeEntry("Filter Method", m_filterMethodCombo->currentItem());
+ config->sync();
+}
+
+void ImageEffect_HotPixels::resetValues()
+{
+ m_filterMethodCombo->blockSignals(true);
+ m_filterMethodCombo->setCurrentItem(HotPixelFixer::QUADRATIC_INTERPOLATION);
+ m_filterMethodCombo->blockSignals(false);
+}
+
+void ImageEffect_HotPixels::slotAddBlackFrame()
+{
+ KURL url = Digikam::ImageDialog::getImageURL(this, m_blackFrameURL,
+ i18n("Select Black Frame Image"));
+
+ if (!url.isEmpty())
+ {
+ // Load the selected file and insert into the list.
+
+ m_blackFrameURL = url;
+ m_blackFrameListView->clear();
+ BlackFrameListViewItem *item = new BlackFrameListViewItem(m_blackFrameListView, m_blackFrameURL);
+
+ connect(item, TQ_SIGNAL(signalLoadingProgress(float)),
+ this, TQ_SLOT(slotLoadingProgress(float)));
+
+ connect(item, TQ_SIGNAL(signalLoadingComplete()),
+ this, TQ_SLOT(slotLoadingComplete()));
+ }
+}
+
+void ImageEffect_HotPixels::slotLoadingProgress(float v)
+{
+ m_progressBar->show();
+ m_progressBar->setValue((int)(v*100));
+}
+
+void ImageEffect_HotPixels::slotLoadingComplete()
+{
+ m_progressBar->hide();
+}
+
+void ImageEffect_HotPixels::renderingFinished()
+{
+ m_filterMethodCombo->setEnabled(true);
+ m_blackFrameListView->setEnabled(true);
+ enableButton(Apply, true);
+}
+
+void ImageEffect_HotPixels::prepareEffect()
+{
+ m_filterMethodCombo->setEnabled(false);
+ m_blackFrameListView->setEnabled(false);
+ enableButton(Apply, false);
+
+ Digikam::DImg image = m_imagePreviewWidget->getOriginalRegionImage();
+ int interpolationMethod = m_filterMethodCombo->currentItem();
+
+ TQValueList<HotPixel> hotPixelsRegion;
+ TQRect area = m_imagePreviewWidget->getOriginalImageRegionToRender();
+ TQValueList<HotPixel>::Iterator end(m_hotPixelsList.end());
+
+ for (TQValueList<HotPixel>::Iterator it = m_hotPixelsList.begin() ; it != end ; ++it )
+ {
+ HotPixel hp = (*it);
+
+ if ( area.contains( hp.rect ) )
+ {
+ hp.rect.moveTopLeft(TQPoint( hp.rect.x()-area.x(), hp.rect.y()-area.y() ));
+ hotPixelsRegion.append(hp);
+ }
+ }
+
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>(
+ new HotPixelFixer(&image, this, hotPixelsRegion, interpolationMethod));
+}
+
+void ImageEffect_HotPixels::prepareFinal()
+{
+ m_filterMethodCombo->setEnabled(false);
+ m_blackFrameListView->setEnabled(false);
+ enableButton(Apply, false);
+
+ int interpolationMethod = m_filterMethodCombo->currentItem();
+
+ Digikam::ImageIface iface(0, 0);
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>(
+ new HotPixelFixer(iface.getOriginalImg(), this,m_hotPixelsList,interpolationMethod));
+}
+
+void ImageEffect_HotPixels::putPreviewData()
+{
+ m_imagePreviewWidget->setPreviewImage(m_threadedFilter->getTargetImage());
+}
+
+void ImageEffect_HotPixels::putFinalData()
+{
+ Digikam::ImageIface iface(0, 0);
+ iface.putOriginalImage(i18n("Hot Pixels Correction"), m_threadedFilter->getTargetImage().bits());
+}
+
+void ImageEffect_HotPixels::slotBlackFrame(TQValueList<HotPixel> hpList, const KURL& blackFrameURL)
+{
+ m_blackFrameURL = blackFrameURL;
+ m_hotPixelsList = hpList;
+
+ TQPointArray pointList(m_hotPixelsList.size());
+ TQValueList <HotPixel>::Iterator it;
+ int i = 0;
+ TQValueList <HotPixel>::Iterator end(m_hotPixelsList.end());
+
+ for (it = m_hotPixelsList.begin() ; it != end ; ++it, i++)
+ pointList.setPoint(i, (*it).rect.center());
+
+ m_imagePreviewWidget->setPanIconHighLightPoints(pointList);
+
+ slotEffect();
+}
+
+} // NameSpace DigikamHotPixelsImagesPlugin
diff --git a/src/imageplugins/hotpixels/imageeffect_hotpixels.h b/src/imageplugins/hotpixels/imageeffect_hotpixels.h
new file mode 100644
index 00000000..4a8b0868
--- /dev/null
+++ b/src/imageplugins/hotpixels/imageeffect_hotpixels.h
@@ -0,0 +1,104 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-27
+ * Description : a digiKam image plugin for fixing dots produced by
+ * hot/stuck/dead pixels from a CCD.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2005-2006 by Unai Garro <ugarro at users dot sourceforge dot net>
+ *
+ * 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_HOTPIXELS_H
+#define IMAGEEFFECT_HOTPIXELS_H
+
+#define MAX_PIXEL_DEPTH 4
+
+// TQt includes.
+
+#include <tqvaluelist.h>
+
+// KDE includes.
+
+#include <kurl.h>
+
+// Digikam includes.
+
+#include "ctrlpaneldlg.h"
+
+// Local includes.
+
+#include "hotpixelfixer.h"
+
+class TQComboBox;
+class TQPushButton;
+
+class KProgress;
+
+namespace DigikamHotPixelsImagesPlugin
+{
+
+class BlackFrameListView;
+
+class ImageEffect_HotPixels : public Digikam::CtrlPanelDlg
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImageEffect_HotPixels(TQWidget *parent);
+ ~ImageEffect_HotPixels();
+
+private slots:
+
+ void slotLoadingProgress(float v);
+ void slotLoadingComplete();
+
+ void slotBlackFrame(TQValueList<HotPixel> hpList, const KURL& blackFrameURL);
+ void slotAddBlackFrame();
+ void readUserSettings();
+
+private:
+
+ void writeUserSettings();
+ void resetValues();
+ void prepareEffect();
+ void prepareFinal();
+ void abortPreview();
+ void putPreviewData();
+ void putFinalData();
+ void renderingFinished();
+
+private:
+
+ TQComboBox *m_filterMethodCombo;
+
+ TQPushButton *m_blackFrameButton;
+
+ TQValueList<HotPixel> m_hotPixelsList;
+
+ KURL m_blackFrameURL;
+
+ KProgress *m_progressBar;
+
+ BlackFrameListView *m_blackFrameListView;
+};
+
+} // NameSpace DigikamHotPixelsImagesPlugin
+
+#endif /* IMAGEEFFECT_HOTPIXELS_H */
diff --git a/src/imageplugins/hotpixels/imageplugin_hotpixels.cpp b/src/imageplugins/hotpixels/imageplugin_hotpixels.cpp
new file mode 100644
index 00000000..864b59dc
--- /dev/null
+++ b/src/imageplugins/hotpixels/imageplugin_hotpixels.cpp
@@ -0,0 +1,72 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-27
+ * Description : a digiKam image plugin for fixing dots produced by
+ * hot/stuck/dead pixels from a CCD.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2005-2006 by Unai Garro <ugarro at users dot sourceforge dot net>
+ *
+ * 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 "hotpixelstool.h"
+#include "imageplugin_hotpixels.h"
+#include "imageplugin_hotpixels.moc"
+
+using namespace DigikamHotPixelsImagesPlugin;
+
+K_EXPORT_COMPONENT_FACTORY(digikamimageplugin_hotpixels,
+ KGenericFactory<ImagePlugin_HotPixels>("digikamimageplugin_hotpixels"));
+
+ImagePlugin_HotPixels::ImagePlugin_HotPixels(TQObject *parent, const char*, const TQStringList &)
+ : Digikam::ImagePlugin(parent, "ImagePlugin_HotPixels")
+{
+ m_hotpixelsAction = new TDEAction(i18n("Hot Pixels..."), "hotpixels", 0,
+ this, TQ_SLOT(slotHotPixels()),
+ actionCollection(), "imageplugin_hotpixels");
+
+ setXMLFile("digikamimageplugin_hotpixels_ui.rc");
+
+ DDebug() << "ImagePlugin_HotPixels plugin loaded" << endl;
+}
+
+ImagePlugin_HotPixels::~ImagePlugin_HotPixels()
+{
+}
+
+void ImagePlugin_HotPixels::setEnabledActions(bool enable)
+{
+ m_hotpixelsAction->setEnabled(enable);
+}
+
+void ImagePlugin_HotPixels::slotHotPixels()
+{
+ HotPixelsTool *tool = new HotPixelsTool(this);
+ loadTool(tool);
+}
diff --git a/src/imageplugins/hotpixels/imageplugin_hotpixels.h b/src/imageplugins/hotpixels/imageplugin_hotpixels.h
new file mode 100644
index 00000000..c639b830
--- /dev/null
+++ b/src/imageplugins/hotpixels/imageplugin_hotpixels.h
@@ -0,0 +1,56 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-27
+ * Description : a digiKam image plugin for fixing dots produced by
+ * hot/stuck/dead pixels from a CCD.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2005-2006 by Unai Garro <ugarro at users dot sourceforge dot net>
+ *
+ * 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_HOTPIXELS_H
+#define IMAGEPLUGIN_HOTPIXELS_H
+
+// Digikam includes.
+
+#include "imageplugin.h"
+#include "digikam_export.h"
+
+class DIGIKAMIMAGEPLUGINS_EXPORT ImagePlugin_HotPixels : public Digikam::ImagePlugin
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImagePlugin_HotPixels(TQObject *parent, const char* name,
+ const TQStringList &args);
+ ~ImagePlugin_HotPixels();
+
+ void setEnabledActions(bool enable);
+
+private slots:
+
+ void slotHotPixels();
+
+private:
+
+ TDEAction *m_hotpixelsAction;
+};
+
+#endif /* IMAGEPLUGIN_HOTPIXELS_H */
diff --git a/src/imageplugins/hotpixels/weights.cpp b/src/imageplugins/hotpixels/weights.cpp
new file mode 100644
index 00000000..e0d3f246
--- /dev/null
+++ b/src/imageplugins/hotpixels/weights.cpp
@@ -0,0 +1,283 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-27
+ * Description : a class to calculate filter weights
+ *
+ * Copyright (C) 2005-2006 by Unai Garro <ugarro at users dot sourceforge dot net>
+ *
+ * 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.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cstring>
+
+// Local includes.
+
+#include "weights.h"
+
+namespace DigikamHotPixelsImagesPlugin
+{
+
+Weights::Weights(const Weights &w)
+{
+ (*this) = w;
+}
+
+void Weights::operator=(const Weights &w)
+{
+ mHeight=w.height();
+ mWidth=w.width();
+ mPositions=(w.positions());
+ mCoefficientNumber=w.coefficientNumber();
+ mTwoDim=w.twoDim();
+ mPolynomeOrder=w.polynomeOrder();
+
+ // Allocate memory and copy weights
+ // if the original one was calculated
+
+ if (!w.weightMatrices()) return;
+ else
+ {
+ double*** origMatrices=w.weightMatrices();
+ mWeightMatrices = new double**[mPositions.count()]; //allocate mPositions.count() matrices
+
+ for (uint i=0; i<mPositions.count(); i++)
+ {
+ mWeightMatrices[i]=new double*[mHeight]; //allocate mHeight rows on each position
+ for (unsigned int j=0; j<mHeight; j++)
+ {
+ mWeightMatrices[i][j]=new double[mWidth]; //Allocate mWidth columns on each row
+ for (unsigned int k=0; k<mWidth; k++)
+ {
+ mWeightMatrices[i][j][k]=origMatrices[i][j][k];
+ }
+ }
+ }
+ }
+}
+
+void Weights::calculateWeights()
+{
+ mCoefficientNumber = (mTwoDim
+ ? ((size_t)mPolynomeOrder + 1) * ((size_t)mPolynomeOrder + 1)
+ : (size_t)mPolynomeOrder + 1);
+ double *matrix; /* num_coeff * num_coeff */
+ double *vector0; /* mPositions.count() * num_coeff */
+ double *vector1; /* mPositions.count() * num_coeff */
+ size_t ix,iy,i,j;
+ int x, y;
+
+ // Determine coordinates of pixels to be sampled
+
+ if (mTwoDim)
+ {
+
+ int iPolynomeOrder=(int) mPolynomeOrder; //lets avoid signed/unsigned comparison warnings
+ int iHeight = (int) height(); //"
+ int iWidth = (int) width(); //"
+
+ for (y = -iPolynomeOrder; y < iHeight + iPolynomeOrder; ++y)
+ {
+ for (x = -iPolynomeOrder; x < iWidth + iPolynomeOrder; ++x)
+ {
+ if ((x < 0 && y < 0 && -x - y < iPolynomeOrder + 2)
+ || (x < 0 && y >= iHeight && -x + y - iHeight < iPolynomeOrder + 1)
+ || (x >= iWidth && y < 0 && x - y - iWidth < iPolynomeOrder + 1)
+ || (x >= iWidth && y >= iHeight && x + y - iWidth - iHeight < iPolynomeOrder)
+ || (x < 0 && y >= 0 && y < iHeight) || (x >= iWidth && y >= 0 && y < iHeight)
+ || (y < 0 && x >= 0 && x < iWidth ) || (y >= iHeight && x >= 0 && x < iWidth))
+ {
+ TQPoint position(x,y);
+ mPositions.append(position);
+ }
+ }
+ }
+ }
+ else
+ {
+ // In the one-dimensional case, only the y coordinate and y size is used. */
+
+ for (y = -mPolynomeOrder; y < 0; ++y)
+ {
+ TQPoint position(0,y);
+ mPositions.append(position);
+ }
+
+ for (y = (int) height(); y < (int) height() + (int) mPolynomeOrder; ++y)
+ {
+ TQPoint position(0,y);
+ mPositions.append(position);
+ }
+ }
+
+ // Allocate memory.
+
+ matrix = new double[mCoefficientNumber*mCoefficientNumber];
+ vector0 = new double[mPositions.count() * mCoefficientNumber];
+ vector1 = new double[mPositions.count() * mCoefficientNumber];
+
+ // Calculate coefficient matrix and vectors
+
+ for (iy = 0; iy < mCoefficientNumber; ++iy)
+ {
+ for (ix = 0; ix < mCoefficientNumber; ++ix)
+ matrix [iy*mCoefficientNumber+ix] = 0.0;
+
+ for (j = 0; j < mPositions.count(); ++j)
+ {
+ vector0 [iy * mPositions.count() + j] = polyTerm (iy, mPositions [j].x(),
+ mPositions [j].y(), mPolynomeOrder);
+
+ for (ix = 0; ix < mCoefficientNumber; ++ix)
+ matrix [iy * mCoefficientNumber + ix] += (vector0 [iy * mPositions.count() + j]
+ * polyTerm (ix, mPositions [j].x(), mPositions[j].y(), mPolynomeOrder));
+ }
+ }
+
+ // Invert matrix.
+
+ matrixInv (matrix, mCoefficientNumber);
+
+ // Multiply inverse matrix with vector.
+
+ for (iy = 0; iy < mCoefficientNumber; ++iy)
+ for (j = 0; j < mPositions.count(); ++j)
+ {
+ vector1 [iy * mPositions.count() + j] = 0.0;
+
+ for (ix = 0; ix < mCoefficientNumber; ++ix)
+ vector1 [iy * mPositions.count() + j] += matrix [iy * mCoefficientNumber + ix]
+ * vector0 [ix * mPositions.count() + j];
+ }
+
+ // Store weights
+
+ mWeightMatrices = new double**[mPositions.count()]; //allocate mPositions.count() matrices
+
+ for (i=0; i<mPositions.count(); i++)
+ {
+ mWeightMatrices[i] = new double*[mHeight]; //allocate mHeight rows on each position
+ for (j=0; j<mHeight; j++)
+ mWeightMatrices[i][j] = new double[mWidth]; //Allocate mWidth columns on each row
+ }
+
+ for (y = 0; y < (int) mHeight; ++y)
+ {
+ for (x = 0; x < (int) mWidth; ++x)
+ {
+ for (j = 0; j < mPositions.count(); ++j)
+ {
+ mWeightMatrices [j][y][x] = 0.0;
+
+ for (iy = 0; iy < mCoefficientNumber; ++iy)
+ mWeightMatrices [j][y][x] += vector1 [iy * mPositions.count() + j]
+ * polyTerm (iy, x, y, mPolynomeOrder);
+
+ mWeightMatrices [j][y][x] *= (double) mPositions.count();
+ }
+ }
+ }
+
+ delete[] vector1;
+ delete[] vector0;
+ delete[] matrix;
+}
+
+bool Weights::operator==(const Weights& ws) const
+{
+ return (mHeight==ws.height() &&
+ mWidth==ws.width() &&
+ mPolynomeOrder==ws.polynomeOrder() &&
+ mTwoDim==ws.twoDim()
+ );
+}
+
+ //Invert a quadratic matrix.
+void Weights::matrixInv (double *const a, const size_t size)
+{
+ double *const b = new double[size * size];
+ size_t ix, iy, j;
+
+ // Copy matrix to new location.
+
+ memcpy (b, a, sizeof (double) * size * size);
+
+ // Set destination matrix to unit matrix.
+
+ for (iy = 0; iy < size; ++iy)
+ for (ix = 0; ix < size; ++ix)
+ a [iy * size + ix] = ix == iy ? 1.0 : 0.0;
+
+ // Convert matrix to upper triangle form.
+
+ for (iy = 0; iy < size - 1; ++iy)
+ {
+ for (j = iy + 1; j < size; ++j)
+ {
+ const double factor = b [j * size + iy] / b [iy * size + iy];
+
+ for (ix = 0; ix < size; ++ix)
+ {
+ b [j * size + ix] -= factor * b [iy * size + ix];
+ a [j * size + ix] -= factor * a [iy * size + ix];
+ }
+ }
+ }
+
+ // Convert matrix to diagonal form.
+
+ for (iy = size - 1; iy > 0; --iy)
+ {
+ for (j = 0; j < iy; ++j)
+ {
+ const double factor = b [j * size + iy] / b [iy * size + iy];
+
+ for (ix = 0; ix < size; ++ix)
+ a [j * size + ix] -= factor * a [iy * size + ix];
+ }
+ }
+
+ // Convert matrix to unit matrix.
+
+ for (iy = 0; iy < size; ++iy)
+ for (ix = 0; ix < size; ++ix)
+ a [iy * size + ix] /= b [iy * size + iy];
+
+ delete [] b;
+}
+
+// Calculates one term of the polynomial
+double Weights::polyTerm (const size_t i_coeff, const int x, const int y, const int poly_order)
+{
+ const size_t x_power = i_coeff / ((size_t)poly_order + 1);
+ const size_t y_power = i_coeff % ((size_t)poly_order + 1);
+ int result;
+ size_t i;
+
+ result = 1;
+
+ for (i = 0; i < x_power; ++i)
+ result *= x;
+
+ for (i = 0; i < y_power; ++i)
+ result *= y;
+
+ return (double)result;
+}
+
+} // NameSpace DigikamHotPixelsImagesPlugin
+
diff --git a/src/imageplugins/hotpixels/weights.h b/src/imageplugins/hotpixels/weights.h
new file mode 100644
index 00000000..b82fde89
--- /dev/null
+++ b/src/imageplugins/hotpixels/weights.h
@@ -0,0 +1,90 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-27
+ * Description : a class to calculate filter weights
+ *
+ * Copyright (C) 2005-2006 by Unai Garro <ugarro at users dot sourceforge dot net>
+ *
+ * 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 WEIGHTS_H
+#define WEIGHTS_H
+
+// TQt includes.
+
+#include <tqrect.h>
+#include <tqvaluelist.h>
+
+namespace DigikamHotPixelsImagesPlugin
+{
+
+class Weights
+{
+public:
+
+ Weights(){};
+ Weights(const Weights &w);
+ void operator=(const Weights &w);
+
+ ~Weights()
+ {
+ if (!mWeightMatrices) return;
+ for (unsigned int i=0; i<mPositions.count(); i++)
+ {
+ for (unsigned int j=0; j<mHeight; j++) delete[] mWeightMatrices[i][j];
+ }
+ }
+
+ unsigned int height() const { return mHeight; };
+ unsigned int polynomeOrder() const { return mPolynomeOrder; };
+ bool twoDim() const { return mTwoDim; };
+ unsigned int width() const { return mWidth; };
+
+ void setHeight(int h) { mHeight=h; };
+ void setPolynomeOrder(int order) { mPolynomeOrder=order; };
+ void setTwoDim(bool td) { mTwoDim=td; };
+ void setWidth(int w) { mWidth=w; };
+
+ void calculateWeights();
+ bool operator==(const Weights& ws) const;
+ double** operator[](int n) const { return mWeightMatrices[n]; };
+ const TQValueList <TQPoint> positions() const { return mPositions; };
+
+protected:
+
+ int coefficientNumber() const { return mCoefficientNumber; };
+
+ double*** weightMatrices() const { return mWeightMatrices; };
+
+private:
+
+ double polyTerm (const size_t i_coeff, const int x, const int y, const int poly_order);
+ void matrixInv (double *const a, const size_t size);
+
+private:
+
+ unsigned int mHeight,mWidth;
+ unsigned int mCoefficientNumber;
+ bool mTwoDim;
+ unsigned int mPolynomeOrder;
+ double *** mWeightMatrices; //Stores a list of weight matrices
+ TQValueList <TQPoint> mPositions;
+};
+
+} // NameSpace DigikamHotPixelsImagesPlugin
+
+#endif // WEIGHTS_H