Bug 142443 - red eye correction should change eye colour to an alternate colour
Summary: red eye correction should change eye colour to an alternate colour
Status: RESOLVED FIXED
Alias: None
Product: digikam
Classification: Applications
Component: Faces-RedEyes (show other bugs)
Version: unspecified
Platform: unspecified Linux
: NOR wishlist
Target Milestone: ---
Assignee: Digikam Developers
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-03-03 08:52 UTC by Oliver Doerr
Modified: 2016-08-18 14:58 UTC (History)
0 users

See Also:
Latest Commit:
Version Fixed In: 0.9.2


Attachments
patch to coloring eyes with a custom color (5.52 KB, patch)
2007-03-04 21:50 UTC, caulier.gilles
Details
2nd version of the patch to coloring red yes... (7.90 KB, patch)
2007-03-05 13:42 UTC, caulier.gilles
Details
A red eyes face of my son before to use the tool (447.17 KB, image/png)
2007-03-06 12:45 UTC, caulier.gilles
Details
A red eyes face of my son after to use the tool with a dark cyan coloring taint (447.81 KB, image/png)
2007-03-06 12:46 UTC, caulier.gilles
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Oliver Doerr 2007-03-03 08:52:04 UTC
Version:           0.9.1-rc1 (using KDE 3.5.5, Kubuntu (edgy) 4:3.5.5-0ubuntu3.1)
Compiler:          Target: i486-linux-gnu
OS:                Linux (i686) release 2.6.17-11-generic

Hi,

using the red eye correction has a big problem. It takes the red out of the eye (great) and produces a "dark" eye (not good). It would be better if i could specify a target eye color, so that the tool moves the colour of the red aereas of the eye into that direction.

Would be perfect if i could choose another eye as target eye. Meaning that this eye has the colour there the red eye correction should move the eye colour to.

What do xou think
Oliver
Comment 1 caulier.gilles 2007-03-03 09:24:08 UTC
Hi Oliver (:=)))

I have planed to add coloring feature to red eyes correction tool later 0.9.1.

I'm study the right algorithm to do it. I will gve inspiration from ACDsee red Eye correction tool (if you know).

Gilles Caulier
Comment 2 Oliver Doerr 2007-03-03 14:36:03 UTC
Hi Gilles,

i don't know ACDsee. The wish comes because my little son had a bithday party with a little girl with beautiful blue eyes ;-))

Oliver
Comment 3 caulier.gilles 2007-03-04 21:50:43 UTC
Created attachment 19881 [details]
patch to coloring eyes with a custom color

Oliver, 

attached a patch against svn to coloring the eyes with a custom color. The
color can be choosen from a button. The red color is changed to this color as
well.

The patch is experimental and not optimized. I have no "red eyes" photograph
here to test indeep, but i think it will work fine normally. If you have some
pictures to test, please attach it to this B.K.O file.

The color is not yet saved between plugin session. I will do it later if
algorithm work fine.

Thanks in advance for you report...

Gilles
Comment 4 caulier.gilles 2007-03-04 21:53:18 UTC
Oliver,

I have forget to said than the algorithm do not support yet 16 bits color depth images, only 8 bits...

It's few source code lines to do. I will do it later...

Gilles
Comment 5 Oliver Doerr 2007-03-04 22:01:49 UTC
I have some Photos with red eyes...

But i don't know how to apply a patch to source code. Witch command do i have to use, i want to attach the patch against rc2?

Oliver
Comment 6 caulier.gilles 2007-03-04 22:12:08 UTC
4 Mar 2007 21:01:49 -0000, Oliver Doerr <oliver@doerr-privat.de>:
[bugs.kde.org quoted mail]


fine


But i don't know how to apply a patch to source code. Witch command do i
> have to use,



it's very simple : copy the patch file into digikam/imageplugin folder and
from the command line use "patch -p0 redeyes.patch".
Recompile and install the core plugin to run "make" and "make install" (as
root of course) in this folder.


 i want to attach the patch against rc2?



yes, normally patch can be applied against RC2 without problem.

Friendly

Gilles
<br><br>
<div><span class="gmail_quote">4 Mar 2007 21:01:49 -0000, Oliver Doerr &lt;<a href="mailto:oliver@doerr-privat.de">oliver@doerr-privat.de</a>&gt;:</span>
<blockquote class="gmail_quote" style="PADDING-LEFT: 1ex; MARGIN: 0px 0px 0px 0.8ex; BORDER-LEFT: #ccc 1px solid">------- You are receiving this mail because: -------<br>You are the assignee for the bug, or are watching the assignee.
<br><br><a href="http://bugs.kde.org/show_bug.cgi?id=142443">http://bugs.kde.org/show_bug.cgi?id=142443</a><br><br><br><br><br>------- Additional Comments From oliver doerr-privat de&nbsp;&nbsp;2007-03-04 22:01 -------<br>I have some Photos with red eyes...
</blockquote>
<div>&nbsp;</div>
<div>fine</div>
<div>&nbsp;</div><br>
<blockquote class="gmail_quote" style="PADDING-LEFT: 1ex; MARGIN: 0px 0px 0px 0.8ex; BORDER-LEFT: #ccc 1px solid">But i don&#39;t know how to apply a patch to source code. Witch command do i have to use,</blockquote>
<div>&nbsp;</div>
<div>it&#39;s very simple : copy the patch file into digikam/imageplugin folder and from the command line use &quot;patch -p0 redeyes.patch&quot;.</div>
<div>Recompile and install the core plugin to run &quot;make&quot; and &quot;make install&quot; (as root of course) in this folder.</div>
<div>&nbsp;</div><br>
<blockquote class="gmail_quote" style="PADDING-LEFT: 1ex; MARGIN: 0px 0px 0px 0.8ex; BORDER-LEFT: #ccc 1px solid"> i want to attach the patch against rc2?</blockquote>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>yes, normally patch can be applied against RC2 without problem.</div>
<div>&nbsp;</div>
<div>Friendly</div>
<div>&nbsp;</div>
<div>Gilles</div></div>
Comment 7 Oliver Doerr 2007-03-04 23:02:40 UTC
Hi Gilles,

the command does not end. It looks like it does sweet nothing, because the timestamps of the files remain the same. 

tmp/digikam-0.9.1-rc2/digikam/imageplugins$ patch -p0 redeyes.patch

I am tired now and go to bed. I will take a look at this tomorrow.

Oliver
Comment 8 Gerhard Kulzer 2007-03-05 06:11:50 UTC
Am Sunday 04 March 2007 schrieb Oliver Doerr:
[bugs.kde.org quoted mail]

the command syntax is patch -p0 < redeyes.patch

-p0 when the cwd matches the path in the patch header, -p1 if you're 1 level 
up and so on.

Gerhard
>
> I am tired now and go to bed. I will take a look at this tomorrow.
>
> Oliver
> _______________________________________________
> Digikam-devel mailing list
> Digikam-devel@kde.org
> https://mail.kde.org/mailman/listinfo/digikam-devel

Comment 9 caulier.gilles 2007-03-05 08:47:46 UTC
Gerhard, 

Have you tried the patch ?

Gilles
Comment 10 Gerhard Kulzer 2007-03-05 09:55:11 UTC
Am Monday 05 March 2007 schrieb Gilles Caulier:
[bugs.kde.org quoted mail]
Yes I've tried it. 
I think it's a step in the right direction, but there are still dark squares 
visible after applying 'red eye'. If the selection was round instead of 
square, that would be much better.

Gerhard

P.S. I posted 0.9.1 to our website
Comment 11 Arnd Baecker 2007-03-05 11:48:03 UTC
[...]
> but there are still dark squares
> visible after applying 'red eye'. If the selection was round instead of
> square, that would be much better.


Maybe then even a feathered selection (i.e. one with a smooth transparency
gradient to the outside) would be needed?
(just a thought, haven't tried anything like that)
Comment 12 caulier.gilles 2007-03-05 13:42:15 UTC
Created attachment 19884 [details]
2nd version of the patch to coloring red yes...

This second version of the patch support 16 bits color depth image and remember
coloring taint between tool session.

Next stage is to provide a preview of corrected image and a slider to set the
agressive red eyes correction level...	 

Gilles
Comment 13 Oliver Doerr 2007-03-05 17:17:29 UTC
Hi Gilles,

tried the 1st version of the patch, but it's very difficult to handle. It's difficult to chose the right colour for the eye. Perhaps a colour picker would help, so that i could choose an eye of the person that has not the red eye effect...

Oliver
Comment 14 Mikolaj Machowski 2007-03-05 18:00:06 UTC
> Maybe then even a feathered selection (i.e. one with a smooth
> transparency gradient to the outside) would be needed?
> (just a thought, haven't tried anything like that)

Such selection would be boon for many other plugins.

m.
Comment 15 caulier.gilles 2007-03-05 22:53:55 UTC
SVN commit 639741 by cgilles:

digiKam from trunk : digiKam 0.9.2 implementation continue here : red eyes correction tool can now coloring the eyes with a custom taint 
BUG: 142443

 M  +46 -25    imageeffect_redeye.cpp  
 M  +7 -2      imageeffect_redeye.h  


--- trunk/extragear/graphics/digikam/imageplugins/imageeffect_redeye.cpp #639740:639741
@@ -5,7 +5,7 @@
  * Description : Red eyes correction tool for image editor
  *
  * Copyright 2004-2005 by Renchi Raju, Gilles Caulier
- * Copyright 2006 by Gilles Caulier
+ * Copyright 2006-2007 by Gilles Caulier
  *
  * This program is free software; you can redistribute it
  * and/or modify it under the terms of the GNU General
@@ -25,6 +25,8 @@
 #include <qvbuttongroup.h>
 #include <qradiobutton.h>
 #include <qlayout.h>
+#include <qhbox.h>
+#include <qlabel.h>
 
 // KDE includes.
 
@@ -34,6 +36,7 @@
 #include <kconfig.h>
 #include <kcursor.h>
 #include <kpassivepopup.h>
+#include <kcolorbutton.h>
 
 // Digikam includes.
 
@@ -44,6 +47,7 @@
 // Local includes.
 
 #include "imageeffect_redeye.h"
+#include "imageeffect_redeye.moc"
 
 namespace DigikamImagesPluginCore
 {
@@ -53,7 +57,7 @@
 public:
 
     RedEyePassivePopup(QWidget* parent)
-        : KPassivePopup(parent), m_parent(parent)          
+        : KPassivePopup(parent), m_parent(parent)
     {
     }
 
@@ -106,15 +110,18 @@
     // -- save settings ----------------------------------------------
 
     bool aggressive = (dlg.result() == ImageEffect_RedEyeDlg::Aggressive);
+    QColor coloring = dlg.coloring();
+
     KConfig *config = kapp->config();
     config->setGroup("ImageViewer Settings");
     config->writeEntry("Red Eye Correction Plugin (Mild)", !aggressive);
+    config->writeEntry("Red Eye Correction Plugin (Coloring)", coloring);
     config->sync();
 
     // -- do the actual operations -----------------------------------
 
     parent->setCursor( KCursor::waitCursor() );
-    
+
     struct channel
     {
         float red_gain;
@@ -142,6 +149,10 @@
     green_norm = 1.0 / (green_chan.red_gain + green_chan.green_gain + green_chan.blue_gain);
     blue_norm  = 1.0 / (blue_chan.red_gain  + blue_chan.green_gain  + blue_chan.blue_gain);
 
+    red_norm   *= coloring.red();
+    green_norm *= coloring.green();
+    blue_norm  *= coloring.blue();
+
     if (!selection.sixteenBit())         // 8 bits image.
     {
         uchar* ptr  = selection.bits();
@@ -161,11 +172,11 @@
                                                  red_chan.green_gain * g +
                                                  red_chan.blue_gain  * b)));
 
-                b1 = QMIN(255, (int)(green_norm * (green_chan.red_gain   * r +
+                g1 = QMIN(255, (int)(green_norm * (green_chan.red_gain   * r +
                                                    green_chan.green_gain * g +
                                                    green_chan.blue_gain  * b)));
 
-                g1 = QMIN(255, (int)(blue_norm * (blue_chan.red_gain   * r +
+                b1 = QMIN(255, (int)(blue_norm * (blue_chan.red_gain   * r +
                                                   blue_chan.green_gain * g +
                                                   blue_chan.blue_gain  * b)));
 
@@ -194,17 +205,17 @@
 
             if ( aggressive || r >= ( 2 * g) )
             {
-                r1 = QMIN(65535, (int)(red_norm * (red_chan.red_gain   * r +
-                                                   red_chan.green_gain * g +
-                                                   red_chan.blue_gain  * b)));
+                r1 = QMIN(65535, (int)(red_norm * 256 * (red_chan.red_gain   * r +
+                                                         red_chan.green_gain * g +
+                                                         red_chan.blue_gain  * b)));
 
-                b1 = QMIN(65535, (int)(green_norm * (green_chan.red_gain   * r +
-                                                     green_chan.green_gain * g +
-                                                     green_chan.blue_gain  * b)));
+                g1 = QMIN(65535, (int)(green_norm *  256 * (green_chan.red_gain   * r +
+                                                            green_chan.green_gain * g +
+                                                            green_chan.blue_gain  * b)));
 
-                g1 = QMIN(65535, (int)(blue_norm * (blue_chan.red_gain   * r +
-                                                    blue_chan.green_gain * g +
-                                                    blue_chan.blue_gain  * b)));
+                b1 = QMIN(65535, (int)(blue_norm * 256 * (blue_chan.red_gain   * r +
+                                                          blue_chan.green_gain * g +
+                                                          blue_chan.blue_gain  * b)));
 
                 nptr[0] = b1;
                 nptr[1] = g1;
@@ -232,24 +243,30 @@
                                    Help|Ok|Cancel, Ok, parent, 0, true, true)
 {
     setHelp("redeyecorrectiontool.anchor", "digikam");
-    QVBoxLayout *topLayout = new QVBoxLayout( plainPage(), 0, spacingHint());
+    QVBoxLayout *topLayout = new QVBoxLayout(plainPage(), 0, spacingHint());
 
-    QVButtonGroup* buttonGroup = new QVButtonGroup( i18n("Level of Red-Eye Correction"),
-                                                    plainPage() );
-    buttonGroup->setRadioButtonExclusive( true );
+    QVButtonGroup* buttonGroup = new QVButtonGroup(i18n("Level of Red-Eye Correction"), plainPage());
+    buttonGroup->setRadioButtonExclusive(true);
 
-    QRadioButton* mildBtn = new QRadioButton( i18n("Mild (use if other parts of the face are also selected)"),
-                                              buttonGroup );
-    QRadioButton* aggrBtn = new QRadioButton( i18n("Aggressive (use if eye(s) have been selected exactly)" ),
-                                              buttonGroup );
+    QRadioButton* mildBtn = new QRadioButton(i18n("Mild (use if other parts of the face are also selected)"),
+                                             buttonGroup);
+    QRadioButton* aggrBtn = new QRadioButton(i18n("Aggressive (use if eye(s) have been selected exactly)" ),
+                                             buttonGroup);
 
-    topLayout->addWidget( buttonGroup );
-    
+    QHBox *hbox      = new QHBox(plainPage());
+    QLabel *label    = new QLabel(i18n("Eyes Coloring:"), hbox);
+    m_coloringButton = new KColorButton(Qt::black, hbox);
+
+    topLayout->addWidget(buttonGroup);
+    topLayout->addWidget(hbox);
+
     connect( buttonGroup, SIGNAL(clicked(int)),
              this, SLOT(slotClicked(int)) );
 
+    QColor black(Qt::black);
     KConfig *config = kapp->config();
     config->setGroup("ImageViewer Settings");
+    m_coloringButton->setColor(config->readColorEntry("Red Eye Correction Plugin (Coloring)", &black));
     bool mild = config->readBoolEntry("Red Eye Correction Plugin (Mild)", true);
 
     if (mild)
@@ -269,6 +286,11 @@
     return (Result)m_selectedId;
 }
 
+QColor ImageEffect_RedEyeDlg::coloring() const
+{
+    return m_coloringButton->color();
+}
+
 void ImageEffect_RedEyeDlg::slotClicked(int id)
 {
     m_selectedId = id;
@@ -276,4 +298,3 @@
 
 }  // NameSpace DigikamImagesPluginCore
 
-#include "imageeffect_redeye.moc"
--- trunk/extragear/graphics/digikam/imageplugins/imageeffect_redeye.h #639740:639741
@@ -5,7 +5,7 @@
  * Description : Red eyes correction tool for image editor
  *
  * Copyright 2004-2005 by Renchi Raju, Gilles Caulier
- * Copyright 2006 by Gilles Caulier
+ * Copyright 2006-2007 by Gilles Caulier
  *
  * This program is free software; you can redistribute it
  * and/or modify it under the terms of the GNU General
@@ -29,6 +29,8 @@
 
 class QRadioButton;
 
+class KColorButton;
+
 namespace DigikamImagesPluginCore
 {
 
@@ -53,6 +55,7 @@
 
     ImageEffect_RedEyeDlg(QWidget* parent);
     Result result() const;
+    QColor coloring() const;
 
 private slots:
 
@@ -60,7 +63,9 @@
 
 private:
 
-    int m_selectedId;
+    int           m_selectedId;
+
+    KColorButton *m_coloringButton;
 };
 
 }  // NameSpace DigikamImagesPluginCore
Comment 16 caulier.gilles 2007-03-06 12:36:07 UTC
SVN commit 639957 by cgilles:

digikam from trunk : first approach to use a blending level to merge coloring taint in red eyes correction tool. level hardcoded to 64 give good result, but a clean tool dialog with a slider and a preview look better to set this parameter to the right value.

Photographers : please, i need pictures with Red Eyes face to test. Please send me some samples files by private mail (caulier dot gilles at gmail dot com). Thanks in advance...

CCBUGS: 142443




 M  +4 -3      imageeffect_redeye.cpp  


--- trunk/extragear/graphics/digikam/imageplugins/imageeffect_redeye.cpp #639956:639957
@@ -144,14 +144,15 @@
     blue_chan.blue_gain   = 1.0;
 
     float red_norm, green_norm, blue_norm;
+    int   level = 64;
 
     red_norm   = 1.0 / (red_chan.red_gain   + red_chan.green_gain   + red_chan.blue_gain);
     green_norm = 1.0 / (green_chan.red_gain + green_chan.green_gain + green_chan.blue_gain);
     blue_norm  = 1.0 / (blue_chan.red_gain  + blue_chan.green_gain  + blue_chan.blue_gain);
 
-    red_norm   *= coloring.red();
-    green_norm *= coloring.green();
-    blue_norm  *= coloring.blue();
+    red_norm   *= coloring.red()   / level;
+    green_norm *= coloring.green() / level;
+    blue_norm  *= coloring.blue()  / level;
 
     if (!selection.sixteenBit())         // 8 bits image.
     {
Comment 17 caulier.gilles 2007-03-06 12:45:26 UTC
Created attachment 19891 [details]
A red eyes face of my son before to use the tool
Comment 18 caulier.gilles 2007-03-06 12:46:17 UTC
Created attachment 19892 [details]
A red eyes face of my son after to use the tool with a dark cyan coloring taint
Comment 19 caulier.gilles 2007-03-06 21:12:13 UTC
SVN commit 640090 by cgilles:

digiKam from trunk : digiKam 0.9.2 implementation continue here : red eyes correction again and again and again...

Now the tool have a dialog with a standard preview effect like other image editor tools. A screenshot can by seen at this url :

http://digikam3rdparty.free.fr/Screenshots/newredeyecorrectiontool.png

TODO : 

- make the Red Threshold setting more configurable using a slider to adjust finely the value.
- give another slider setting to adjust the Coloring Taint blending level.

TO STUDY : The content of the eye pupil is destroyed by the flash light reflected on the retinal. Why not use a real eye small pupil photo texture ? This tecture will be in black & white using an alpha channel. We will coloring it using the taint and merge it with the original image to remplace the red area... What do you think about ?

Other implementation patched with this commit : now the image editor plugin interface can render the preview in dialog using the current selection and not only using the full image data.

CCBUGS: 142443

 M  +262 -122  imageplugins/imageeffect_redeye.cpp  
 M  +83 -16    imageplugins/imageeffect_redeye.h  
 M  +17 -1     imageplugins/imageplugin_core.cpp  
 M  +3 -1      libs/widgets/imageplugins/imageguidewidget.cpp  
 M  +2 -1      libs/widgets/imageplugins/imageguidewidget.h  
 M  +3 -2      libs/widgets/imageplugins/imagewidget.cpp  
 M  +2 -1      libs/widgets/imageplugins/imagewidget.h  
 M  +33 -3     utilities/imageeditor/editor/imageiface.cpp  
 M  +10 -0     utilities/imageeditor/editor/imageiface.h  
Comment 20 caulier.gilles 2007-03-07 10:13:34 UTC
SVN commit 640187 by cgilles:

digikam from trunk : Continue to work on Red Eyes correction tool. The dialog provide a fast acess to taint coloring selection using a HSV selector.
A new slider have been added to provide the Taint Level adjustment.

Screenshot is updated :

http://digikam3rdparty.free.fr/Screenshots/newredeyecorrectiontool.png

CCBUGS: 142443




 M  +72 -21    imageeffect_redeye.cpp  
 M  +10 -8     imageeffect_redeye.h  


--- trunk/extragear/graphics/digikam/imageplugins/imageeffect_redeye.cpp #640186:640187
@@ -1,7 +1,7 @@
 /* ============================================================
- * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Authors: Renchi Raju <renchi@pooh.tam.uiuc.edu>
  *         Gilles Caulier <caulier dot gilles at gmail dot com>
- * Date  : 2004-06-06
+ * Date   : 2004-06-06
  * Description : Red eyes correction tool for image editor
  *
  * Copyright 2004-2005 by Renchi Raju, Gilles Caulier
@@ -44,7 +44,7 @@
 #include <kconfig.h>
 #include <kcursor.h>
 #include <kstandarddirs.h>
-#include <kcolorbutton.h>
+#include <kcolordialog.h>
 
 // Digikam includes.
 
@@ -79,7 +79,7 @@
     // -------------------------------------------------------------
                 
     QWidget *gboxSettings     = new QWidget(plainPage());
-    QGridLayout* gridSettings = new QGridLayout( gboxSettings, 6, 4, marginHint(), spacingHint());
+    QGridLayout* gridSettings = new QGridLayout( gboxSettings, 9, 4, marginHint(), spacingHint());
 
     QLabel *label1 = new QLabel(i18n("Channel:"), gboxSettings);
     label1->setAlignment ( Qt::AlignRight | Qt::AlignVCenter );
@@ -152,12 +152,25 @@
     gridSettings->addMultiCellWidget(label2, 3, 3, 0, 4);
     gridSettings->addMultiCellWidget(m_redThreshold, 4, 4, 0, 4);
 
-    QHBox *hbox      = new QHBox(gboxSettings);
-    QLabel *label3   = new QLabel(i18n("Coloring Taint:"), hbox);
-    m_coloringButton = new KColorButton(Qt::black, hbox);
-    gridSettings->addMultiCellWidget(hbox, 5, 5, 0, 4);
+    QLabel *label3 = new QLabel(i18n("Coloring Taint:"), gboxSettings);
+    m_HSSelector   = new KHSSelector(gboxSettings);
+    m_VSelector    = new KValueSelector(gboxSettings);
+    m_HSSelector->setMinimumSize(200, 142);
+    m_VSelector->setMinimumSize(26, 142);
+    gridSettings->addMultiCellWidget(label3, 5, 5, 0, 4);
+    gridSettings->addMultiCellWidget(m_HSSelector, 6, 6, 0, 3);
+    gridSettings->addMultiCellWidget(m_VSelector, 6, 6, 4, 4);
 
-    gridSettings->setRowStretch(6, 10);    
+    QLabel *label4 = new QLabel(i18n("Taint Level:"), gboxSettings);
+    m_taintLevel   = new KIntNumInput(gboxSettings);
+    m_taintLevel->setRange(1, 200, 1, true);
+    m_taintLevel->setValue(0);
+    QWhatsThis::add( m_taintLevel, i18n("<p>Set here the taint level used to coloring red eye."));
+    gridSettings->addMultiCellWidget(label4, 7, 7, 0, 4);
+    gridSettings->addMultiCellWidget(m_taintLevel, 8, 8, 0, 4);
+
+    gridSettings->setRowStretch(9, 10);    
+    gridSettings->setColStretch(3, 10);    
     setUserAreaWidget(gboxSettings);
     
     // -------------------------------------------------------------
@@ -177,8 +190,14 @@
     connect(m_redThreshold, SIGNAL(activated(int)),
             this, SLOT(slotEffect()));   
 
-    connect(m_coloringButton, SIGNAL(changed (const QColor&)),
-            this, SLOT(slotEffect())); 
+    connect(m_HSSelector, SIGNAL(valueChanged(int, int)),
+            this, SLOT(slotHSChanged(int, int)));
+
+    connect(m_VSelector, SIGNAL(valueChanged(int)),
+            this, SLOT(slotTimer()));
+
+    connect(m_taintLevel, SIGNAL(valueChanged(int)),
+            this, SLOT(slotTimer()));  
 }
 
 ImageEffect_RedEye::~ImageEffect_RedEye()
@@ -192,6 +211,17 @@
     delete m_previewWidget;
 }
 
+void ImageEffect_RedEye::slotHSChanged(int h, int s)
+{
+    m_VSelector->blockSignals(true);
+    m_VSelector->setHue(h);
+    m_VSelector->setSaturation(s);
+    m_VSelector->updateContents();
+    m_VSelector->repaint(false);
+    m_VSelector->blockSignals(false);  
+    slotTimer();
+}
+
 void ImageEffect_RedEye::slotChannelChanged(int channel)
 {
     switch(channel)
@@ -233,13 +263,16 @@
 
 void ImageEffect_RedEye::readUserSettings()
 {
-    QColor black(Qt::black);
     KConfig* config = kapp->config();
     config->setGroup("redeye Tool Dialog");
-    m_channelCB->setCurrentItem(config->readNumEntry("Histogram Channel", 0));    // Luminosity.
+    m_channelCB->setCurrentItem(config->readNumEntry("Histogram Channel", 0)); // Luminosity.
     m_scaleBG->setButton(config->readNumEntry("Histogram Scale", Digikam::HistogramWidget::LogScaleHistogram));
     m_redThreshold->setCurrentItem(config->readNumEntry("RedThreshold", Mild));
-    m_coloringButton->setColor(config->readColorEntry("ColoringTaint", &black));
+    m_HSSelector->setXValue(config->readNumEntry("HueColoringTaint", 0));
+    m_HSSelector->setYValue(config->readNumEntry("SatColoringTaint", 0));
+    m_VSelector->setValue(config->readNumEntry("ValColoringTaint", 0));
+    m_taintLevel->setValue(config->readNumEntry("TaintLevel", 64));
+    slotHSChanged(m_HSSelector->xValue(), m_HSSelector->yValue());
     slotChannelChanged(m_channelCB->currentItem());
     slotScaleChanged(m_scaleBG->selectedId());
 }
@@ -251,19 +284,33 @@
     config->writeEntry("Histogram Channel", m_channelCB->currentItem());
     config->writeEntry("Histogram Scale", m_scaleBG->selectedId());
     config->writeEntry("RedThreshold", m_redThreshold->currentItem());
-    config->writeEntry("ColoringTaint", m_coloringButton->color());
+    config->writeEntry("HueColoringTaint", m_HSSelector->xValue());
+    config->writeEntry("SatColoringTaint", m_HSSelector->yValue());
+    config->writeEntry("ValColoringTaint", m_VSelector->value());
+    config->writeEntry("TaintLevel", m_taintLevel->value());
     config->sync();
 }
 
 void ImageEffect_RedEye::resetValues()
 {
-    QColor black(Qt::black);
     m_redThreshold->blockSignals(true);	
-    m_coloringButton->blockSignals(true);	
+    m_HSSelector->blockSignals(true);       
+    m_VSelector->blockSignals(true);   
+    m_taintLevel->blockSignals(true);   
+
     m_redThreshold->setCurrentItem(Mild);
-    m_coloringButton->setColor(black);
+
+    // Black color by default
+    m_HSSelector->setXValue(0);
+    m_HSSelector->setYValue(0);
+    m_VSelector->setValue(0);
+
+    m_taintLevel->setValue(64);
+
     m_redThreshold->blockSignals(false); 
-    m_coloringButton->blockSignals(false);       
+    m_HSSelector->blockSignals(false);       
+    m_VSelector->blockSignals(false);
+    m_taintLevel->blockSignals(false);        
 } 
 
 void ImageEffect_RedEye::slotEffect()
@@ -323,8 +370,12 @@
     Digikam::DImg newSelection = selection.copy();
 
     bool aggressive = (m_redThreshold->currentItem() == Mild) ? false : true;
-    QColor coloring = m_coloringButton->color();
 
+    int hue = m_HSSelector->xValue();
+    int sat = m_HSSelector->yValue();
+    int val = m_VSelector->value();
+    QColor coloring(hue, sat, val, QColor::Hsv);
+
     struct channel
     {
         float red_gain;
@@ -347,7 +398,7 @@
     blue_chan.blue_gain   = 1.0;
 
     float red_norm, green_norm, blue_norm;
-    int   level = 64;
+    int   level = m_taintLevel->value();
 
     red_norm   = 1.0 / (red_chan.red_gain   + red_chan.green_gain   + red_chan.blue_gain);
     green_norm = 1.0 / (green_chan.red_gain + green_chan.green_gain + green_chan.blue_gain);
--- trunk/extragear/graphics/digikam/imageplugins/imageeffect_redeye.h #640186:640187
@@ -1,7 +1,7 @@
 /* ============================================================
- * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Authors: Renchi Raju <renchi@pooh.tam.uiuc.edu>
  *         Gilles Caulier <caulier dot gilles at gmail dot com>
- * Date  : 2004-06-06
+ * Date   : 2004-06-06
  * Description : Red eyes correction tool for image editor
  *
  * Copyright 2004-2005 by Renchi Raju, Gilles Caulier
@@ -34,7 +34,9 @@
 class QComboBox;
 class QHButtonGroup;
 
-class KColorButton;
+class KHSSelector;
+class KValueSelector;
+class KIntNumInput;
 
 namespace Digikam
 {
@@ -83,7 +85,8 @@
     void slotEffect();
     void slotChannelChanged(int channel);
     void slotScaleChanged(int scale);
-    void slotColorSelectedFromTarget( const Digikam::DColor &color );
+    void slotColorSelectedFromTarget(const Digikam::DColor &color);
+    void slotHSChanged(int h, int s);
 
 private:
 
@@ -122,11 +125,10 @@
     
     QHButtonGroup                *m_scaleBG;  
 
-/*    KIntNumInput                 *m_bInput;
-    KIntNumInput                 *m_cInput;
-    KDoubleNumInput              *m_gInput;*/
+    KIntNumInput                 *m_taintLevel;
 
-    KColorButton                 *m_coloringButton;
+    KHSSelector                  *m_HSSelector;
+    KValueSelector               *m_VSelector;
     
     Digikam::ImageWidget         *m_previewWidget;
 
Comment 21 caulier.gilles 2007-03-07 12:12:31 UTC
SVN commit 640215 by cgilles:

digikam from trunk : "Et voilà..." The new digiKam 0.9.2 Red Eyes correction tool is complete and ready to use. With this commit, There is a new slider to set the Red Color Threshold adjustment.

The screenshot is updated :

http://digikam3rdparty.free.fr/Screenshots/newredeyecorrectiontool.png

CCBUGS: 142443


 M  +57 -29    imageeffect_redeye.cpp  
 M  +10 -3     imageeffect_redeye.h  


--- trunk/extragear/graphics/digikam/imageplugins/imageeffect_redeye.cpp #640214:640215
@@ -1,6 +1,6 @@
 /* ============================================================
  * Authors: Renchi Raju <renchi@pooh.tam.uiuc.edu>
- *         Gilles Caulier <caulier dot gilles at gmail dot com>
+ *          Gilles Caulier <caulier dot gilles at gmail dot com>
  * Date   : 2004-06-06
  * Description : Red eyes correction tool for image editor
  *
@@ -33,6 +33,7 @@
 #include <qlabel.h>
 #include <qpushbutton.h>
 #include <qcombobox.h>
+#include <qcheckbox.h>
 #include <qwhatsthis.h>
 #include <qtooltip.h>
 
@@ -79,7 +80,7 @@
     // -------------------------------------------------------------
                 
     QWidget *gboxSettings     = new QWidget(plainPage());
-    QGridLayout* gridSettings = new QGridLayout( gboxSettings, 9, 4, marginHint(), spacingHint());
+    QGridLayout* gridSettings = new QGridLayout(gboxSettings, 10, 4, marginHint(), spacingHint());
 
     QLabel *label1 = new QLabel(i18n("Channel:"), gboxSettings);
     label1->setAlignment ( Qt::AlignRight | Qt::AlignVCenter );
@@ -142,34 +143,43 @@
 
     // -------------------------------------------------------------
 
-    QLabel *label2 = new QLabel(i18n("Red Threshold:"), gboxSettings);
-    m_redThreshold = new QComboBox( false, gboxSettings );
-    m_redThreshold->insertItem( i18n("Mild"), Mild );
-    m_redThreshold->insertItem( i18n("Aggressive"), Aggressive );
-    QWhatsThis::add( m_redThreshold, i18n("<p>Set here red color threshold to use:</p>"
-                     "<b>Mild</b>: use this option if other parts of the face are also selected."
-                     "<b>Aggressive</b>: use this option only if eye(s) have been selected exactly."));
-    gridSettings->addMultiCellWidget(label2, 3, 3, 0, 4);
-    gridSettings->addMultiCellWidget(m_redThreshold, 4, 4, 0, 4);
+    m_aggressiveBox = new QCheckBox(gboxSettings);
+    m_aggressiveBox->setText(i18n("Aggressive"));
+    QWhatsThis::add(m_aggressiveBox, i18n("<p>When this option is on, the filter will use an agressive "
+                                          "red color threshold method. To use only if eye have been "
+                                          "selected exactly.</p>"
+                                          "<p>When this option is off, the filter will use an mild red "
+                                          "color threshold method. A slider will be available in this "
+                                          "case to adjust the threshold value.</p>"));
+    gridSettings->addMultiCellWidget(m_aggressiveBox, 3, 3, 0, 4);
 
+    m_thresholdlabel = new QLabel(i18n("Red Threshold:"), gboxSettings);
+    m_redThreshold   = new KIntNumInput(gboxSettings);
+    m_redThreshold->setRange(10, 90, 1, true);
+    m_redThreshold->setValue(20);
+    QWhatsThis::add(m_redThreshold, i18n("<p>Set here the red color threshold value to use. "
+                                         "Low values will select more red color pixels, high values less."));
+    gridSettings->addMultiCellWidget(m_thresholdlabel, 4, 4, 0, 4);
+    gridSettings->addMultiCellWidget(m_redThreshold, 5, 5, 0, 4);
+
     QLabel *label3 = new QLabel(i18n("Coloring Taint:"), gboxSettings);
     m_HSSelector   = new KHSSelector(gboxSettings);
     m_VSelector    = new KValueSelector(gboxSettings);
     m_HSSelector->setMinimumSize(200, 142);
     m_VSelector->setMinimumSize(26, 142);
-    gridSettings->addMultiCellWidget(label3, 5, 5, 0, 4);
-    gridSettings->addMultiCellWidget(m_HSSelector, 6, 6, 0, 3);
-    gridSettings->addMultiCellWidget(m_VSelector, 6, 6, 4, 4);
+    gridSettings->addMultiCellWidget(label3, 6, 6, 0, 4);
+    gridSettings->addMultiCellWidget(m_HSSelector, 7, 7, 0, 3);
+    gridSettings->addMultiCellWidget(m_VSelector, 7, 7, 4, 4);
 
     QLabel *label4 = new QLabel(i18n("Taint Level:"), gboxSettings);
     m_taintLevel   = new KIntNumInput(gboxSettings);
     m_taintLevel->setRange(1, 200, 1, true);
-    m_taintLevel->setValue(0);
+    m_taintLevel->setValue(128);
     QWhatsThis::add( m_taintLevel, i18n("<p>Set here the taint level used to coloring red eye."));
-    gridSettings->addMultiCellWidget(label4, 7, 7, 0, 4);
-    gridSettings->addMultiCellWidget(m_taintLevel, 8, 8, 0, 4);
+    gridSettings->addMultiCellWidget(label4, 8, 8, 0, 4);
+    gridSettings->addMultiCellWidget(m_taintLevel, 9, 9, 0, 4);
 
-    gridSettings->setRowStretch(9, 10);    
+    gridSettings->setRowStretch(10, 10);    
     gridSettings->setColStretch(3, 10);    
     setUserAreaWidget(gboxSettings);
     
@@ -187,8 +197,8 @@
     connect(m_previewWidget, SIGNAL(signalResized()),
             this, SLOT(slotEffect()));    
             
-    connect(m_redThreshold, SIGNAL(activated(int)),
-            this, SLOT(slotEffect()));   
+    connect(m_redThreshold, SIGNAL(valueChanged(int)),
+            this, SLOT(slotTimer()));   
 
     connect(m_HSSelector, SIGNAL(valueChanged(int, int)),
             this, SLOT(slotHSChanged(int, int)));
@@ -198,6 +208,9 @@
 
     connect(m_taintLevel, SIGNAL(valueChanged(int)),
             this, SLOT(slotTimer()));  
+
+    connect(m_aggressiveBox, SIGNAL(toggled(bool)),
+            this, SLOT(slotAggressiveToggled(bool)));      
 }
 
 ImageEffect_RedEye::~ImageEffect_RedEye()
@@ -222,6 +235,13 @@
     slotTimer();
 }
 
+void ImageEffect_RedEye::slotAggressiveToggled(bool b)
+{
+    m_thresholdlabel->setEnabled(!b);
+    m_redThreshold->setEnabled(!b);
+    slotEffect();
+}
+
 void ImageEffect_RedEye::slotChannelChanged(int channel)
 {
     switch(channel)
@@ -267,11 +287,14 @@
     config->setGroup("redeye Tool Dialog");
     m_channelCB->setCurrentItem(config->readNumEntry("Histogram Channel", 0)); // Luminosity.
     m_scaleBG->setButton(config->readNumEntry("Histogram Scale", Digikam::HistogramWidget::LogScaleHistogram));
-    m_redThreshold->setCurrentItem(config->readNumEntry("RedThreshold", Mild));
+    m_aggressiveBox->setChecked(config->readBoolEntry("Aggressive", false));
+    m_redThreshold->setValue(config->readNumEntry("RedThreshold", 20));
     m_HSSelector->setXValue(config->readNumEntry("HueColoringTaint", 0));
     m_HSSelector->setYValue(config->readNumEntry("SatColoringTaint", 0));
     m_VSelector->setValue(config->readNumEntry("ValColoringTaint", 0));
-    m_taintLevel->setValue(config->readNumEntry("TaintLevel", 64));
+    m_taintLevel->setValue(config->readNumEntry("TaintLevel", 128));
+    
+    slotAggressiveToggled(m_aggressiveBox->isChecked());
     slotHSChanged(m_HSSelector->xValue(), m_HSSelector->yValue());
     slotChannelChanged(m_channelCB->currentItem());
     slotScaleChanged(m_scaleBG->selectedId());
@@ -283,7 +306,8 @@
     config->setGroup("redeye Tool Dialog");
     config->writeEntry("Histogram Channel", m_channelCB->currentItem());
     config->writeEntry("Histogram Scale", m_scaleBG->selectedId());
-    config->writeEntry("RedThreshold", m_redThreshold->currentItem());
+    config->writeEntry("Aggressive", m_aggressiveBox->isChecked());
+    config->writeEntry("RedThreshold", m_redThreshold->value());
     config->writeEntry("HueColoringTaint", m_HSSelector->xValue());
     config->writeEntry("SatColoringTaint", m_HSSelector->yValue());
     config->writeEntry("ValColoringTaint", m_VSelector->value());
@@ -293,20 +317,23 @@
 
 void ImageEffect_RedEye::resetValues()
 {
+    m_aggressiveBox->blockSignals(true);   
     m_redThreshold->blockSignals(true);	
     m_HSSelector->blockSignals(true);       
     m_VSelector->blockSignals(true);   
     m_taintLevel->blockSignals(true);   
 
-    m_redThreshold->setCurrentItem(Mild);
+    m_aggressiveBox->setChecked(false);
+    m_redThreshold->setValue(20);
 
     // Black color by default
     m_HSSelector->setXValue(0);
     m_HSSelector->setYValue(0);
     m_VSelector->setValue(0);
 
-    m_taintLevel->setValue(64);
+    m_taintLevel->setValue(128);
 
+    m_aggressiveBox->blockSignals(false);   
     m_redThreshold->blockSignals(false); 
     m_HSSelector->blockSignals(false);       
     m_VSelector->blockSignals(false);
@@ -369,7 +396,8 @@
 {
     Digikam::DImg newSelection = selection.copy();
 
-    bool aggressive = (m_redThreshold->currentItem() == Mild) ? false : true;
+    bool  aggressive   = m_aggressiveBox->isChecked();
+    float redThreshold = m_redThreshold->value()/10.0;
 
     int hue = m_HSSelector->xValue();
     int sat = m_HSSelector->yValue();
@@ -398,7 +426,7 @@
     blue_chan.blue_gain   = 1.0;
 
     float red_norm, green_norm, blue_norm;
-    int   level = m_taintLevel->value();
+    int   level = 201 - m_taintLevel->value();
 
     red_norm   = 1.0 / (red_chan.red_gain   + red_chan.green_gain   + red_chan.blue_gain);
     green_norm = 1.0 / (green_chan.red_gain + green_chan.green_gain + green_chan.blue_gain);
@@ -421,7 +449,7 @@
             r = ptr[2];
             a = ptr[3];
 
-            if ( aggressive || r >= ( 2 * g) )
+            if ( aggressive || r >= ( redThreshold * g) )
             {
                 r1 = QMIN(255, (int)(red_norm * (red_chan.red_gain   * r +
                                                  red_chan.green_gain * g +
@@ -458,7 +486,7 @@
             r = ptr[2];
             a = ptr[3];
 
-            if ( aggressive || r >= ( 2 * g) )
+            if ( aggressive || r >= ( redThreshold * g) )
             {
                 r1 = QMIN(65535, (int)(red_norm * 256 * (red_chan.red_gain   * r +
                                                          red_chan.green_gain * g +
--- trunk/extragear/graphics/digikam/imageplugins/imageeffect_redeye.h #640214:640215
@@ -1,6 +1,6 @@
 /* ============================================================
  * Authors: Renchi Raju <renchi@pooh.tam.uiuc.edu>
- *         Gilles Caulier <caulier dot gilles at gmail dot com>
+ *          Gilles Caulier <caulier dot gilles at gmail dot com>
  * Date   : 2004-06-06
  * Description : Red eyes correction tool for image editor
  *
@@ -31,7 +31,9 @@
 
 #include "imagedlgbase.h"
 
+class QLabel;
 class QComboBox;
+class QCheckBox;
 class QHButtonGroup;
 
 class KHSSelector;
@@ -87,6 +89,7 @@
     void slotScaleChanged(int scale);
     void slotColorSelectedFromTarget(const Digikam::DColor &color);
     void slotHSChanged(int h, int s);
+    void slotAggressiveToggled(bool b);
 
 private:
 
@@ -120,12 +123,16 @@
 
     uchar                        *m_destinationPreviewData;
 
+    QLabel                       *m_thresholdlabel;
+
     QComboBox                    *m_channelCB;   
-    QComboBox                    *m_redThreshold; 
-    
+
+    QCheckBox                    *m_aggressiveBox;    
+
     QHButtonGroup                *m_scaleBG;  
 
     KIntNumInput                 *m_taintLevel;
+    KIntNumInput                 *m_redThreshold; 
 
     KHSSelector                  *m_HSSelector;
     KValueSelector               *m_VSelector;
Comment 22 caulier.gilles 2007-03-07 16:01:01 UTC
SVN commit 640295 by cgilles:

digikam from trunk : Red Eyes correction tool improvements !!!

Gerhard, 

I have found an indeep bug into the Renchi algorithm about Alpha channel rule used to merge red pixels mask and original image. With the new implementation, we can use a gaussian blur effect on the mask to polish the pupil border. With the old implementation, all the mask is blured. With the new, only the pupil pixels are blured.

I have add a new "Smooth" adjsutment witch can control the gaussian blur effect. The result are very nice (:=)))...

Question: I think than the "Agressive" settings is obsolete now. What do you think about ?

The screenshot is updated again :

http://digikam3rdparty.free.fr/Screenshots/newredeyecorrectiontool.png

CCBUGS: 142443


 M  +64 -25    imageeffect_redeye.cpp  
 M  +3 -1      imageeffect_redeye.h  


--- trunk/extragear/graphics/digikam/imageplugins/imageeffect_redeye.cpp #640294:640295
@@ -55,6 +55,7 @@
 #include "colorgradientwidget.h"
 #include "bcgmodifier.h"
 #include "dimg.h"
+#include "dimgimagefilters.h"
 
 // Local includes.
 
@@ -80,7 +81,7 @@
     // -------------------------------------------------------------
                 
     QWidget *gboxSettings     = new QWidget(plainPage());
-    QGridLayout* gridSettings = new QGridLayout(gboxSettings, 10, 4, marginHint(), spacingHint());
+    QGridLayout* gridSettings = new QGridLayout(gboxSettings, 12, 4, marginHint(), spacingHint());
 
     QLabel *label1 = new QLabel(i18n("Channel:"), gboxSettings);
     label1->setAlignment ( Qt::AlignRight | Qt::AlignVCenter );
@@ -146,40 +147,49 @@
     m_aggressiveBox = new QCheckBox(gboxSettings);
     m_aggressiveBox->setText(i18n("Aggressive"));
     QWhatsThis::add(m_aggressiveBox, i18n("<p>When this option is on, the filter will use an agressive "
-                                          "red color threshold method. To use only if eye have been "
+                                          "sensitivity. To use only if eye have been "
                                           "selected exactly.</p>"
-                                          "<p>When this option is off, the filter will use an mild red "
-                                          "color threshold method. A slider will be available in this "
-                                          "case to adjust the threshold value.</p>"));
+                                          "<p>When this option is off, the filter will use an mild " 
+                                          "sensitivity. Use the slider to adjust the threshold of "
+                                          "red color pixels selection.</p>"));
     gridSettings->addMultiCellWidget(m_aggressiveBox, 3, 3, 0, 4);
 
-    m_thresholdlabel = new QLabel(i18n("Red Threshold:"), gboxSettings);
+    m_thresholdLabel = new QLabel(i18n("Sensitivity:"), gboxSettings);
     m_redThreshold   = new KIntNumInput(gboxSettings);
     m_redThreshold->setRange(10, 90, 1, true);
     m_redThreshold->setValue(20);
-    QWhatsThis::add(m_redThreshold, i18n("<p>Set here the red color threshold value to use. "
+    QWhatsThis::add(m_redThreshold, i18n("<p>Set here the red color pixels selection threshold. "
                                          "Low values will select more red color pixels, high values less."));
-    gridSettings->addMultiCellWidget(m_thresholdlabel, 4, 4, 0, 4);
+    gridSettings->addMultiCellWidget(m_thresholdLabel, 4, 4, 0, 4);
     gridSettings->addMultiCellWidget(m_redThreshold, 5, 5, 0, 4);
 
+    m_smoothLabel  = new QLabel(i18n("Smooth:"), gboxSettings);
+    m_smoothLevel = new KIntNumInput(gboxSettings);
+    m_smoothLevel->setRange(0, 10, 1, true);
+    m_smoothLevel->setValue(3);
+    QWhatsThis::add(m_smoothLevel, i18n("<p>Set here the smootness value used to blur red color "
+                                        "pixels selection."));
+    gridSettings->addMultiCellWidget(m_smoothLabel, 6, 6, 0, 4);
+    gridSettings->addMultiCellWidget(m_smoothLevel, 7, 7, 0, 4);
+
     QLabel *label3 = new QLabel(i18n("Coloring Taint:"), gboxSettings);
     m_HSSelector   = new KHSSelector(gboxSettings);
     m_VSelector    = new KValueSelector(gboxSettings);
     m_HSSelector->setMinimumSize(200, 142);
     m_VSelector->setMinimumSize(26, 142);
-    gridSettings->addMultiCellWidget(label3, 6, 6, 0, 4);
-    gridSettings->addMultiCellWidget(m_HSSelector, 7, 7, 0, 3);
-    gridSettings->addMultiCellWidget(m_VSelector, 7, 7, 4, 4);
+    gridSettings->addMultiCellWidget(label3, 8, 8, 0, 4);
+    gridSettings->addMultiCellWidget(m_HSSelector, 9, 9, 0, 3);
+    gridSettings->addMultiCellWidget(m_VSelector, 9, 9, 4, 4);
 
     QLabel *label4 = new QLabel(i18n("Taint Level:"), gboxSettings);
     m_taintLevel   = new KIntNumInput(gboxSettings);
     m_taintLevel->setRange(1, 200, 1, true);
     m_taintLevel->setValue(128);
     QWhatsThis::add( m_taintLevel, i18n("<p>Set here the taint level used to coloring red eye."));
-    gridSettings->addMultiCellWidget(label4, 8, 8, 0, 4);
-    gridSettings->addMultiCellWidget(m_taintLevel, 9, 9, 0, 4);
+    gridSettings->addMultiCellWidget(label4, 10, 10, 0, 4);
+    gridSettings->addMultiCellWidget(m_taintLevel, 11, 11, 0, 4);
 
-    gridSettings->setRowStretch(10, 10);    
+    gridSettings->setRowStretch(12, 10);    
     gridSettings->setColStretch(3, 10);    
     setUserAreaWidget(gboxSettings);
     
@@ -200,6 +210,9 @@
     connect(m_redThreshold, SIGNAL(valueChanged(int)),
             this, SLOT(slotTimer()));   
 
+    connect(m_smoothLevel, SIGNAL(valueChanged(int)),
+            this, SLOT(slotTimer()));   
+
     connect(m_HSSelector, SIGNAL(valueChanged(int, int)),
             this, SLOT(slotHSChanged(int, int)));
 
@@ -237,8 +250,10 @@
 
 void ImageEffect_RedEye::slotAggressiveToggled(bool b)
 {
-    m_thresholdlabel->setEnabled(!b);
+    m_thresholdLabel->setEnabled(!b);
     m_redThreshold->setEnabled(!b);
+    m_smoothLabel->setEnabled(!b);
+    m_smoothLevel->setEnabled(!b);
     slotEffect();
 }
 
@@ -289,6 +304,7 @@
     m_scaleBG->setButton(config->readNumEntry("Histogram Scale", Digikam::HistogramWidget::LogScaleHistogram));
     m_aggressiveBox->setChecked(config->readBoolEntry("Aggressive", false));
     m_redThreshold->setValue(config->readNumEntry("RedThreshold", 20));
+    m_smoothLevel->setValue(config->readNumEntry("SmoothLevel", 3));
     m_HSSelector->setXValue(config->readNumEntry("HueColoringTaint", 0));
     m_HSSelector->setYValue(config->readNumEntry("SatColoringTaint", 0));
     m_VSelector->setValue(config->readNumEntry("ValColoringTaint", 0));
@@ -308,6 +324,7 @@
     config->writeEntry("Histogram Scale", m_scaleBG->selectedId());
     config->writeEntry("Aggressive", m_aggressiveBox->isChecked());
     config->writeEntry("RedThreshold", m_redThreshold->value());
+    config->writeEntry("SmoothLevel", m_smoothLevel->value());
     config->writeEntry("HueColoringTaint", m_HSSelector->xValue());
     config->writeEntry("SatColoringTaint", m_HSSelector->yValue());
     config->writeEntry("ValColoringTaint", m_VSelector->value());
@@ -325,6 +342,7 @@
 
     m_aggressiveBox->setChecked(false);
     m_redThreshold->setValue(20);
+    m_smoothLevel->setValue(3);
 
     // Black color by default
     m_HSSelector->setXValue(0);
@@ -394,8 +412,11 @@
 
 void ImageEffect_RedEye::redEyeFilter(Digikam::DImg& selection)
 {
-    Digikam::DImg newSelection = selection.copy();
+    Digikam::DImg mask(selection.width(), selection.height(), selection.sixteenBit(), true, 
+                       selection.bits(), true);
 
+    selection = mask.copy();
+
     bool  aggressive   = m_aggressiveBox->isChecked();
     float redThreshold = m_redThreshold->value()/10.0;
 
@@ -439,8 +460,8 @@
     if (!selection.sixteenBit())         // 8 bits image.
     {
         uchar* ptr  = selection.bits();
-        uchar* nptr = newSelection.bits();
-        uchar  r, g, b, a, r1, g1, b1;
+        uchar* nptr = mask.bits();
+        uchar  r, g, b, a, r1, g1, b1, a1;
 
         for (uint i = 0 ; i < selection.width() * selection.height() ; i++) 
         {
@@ -463,12 +484,16 @@
                                                   blue_chan.green_gain * g +
                                                   blue_chan.blue_gain  * b)));
 
+                a1 = QMIN( (int)((r-g) / 150.0 * 255.0), 255);
                 nptr[0] = b1;
                 nptr[1] = g1;
                 nptr[2] = r1;
-                nptr[3] = QMIN( (int)((r-g) / 150.0 * 255.0), 255);
+                nptr[3] = a1;
             }
 
+            ptr[3]  = nptr[3];
+            nptr[3] = 255-ptr[3];
+
             ptr += 4;
             nptr+= 4;
         }
@@ -476,8 +501,8 @@
     else                                 // 16 bits image.
     {
         unsigned short* ptr  = (unsigned short*)selection.bits();
-        unsigned short* nptr = (unsigned short*)newSelection.bits();
-        unsigned short  r, g, b, a, r1, g1, b1;
+        unsigned short* nptr = (unsigned short*)mask.bits();
+        unsigned short  r, g, b, a, r1, g1, b1, a1;
 
         for (uint i = 0 ; i < selection.width() * selection.height() ; i++) 
         {
@@ -500,21 +525,35 @@
                                                           blue_chan.green_gain * g +
                                                           blue_chan.blue_gain  * b)));
 
+                a1 = QMIN( (int)((r-g) / 38400.0 * 65535.0), 65535);
+        
                 nptr[0] = b1;
                 nptr[1] = g1;
                 nptr[2] = r1;
-                nptr[3] = QMIN( (int)((r-g) / 38400.0 * 65535.0), 65535);
+                nptr[3] = a1;
             }
 
+            ptr[3]  = nptr[3];
+            nptr[3] = 65535-ptr[3];
+
             ptr += 4;
             nptr+= 4;
         }
     }
 
-    // - Perform pixels blending using alpha channel to blur a little the result.
+    if (!aggressive)
+    {
+        Digikam::DImgImageFilters filter;
+        filter.gaussianBlurImage(mask.bits(), mask.width(), mask.height(), 
+                                 mask.sixteenBit(), m_smoothLevel->value());
+    }
 
-    selection.bitBlend_RGBA2RGB(newSelection, 0, 0, selection.width(), selection.height());
+    // - Perform pixels blending using alpha channel.
+
+    Digikam::DColorComposer *composer = Digikam::DColorComposer::getComposer(Digikam::DColorComposer::PorterDuffNone);
+    selection.bitBlendImage(composer, &mask, 
+                            0, 0, mask.width(), mask.height(),
+                            0, 0);
 }
 
 }  // NameSpace DigikamImagesPluginCore
-
--- trunk/extragear/graphics/digikam/imageplugins/imageeffect_redeye.h #640294:640295
@@ -123,7 +123,8 @@
 
     uchar                        *m_destinationPreviewData;
 
-    QLabel                       *m_thresholdlabel;
+    QLabel                       *m_thresholdLabel;
+    QLabel                       *m_smoothLabel;
 
     QComboBox                    *m_channelCB;   
 
@@ -133,6 +134,7 @@
 
     KIntNumInput                 *m_taintLevel;
     KIntNumInput                 *m_redThreshold; 
+    KIntNumInput                 *m_smoothLevel;
 
     KHSSelector                  *m_HSSelector;
     KValueSelector               *m_VSelector;
Comment 23 Gerhard Kulzer 2007-03-07 18:57:51 UTC
Am Wednesday 07 March 2007 schrieb Gilles Caulier:

>
> digikam from trunk : Red Eyes correction tool improvements !!!
>
> Gerhard,
>
> I have found an indeep bug into the Renchi algorithm about Alpha channel
> rule used to merge red pixels mask and original image. With the new
> implementation, we can use a gaussian blur effect on the mask to polish the
> pupil border. With the old implementation, all the mask is blured. With the
> new, only the pupil pixels are blured.
>
> I have add a new "Smooth" adjsutment witch can control the gaussian blur
> effect. The result are very nice (:=)))...
>
> Question: I think than the "Agressive" settings is obsolete now. What do
> you think about ?
>
> The screenshot is updated again :
>
> http://digikam3rdparty.free.fr/Screenshots/newredeyecorrectiontool.png
>
> CCBUGS: 142443
>


Gilles, I tried it, and it's better than the one we had. 
I think the blurring could be stronger, say 20, it still shows relatively hard 
edges. I tried it with 20, think it is good.

The aggressive tool can be taken away, I agree.

But the transparency of the blob is too high, it doesn't really cover the red 
eye (or something is not yet functioning right, the zoomed image does not 
correspond to the flattened image).

Gerhard
Comment 24 caulier.gilles 2007-03-08 16:18:57 UTC
SVN commit 640606 by cgilles:

digikam from trunk: Red Eyes correction tool :

- remove obsolete 'Aggressive' options.
- Adapt Gausian blur radius to real image size and not preview.
- Fix 16 bits color depth Taint Levels to right value
- Blur only the pixels extracted from the Red Color using Alpha Channel informations.
- Preformance optimization of algorithm.

CCBUGS: 142443

 M  +111 -103  imageeffect_redeye.cpp  
 M  +0 -4      imageeffect_redeye.h  
Comment 25 Gerhard Kulzer 2007-03-10 12:18:42 UTC
Am Thursday 08 March 2007 schrieb Gilles Caulier:
[bugs.kde.org quoted mail]
Gilles, I try to make sense of the 'Taint Level' parameter in the new and 
wonderful red eye plugin to update the documentation and help strings. But i 
can't (neither by experimenting nor by reading the code). I see what it does 
but can't categorize it. As it is, I think it is too esoteric.
Can you educate me on that one?

Gerhard