diff --git a/rtdata/languages/default b/rtdata/languages/default
index da76c9387..a2acbba04 100644
--- a/rtdata/languages/default
+++ b/rtdata/languages/default
@@ -570,17 +570,13 @@ TP_DIRPYRDENOISE_CHROMA;Chrominance
TP_DIRPYRDENOISE_GAMMA;Gamma
TP_DIRPYRDENOISE_LABEL;Directional pyramid noise reduction
TP_DIRPYRDENOISE_LUMA;Luminance
-TP_DIRPYREQUALIZER_CHROMACOARSEST;chroma coarsest
-TP_DIRPYREQUALIZER_CHROMACONTRAST_MINUS;Contrast-
-TP_DIRPYREQUALIZER_CHROMACONTRAST_PLUS;Contrast+
-TP_DIRPYREQUALIZER_CHROMAFINEST;chroma finest
-TP_DIRPYREQUALIZER_CHROMANEUTRAL;Neutral
-TP_DIRPYREQUALIZER_LUMACOARSEST;luma coarsest
+TP_DIRPYREQUALIZER_LUMACOARSEST;Coarsest
TP_DIRPYREQUALIZER_LUMACONTRAST_MINUS;Contrast-
TP_DIRPYREQUALIZER_LUMACONTRAST_PLUS;Contrast+
-TP_DIRPYREQUALIZER_LUMAFINEST;luma finest
+TP_DIRPYREQUALIZER_LUMAFINEST;Finest
TP_DIRPYREQUALIZER_LUMANEUTRAL;Neutral
TP_DIRPYREQUALIZER_LABEL;Directional pyramid equalizer
+TP_DIRPYREQUALIZER_THRESHOLD;Threshold
TP_DISTORTION_AMOUNT;Amount
TP_DISTORTION_LABEL;Distortion
TP_EQUALIZER_CONTRAST_MINUS;Contrast-
diff --git a/rtengine/CMakeLists.txt b/rtengine/CMakeLists.txt
index 5fcf0f6ba..638b21613 100644
--- a/rtengine/CMakeLists.txt
+++ b/rtengine/CMakeLists.txt
@@ -13,7 +13,7 @@ set (RTENGINESOURCEFILES colortemp.cc curves.cc dcraw.cc iccstore.cc
stdimagesource.cc myfile.cc iccjpeg.c hlmultipliers.cc improccoordinator.cc
processingjob.cc rtthumbnail.cc utils.cc labimage.cc
iplab2rgb.cc ipsharpen.cc iptransform.cc ipresize.cc
- wavelet_dec.cc ipequalizer.cc dirpyrLab_denoise.cc dirpyrLab_equalizer.cc)
+ wavelet_dec.cc ipequalizer.cc dirpyrLab_denoise.cc dirpyrLab_equalizer.cc dirpyr_equalizer.cc)
add_library (rtengine ${RTENGINESOURCEFILES})
#It may be nice to store library version too
diff --git a/rtengine/dirpyr_equalizer.cc b/rtengine/dirpyr_equalizer.cc
new file mode 100644
index 000000000..67ce8f1f0
--- /dev/null
+++ b/rtengine/dirpyr_equalizer.cc
@@ -0,0 +1,286 @@
+/*
+ * This file is part of RawTherapee.
+ *
+ * RawTherapee 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * RawTherapee 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with RawTherapee. If not, see .
+ *
+ * © 2010 Emil Martinec
+ *
+ */
+
+//#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#ifdef _OPENMP
+#include
+#endif
+
+#define SQR(x) ((x)*(x))
+#define CLIPTO(a,b,c) ((a)>(b)?((a)<(c)?(a):(c)):(b))
+#define CLIPC(a) ((a)>-32000?((a)<32000?(a):32000):-32000)
+#define CLIP(a) (CLIPTO(a,0,65535))
+
+
+
+#define DIRWT(i1,j1,i,j) ( domker[(i1-i)/scale+halfwin][(j1-j)/scale+halfwin] * rangefn[abs((int)data_fine[i1][j1]-data_fine[i][j])] )
+
+namespace rtengine {
+
+ static const int maxlevel = 4;
+ static const float noise = 2000;
+ static const float thresh = 1000;
+
+ //sequence of scales
+ static const int scales[8] = {1,2,4,8,16,32,64,128};
+
+ //sequence of scales
+ //static const int scales[8] = {1,2,3,6,15,21,28,36};
+ //scale is spacing of directional averaging weights
+
+
+ void ImProcFunctions :: dirpyr_equalizer(unsigned short ** src, unsigned short ** dst, int srcwidth, int srcheight, const double * mult )
+ {
+ int lastlevel=maxlevel;
+
+ while (fabs(mult[lastlevel-1]-1)<0.001 && lastlevel>0) {
+ lastlevel--;
+ //printf("last level to process %d \n",lastlevel);
+ }
+ if (lastlevel==0) return;
+
+ /*float gam = 2.0;//MIN(3.0, 0.1*fabs(c[4])/3.0+0.001);
+ float gamthresh = 0.03;
+ float gamslope = exp(log((double)gamthresh)/gam)/gamthresh;
+ unsigned short gamcurve[65536];
+ for (int i=0; i<65536; i++) {
+ int g = (int)(CurveFactory::gamma((double)i/65535.0, gam, gamthresh, gamslope, 1.0, 0.0) * 65535.0);
+ //if (i<500) printf("%d %d \n",i,g);
+ gamcurve[i] = CLIP(g);
+ }
+
+
+ //#pragma omp parallel for if (multiThread)
+ for (int i=0; iH; i++) {
+ for (int j=0; jW; j++) {
+ src[i][j] = gamcurve[src[i][j] ];
+ }
+ }*/
+
+ //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ int * rangefn = new int [0x20000];
+
+ int intfactor = 1024;//16384;
+
+
+ //set up range functions
+
+ for (int i=0; i<0x10000; i++) {
+ rangefn[i] = (int)((thresh/((double)(i) + thresh))*intfactor);
+ //rangefn[i] = (int)(exp(-(double)abs(i)/(5*thresh))*(thresh/((double)(i) + thresh))*intfactor);
+ //rangefn[i] = (int)((thresh*thresh/((double)(i)*(double)(i) + thresh*thresh))*intfactor);
+ }
+
+ //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+ int level;
+ int ** buffer;
+
+ unsigned short ** dirpyrlo[maxlevel];
+
+
+ buffer = allocArray (srcwidth, srcheight);
+
+ for (int i=0; i (srcwidth, srcheight);
+
+ dirpyr_channel(src, dirpyrlo[0], srcwidth, srcheight, rangefn, 0, scale, mult );
+
+ level = 1;
+
+ while(level < lastlevel)
+ {
+ scale = scales[level];
+
+ dirpyrlo[level] = allocArray(srcwidth, srcheight);
+
+ dirpyr_channel(dirpyrlo[level-1], dirpyrlo[level], srcwidth, srcheight, rangefn, level, scale, mult );
+
+ level ++;
+ }
+
+ //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ //initiate buffer for final image
+ for(int i = 0; i < srcheight; i++)
+ for(int j = 0; j < srcwidth; j++) {
+
+ //copy pixels
+ buffer[i][j] = dirpyrlo[lastlevel-1][i][j];
+
+ }
+
+ //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+
+ for(int level = lastlevel - 1; level > 0; level--)
+ {
+ idirpyr_eq_channel(dirpyrlo[level], dirpyrlo[level-1], buffer, srcwidth, srcheight, level, mult );
+ }
+
+
+ scale = scales[0];
+
+ idirpyr_eq_channel(dirpyrlo[0], dst, buffer, srcwidth, srcheight, 0, mult );
+
+
+ //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+ /*float igam = 1/gam;
+ float igamthresh = gamthresh*gamslope;
+ float igamslope = 1/gamslope;
+ for (int i=0; i<65536; i++) {
+ int g = (int)(CurveFactory::gamma((float)i/65535.0, igam, igamthresh, igamslope, 1.0, 0.0) * 65535.0);
+ gamcurve[i] = CLIP(g);
+ }*/
+
+
+ for (int i=0; iL[i][j] ];
+
+ }
+
+ //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+ for(int i = 0; i < lastlevel; i++)
+ {
+ freeArray(dirpyrlo[i], srcheight);
+ }
+
+ freeArray(buffer, srcheight);
+
+ delete [] rangefn;
+
+
+ //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ };
+
+ void ImProcFunctions::dirpyr_channel(unsigned short ** data_fine, unsigned short ** data_coarse, int width, int height, int * rangefn, int level, int scale, const double * mult )
+ {
+ //scale is spacing of directional averaging weights
+
+ //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ // calculate weights, compute directionally weighted average
+
+ int halfwin=2;
+ int domker[5][5] = {{1,1,1,1,1},{1,2,2,2,1},{1,2,2,2,1},{1,2,2,2,1},{1,1,1,1,1}};
+
+ //generate domain kernel
+ if (level<2) {
+ halfwin = 1;
+ domker[1][1]=domker[1][2]=domker[2][1]=domker[2][2]=1;
+ }
+
+
+ int scalewin = halfwin*scale;
+
+#ifdef _OPENMP
+#pragma omp parallel for
+#endif
+ for(int i = 0; i < height; i++) {
+ for(int j = 0; j < width; j++)
+ {
+ float val=0;
+ float norm=0;
+
+ for(int inbr=MAX(0,i-scalewin); inbr<=MIN(height-1,i+scalewin); inbr+=scale) {
+ for (int jnbr=MAX(0,j-scalewin); jnbr<=MIN(width-1,j+scalewin); jnbr+=scale) {
+ float dirwt = DIRWT(inbr, jnbr, i, j);
+ val += dirwt*data_fine[inbr][jnbr];
+ norm += dirwt;
+ }
+ }
+ data_coarse[i][j]=val/norm;//low pass filter
+ }
+ }
+
+
+
+
+ };
+
+ //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ void ImProcFunctions::idirpyr_eq_channel(unsigned short ** data_coarse, unsigned short ** data_fine, int ** buffer, int width, int height, int level, const double * mult )
+ {
+ int hipass;
+
+ float noisehi = 1.33*noise*mult[4]/pow(3,level), noiselo = 0.66*noise*mult[4]/pow(3,level);
+ float * irangefn = new float [0x20000];
+
+ for (int i=0; i<0x20000; i++) {
+ if (abs(i-0x10000)>noisehi || mult[level]<1.0) {
+ irangefn[i] = mult[level] ;
+ } else {
+ if (abs(i-0x10000)dirpyrequalizer.enabled && lab->W>=8 && lab->H>=8) {
- dirpyrLab_equalizer(lab, lab, params->dirpyrequalizer.mult);
+ //dirpyrLab_equalizer(lab, lab, params->dirpyrequalizer.mult);
+ dirpyr_equalizer(lab->L, lab->L, lab->W, lab->H, params->dirpyrequalizer.mult);
+
}
}
diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h
index bfbdb98f0..d065cfac3 100644
--- a/rtengine/improcfun.h
+++ b/rtengine/improcfun.h
@@ -104,6 +104,10 @@ class ImProcFunctions {
void dirpyr_eq(LabImage* data_coarse, LabImage* data_fine, int * rangefn, int level, int pitch, int scale, const double * mult );
void idirpyr_eq(LabImage* data_coarse, LabImage* data_fine, int *** buffer, int * irangefn, int level, int pitch, int scale, const double * mult );
+ void dirpyr_equalizer(unsigned short ** src, unsigned short ** dst, int srcwidth, int srcheight, const double * mult );//Emil's directional pyramid equalizer
+ void dirpyr_channel(unsigned short ** data_fine, unsigned short ** data_coarse, int width, int height, int * rangefn, int level, int scale, const double * mult );
+ void idirpyr_eq_channel(unsigned short ** data_coarse, unsigned short ** data_fine, int ** buffer, int width, int height, int level, const double * mult );
+
Image8* lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch, Glib::ustring profile);
Image16* lab2rgb16 (LabImage* lab, int cx, int cy, int cw, int ch, Glib::ustring profile);
diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc
index 449494c49..62c51d30c 100644
--- a/rtengine/procparams.cc
+++ b/rtengine/procparams.cc
@@ -173,11 +173,12 @@ void ProcParams::setDefaults () {
equalizer.c[i] = 0;
}
dirpyrequalizer.enabled = false;
- for(int i = 0; i < 8; i ++)
+ for(int i = 0; i < 4; i ++)
{
dirpyrequalizer.mult[i] = 1.0;
}
-
+ dirpyrequalizer.mult[4] = 0.0;
+
exif.clear ();
iptc.clear ();
diff --git a/rtgui/dirpyrequalizer.cc b/rtgui/dirpyrequalizer.cc
index 3cad8853b..06630b951 100644
--- a/rtgui/dirpyrequalizer.cc
+++ b/rtgui/dirpyrequalizer.cc
@@ -60,56 +60,24 @@ DirPyrEqualizer::DirPyrEqualizer () : ToolPanel() {
ss << " (" << M("TP_DIRPYREQUALIZER_LUMAFINEST") << ")";
if(i == 3)
ss << " (" << M("TP_DIRPYREQUALIZER_LUMACOARSEST") << ")";
-
- multiplier[i] = new Adjuster (ss.str(), 0, 4, 0.01, 1.0);
+ multiplier[i] = new Adjuster (ss.str(), 0, 4, 0.01, 1.0);
multiplier[i]->setAdjusterListener(this);
pack_start(*multiplier[i]);
}
-
- show_all_children ();
-
- //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Gtk::HSeparator *separator3 = Gtk::manage (new Gtk::HSeparator());
pack_start(*separator3, Gtk::PACK_SHRINK, 2);
-
- Gtk::HBox * buttonBox2 = Gtk::manage (new Gtk::HBox());
- pack_start(*buttonBox2, Gtk::PACK_SHRINK, 2);
- Gtk::Button * chromacontrastMinusButton = Gtk::manage (new Gtk::Button(M("TP_DIRPYREQUALIZER_CHROMACONTRAST_MINUS")));
- buttonBox2->pack_start(*chromacontrastMinusButton, Gtk::PACK_SHRINK, 2);
- chromacontrastMinusPressedConn = chromacontrastMinusButton->signal_pressed().connect( sigc::mem_fun(*this, &DirPyrEqualizer::chromacontrastMinusPressed));
-
- Gtk::Button * chromaneutralButton = Gtk::manage (new Gtk::Button(M("TP_DIRPYREQUALIZER_CHROMANEUTRAL")));
- buttonBox2->pack_start(*chromaneutralButton, Gtk::PACK_SHRINK, 2);
- chromaneutralPressedConn = chromaneutralButton->signal_pressed().connect( sigc::mem_fun(*this, &DirPyrEqualizer::chromaneutralPressed));
-
- Gtk::Button * chromacontrastPlusButton = Gtk::manage (new Gtk::Button(M("TP_DIRPYREQUALIZER_CHROMACONTRAST_PLUS")));
- buttonBox2->pack_start(*chromacontrastPlusButton, Gtk::PACK_SHRINK, 2);
- chromacontrastPlusPressedConn = chromacontrastPlusButton->signal_pressed().connect( sigc::mem_fun(*this, &DirPyrEqualizer::chromacontrastPlusPressed));
-
- buttonBox2->show_all_children();
-
- Gtk::HSeparator *separator4 = Gtk::manage (new Gtk::HSeparator());
- pack_start(*separator4, Gtk::PACK_SHRINK, 2);
-
- for(int i = 0; i < 4; i++)
- {
- std::stringstream ss;
- ss << i;
- if(i == 0)
- ss << " (" << M("TP_DIRPYREQUALIZER_CHROMAFINEST") << ")";
- if(i == 3)
- ss << " (" << M("TP_DIRPYREQUALIZER_CHROMACOARSEST") << ")";
-
- multiplier[i+4] = new Adjuster (ss.str(), 0, 4, 0.01, 1.0);
- multiplier[i+4]->setAdjusterListener(this);
- pack_start(*multiplier[i+4]);
- }
+ std::stringstream ss;
+ ss << M("TP_DIRPYREQUALIZER_THRESHOLD") ;
+ multiplier[4] = new Adjuster (ss.str(), 0, 1, 0.01, 0.0);
+ multiplier[4]->setAdjusterListener(this);
+ pack_start(*multiplier[4]);
+
show_all_children ();
-
+ //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
}
DirPyrEqualizer::~DirPyrEqualizer () {
@@ -124,7 +92,7 @@ void DirPyrEqualizer::read (const ProcParams* pp, const ParamsEdited* pedited) {
enabled->set_inconsistent (!pedited->dirpyrequalizer.enabled);
- for(int i = 0; i < 8; i++) {
+ for(int i = 0; i < 5; i++) {
multiplier[i]->setEditedState (pedited->dirpyrequalizer.mult[i] ? Edited : UnEdited);
}
}
@@ -134,7 +102,7 @@ void DirPyrEqualizer::read (const ProcParams* pp, const ParamsEdited* pedited) {
enaConn.block (false);
lastEnabled = pp->dirpyrequalizer.enabled;
- for (int i = 0; i < 8; i++) {
+ for (int i = 0; i < 5; i++) {
multiplier[i]->setValue(pp->dirpyrequalizer.mult[i]);
}
@@ -145,7 +113,7 @@ void DirPyrEqualizer::write (ProcParams* pp, ParamsEdited* pedited) {
pp->dirpyrequalizer.enabled = enabled->get_active ();
- for (int i = 0; i < 8; i++) {
+ for (int i = 0; i < 5; i++) {
pp->dirpyrequalizer.mult[i] = multiplier[i]->getValue();
}
@@ -153,7 +121,7 @@ void DirPyrEqualizer::write (ProcParams* pp, ParamsEdited* pedited) {
pedited->dirpyrequalizer.enabled = !enabled->get_inconsistent();
- for(int i = 0; i < 8; i++) {
+ for(int i = 0; i < 5; i++) {
pedited->dirpyrequalizer.mult[i] = multiplier[i]->getEditedState();
}
}
@@ -161,17 +129,17 @@ void DirPyrEqualizer::write (ProcParams* pp, ParamsEdited* pedited) {
void DirPyrEqualizer::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) {
- for (int i = 0; i < 8; i++) {
+ for (int i = 0; i < 5; i++) {
multiplier[i]->setDefault(defParams->dirpyrequalizer.mult[i]);
}
if (pedited) {
- for (int i = 0; i < 8; i++) {
+ for (int i = 0; i < 5; i++) {
multiplier[i]->setDefaultEditedState(pedited->dirpyrequalizer.mult[i] ? Edited : UnEdited);
}
}
else {
- for (int i = 0; i < 8; i++) {
+ for (int i = 0; i < 5; i++) {
multiplier[i]->setDefaultEditedState(Irrelevant);
}
}
@@ -181,7 +149,7 @@ void DirPyrEqualizer::setBatchMode (bool batchMode) {
ToolPanel::setBatchMode (batchMode);
- for (int i = 0; i < 8; i++) {
+ for (int i = 0; i < 5; i++) {
multiplier[i]->showEditedCB();
}
}
@@ -192,7 +160,7 @@ void DirPyrEqualizer::adjusterChanged (Adjuster* a, double newval) {
std::stringstream ss;
ss << "(";
int i;
- for (i = 0; i < 8; i++) {
+ for (i = 0; i < 5; i++) {
if (i > 0) {
ss << ", ";
}
@@ -235,14 +203,6 @@ void DirPyrEqualizer::lumaneutralPressed () {
}
}
-void DirPyrEqualizer::chromaneutralPressed () {
-
- for (int i = 4; i < 8; i++) {
- multiplier[i]->setValue(1.0);
- adjusterChanged(multiplier[i], 1.0);
- }
-}
-
void DirPyrEqualizer::lumacontrastPlusPressed () {
@@ -253,14 +213,6 @@ void DirPyrEqualizer::lumacontrastPlusPressed () {
}
}
-void DirPyrEqualizer::chromacontrastPlusPressed () {
-
- for (int i = 4; i < 8; i++) {
- float inc = 0.05 * (8 - i);
- multiplier[i]->setValue(multiplier[i]->getValue() + inc);
- adjusterChanged(multiplier[i], multiplier[i]->getValue());
- }
-}
void DirPyrEqualizer::lumacontrastMinusPressed () {
@@ -271,11 +223,4 @@ void DirPyrEqualizer::lumacontrastMinusPressed () {
}
}
-void DirPyrEqualizer::chromacontrastMinusPressed () {
-
- for (int i = 4; i < 8; i++) {
- float inc = -0.05 * (8 - i);
- multiplier[i]->setValue(multiplier[i]->getValue() + inc);
- adjusterChanged(multiplier[i], multiplier[i]->getValue());
- }
-}
+
diff --git a/rtgui/dirpyrequalizer.h b/rtgui/dirpyrequalizer.h
index ba7976a96..ddad93034 100644
--- a/rtgui/dirpyrequalizer.h
+++ b/rtgui/dirpyrequalizer.h
@@ -30,15 +30,12 @@ class DirPyrEqualizer : public Gtk::VBox, public AdjusterListener, public ToolPa
protected:
Gtk::CheckButton * enabled;
- Adjuster* multiplier[8];
+ Adjuster* multiplier[5];
sigc::connection enaConn;
sigc::connection lumaneutralPressedConn;
sigc::connection lumacontrastPlusPressedConn;
sigc::connection lumacontrastMinusPressedConn;
- sigc::connection chromaneutralPressedConn;
- sigc::connection chromacontrastPlusPressedConn;
- sigc::connection chromacontrastMinusPressedConn;
bool lastEnabled;
@@ -57,9 +54,6 @@ public:
void lumaneutralPressed ();
void lumacontrastPlusPressed ();
void lumacontrastMinusPressed ();
- void chromaneutralPressed ();
- void chromacontrastPlusPressed ();
- void chromacontrastMinusPressed ();
};
#endif