Author: post
Date: 2012-06-19 20:04:34 +0200 (Tue, 19 Jun 2012)
New Revision: 4236
Modified:
trunk/plugins/denoise/denoise.c
trunk/plugins/denoise/denoisethread.cpp
trunk/plugins/denoise/floatimageplane.cpp
trunk/plugins/denoise/floatimageplane.h
Log:
Apply limiter to luminance sharpening/denoising. Greatly reduces halos and
lessens sharpening in "flat" areas.
Modified: trunk/plugins/denoise/denoise.c
===================================================================
--- trunk/plugins/denoise/denoise.c 2012-06-19 18:00:28 UTC (rev 4235)
+++ trunk/plugins/denoise/denoise.c 2012-06-19 18:04:34 UTC (rev 4236)
@@ -287,12 +287,13 @@
denoise->info.image = tmp;
denoise->info.sigmaLuma = ((float) denoise->denoise_luma * scale) / 3.0;
denoise->info.sigmaChroma = ((float) denoise->denoise_chroma * scale) /
1.5;
- denoise->info.sharpenLuma = (float) denoise->sharpen / 20.0f;
- denoise->info.sharpenCutoffLuma = 0.05f * scale;
- denoise->info.betaLuma = 1.025;
+ denoise->info.sharpenLuma = 1.5f * (float) denoise->sharpen / 20.0f;
+ denoise->info.sharpenLuma *= fmin(1.0f, 0.25 + ((100.0f -
denoise->denoise_luma) / 100.0f));
+ denoise->info.sharpenCutoffLuma = 0.07f * scale;
+ denoise->info.betaLuma = 1.0 + denoise->info.sigmaLuma * 0.030;
denoise->info.sharpenChroma = 0.0f;
- denoise->info.sharpenMinSigmaLuma = denoise->info.sigmaLuma * 2.0;
- denoise->info.sharpenMaxSigmaLuma = denoise->info.sharpenMinSigmaLuma +
denoise->info.sharpenLuma * 2.0f;
+ denoise->info.sharpenMinSigmaLuma = denoise->info.sigmaLuma * 1.0;
+ denoise->info.sharpenMaxSigmaLuma = denoise->info.sharpenMinSigmaLuma +
denoise->info.sharpenLuma * 3.0f;
denoise->info.redCorrection = 1.0f;
denoise->info.blueCorrection = 1.0f;
Modified: trunk/plugins/denoise/denoisethread.cpp
===================================================================
--- trunk/plugins/denoise/denoisethread.cpp 2012-06-19 18:00:28 UTC (rev
4235)
+++ trunk/plugins/denoise/denoisethread.cpp 2012-06-19 18:04:34 UTC (rev
4236)
@@ -154,7 +154,10 @@
// Currently not used, as no overlapped data is used.
//j->p->window->applySynthesisWindow(j->p->out);
- j->outPlane->applySlice(j->p);
+ if (j->outPlane->plane_id == 0)
+ j->outPlane->applySliceLimited(j->p, input);
+ else
+ j->outPlane->applySlice(j->p);
}
Modified: trunk/plugins/denoise/floatimageplane.cpp
===================================================================
--- trunk/plugins/denoise/floatimageplane.cpp 2012-06-19 18:00:28 UTC (rev
4235)
+++ trunk/plugins/denoise/floatimageplane.cpp 2012-06-19 18:04:34 UTC (rev
4236)
@@ -19,9 +19,14 @@
#include "floatimageplane.h"
#include "fftw3.h"
+#include "math.h" /* min / max */
#include <string.h>
#include <stdlib.h> /* posix_memalign() */
+#ifdef __SSE2__
+#include <emmintrin.h>
+#endif
+
namespace RawStudio {
namespace FFTFilter {
@@ -180,7 +185,113 @@
}
}
+#ifdef __SSE2__
+static inline void findminmax_five_five(float* start, float min_max_out[2],
int pitch)
+{
+ __m128 a = _mm_loadu_ps(&start[0]);
+ __m128 b = _mm_loadu_ps(&start[0+pitch]);
+ __m128 c = _mm_loadu_ps(&start[0+pitch*2]);
+ __m128 d = _mm_loadu_ps(&start[0+pitch*3]);
+ __m128 e = _mm_loadu_ps(&start[0+pitch*4]);
+ __m128 ab_min = _mm_min_ps(a,b);
+ __m128 ab_max = _mm_max_ps(a,b);
+ __m128 cd_min = _mm_min_ps(c,d);
+ __m128 cd_max = _mm_max_ps(c,d);
+ __m128 abe_min = _mm_min_ps(ab_min,e);
+ __m128 abe_max = _mm_max_ps(ab_max,e);
+ __m128 abcde_min = _mm_min_ps(abe_min,cd_min);
+ __m128 abcde_max = _mm_max_ps(abe_max,cd_max);
+ a = _mm_load_ss(&start[4]);
+ b = _mm_load_ss(&start[4+pitch]);
+ c = _mm_load_ss(&start[4+pitch*2]);
+ d = _mm_load_ss(&start[4+pitch*3]);
+ e = _mm_load_ss(&start[4+pitch*4]);
+ ab_min = _mm_min_ss(a,b);
+ ab_max = _mm_max_ss(a,b);
+ cd_min = _mm_min_ss(c,d);
+ cd_max = _mm_max_ss(c,d);
+ abe_min = _mm_min_ss(ab_min,e);
+ abe_max = _mm_max_ss(ab_max,e);
+ abcde_min = _mm_min_ss(abcde_min, _mm_min_ss(abe_min,cd_min));
+ abcde_max = _mm_max_ss(abcde_max, _mm_max_ss(abe_max,cd_max));
+ abcde_min = _mm_min_ps(abcde_min, _mm_movehl_ps(abcde_min, abcde_min));
+ abcde_max = _mm_max_ps(abcde_max, _mm_movehl_ps(abcde_max, abcde_max));
+ abcde_min = _mm_min_ps(abcde_min, _mm_shuffle_ps(abcde_min, abcde_min,
_MM_SHUFFLE(1,1,1,1)));
+ abcde_max = _mm_max_ps(abcde_max, _mm_shuffle_ps(abcde_max, abcde_max,
_MM_SHUFFLE(1,1,1,1)));
+
+ _mm_store_ss(&min_max_out[0], abcde_min);
+ _mm_store_ss(&min_max_out[1], abcde_max);
+}
+
+#else
+static inline void findminmax_five_h(float* start, float min_max_out[2])
+{
+ min_max_out[0] = fmin(start[0], start[1]);
+ min_max_out[1] = fmax(start[0], start[1]);
+ min_max_out[0] = fmin(min_max_out[0], fmin(start[2], start[3]));
+ min_max_out[1] = fmax(min_max_out[1], fmax(start[2], start[3]));
+ min_max_out[0] = fmin(min_max_out[0], start[4]);
+ min_max_out[1] = fmax(min_max_out[1], start[4]);
+}
+#endif
+
+void FloatImagePlane::applySliceLimited( PlanarImageSlice *p, FloatImagePlane
*org_plane ) {
+ int start_y = p->offset_y + p->overlap_y;
+ int start_x = p->offset_x + p->overlap_x;
+ g_assert(start_y >= 0);
+ g_assert(start_x >= 0);
+ g_assert(start_y < h);
+ g_assert(start_x < w);
+
+ if (p->blockSkipped) {
+ FBitBlt((guchar*)getAt(start_x,start_y), pitch*sizeof(float),
+ (const guchar*)p->in->getAt(p->overlap_x,p->overlap_y),
p->in->pitch*sizeof(float),
+ p->in->w*sizeof(float)-p->overlap_x*2*sizeof(float),
p->in->h-p->overlap_y*2);
+ return;
+ }
+
+ float normalization = 1.0f / (float)(p->out->w * p->out->h);
+
+ int end_x = p->offset_x + p->out->w - p->overlap_x;
+ int end_y = p->offset_y + p->out->h - p->overlap_y;
+
+ g_assert(end_y >= 0);
+ g_assert(end_x >= 0);
+ g_assert(end_y < h);
+ g_assert(end_x < w);
+ float min_max[2];
+
+ for (int y = start_y; y < end_y; y++ ) {
+ float* src = p->out->getAt(p->overlap_x,y-start_y+p->overlap_y);
+ float* dst = getAt(start_x, y);
+ for (int x = start_x; x < end_x; x++) {
+#ifdef __SSE2__
+ float* org = org_plane->getAt(x - p->offset_x - 2, y -
p->offset_y - 2);
+ findminmax_five_five(org, min_max, org_plane->pitch);
+ float org_min = min_max[0];
+ float org_max = min_max[1];
+#else
+ const int radius = 2;
+ float org_min = 100000000000.0f;
+ float org_max = -10000000.0f;
+ for (int y2 = y-radius; y2 <= y+radius; y2++) {
+ float* org = org_plane->getAt(x - p->offset_x -
radius, y2 - p->offset_y);
+ findminmax_five_h(org, min_max);
+ org_min = fmin(org_min, min_max[0]);
+ org_max = fmax(org_max, min_max[1]);
+ }
+#endif
+ float dev = org_max - org_min;
+ org_min -= dev * 0.1; // 10% Undershoot allowed
+ org_max += dev * 0.1; // 10% Overshoot allowed
+ float new_value = normalization * (*src++);
+ *dst++ = fmax(org_min, fmin(new_value, org_max));
+ }
+ }
+}
+
+
void FloatImagePlane::blitOnto( FloatImagePlane *dst )
{
g_assert(dst->w == w);
Modified: trunk/plugins/denoise/floatimageplane.h
===================================================================
--- trunk/plugins/denoise/floatimageplane.h 2012-06-19 18:00:28 UTC (rev
4235)
+++ trunk/plugins/denoise/floatimageplane.h 2012-06-19 18:04:34 UTC (rev
4236)
@@ -46,6 +46,7 @@
void multiply(float mul);
void addJobs(JobQueue *jobs, int bw, int bh, int ox, int oy, FloatImagePlane
*outPlane);
void applySlice(PlanarImageSlice *p);
+ void applySliceLimited( PlanarImageSlice *p, FloatImagePlane *org_plane );
const int w;
const int h;
gfloat* data;
_______________________________________________
Rawstudio-commit mailing list
[email protected]
http://rawstudio.org/cgi-bin/mailman/listinfo/rawstudio-commit