Author: post
Date: 2009-11-24 21:08:56 +0100 (Tue, 24 Nov 2009)
New Revision: 2760
Modified:
trunk/plugins/dcp/dcp.c
Log:
DCP: Use Exposure ramp for exposure compensation.
Modified: trunk/plugins/dcp/dcp.c
===================================================================
--- trunk/plugins/dcp/dcp.c 2009-11-24 16:23:18 UTC (rev 2759)
+++ trunk/plugins/dcp/dcp.c 2009-11-24 20:08:56 UTC (rev 2760)
@@ -89,7 +89,12 @@
RS_VECTOR3 camera_white;
RS_MATRIX3 camera_to_prophoto;
-
+
+ gfloat exposure_slope;
+ gfloat exposure_black;
+ gfloat exposure_radius;
+ gfloat exposure_qscale;
+
#if defined (__SSE2__)
PrecalcHSM huesatmap_precalc;
PrecalcHSM looktable_precalc;
@@ -281,6 +286,30 @@
}
static void
+init_exposure(RSDcp *dcp)
+{
+ /* Adobe applies negative exposure to the tone curve instead */
+
+ /* Todo: Maybe enable shadow (black point) adjustment. */
+ gfloat shadow = 5.0;
+ gfloat minBlack = shadow * 0.001f;
+ gfloat white = 1.0 / pow (2.0, dcp->exposure);
+ dcp->exposure_black = 0;
+
+ dcp->exposure_slope = 1.0 / (white - dcp->exposure_black);
+ const gfloat kMaxCurveX = 0.5;
+ const gfloat kMaxCurveY = 1.0 / 16.0;
+
+ dcp->exposure_radius = MIN (kMaxCurveX * minBlack,
+ kMaxCurveY /
dcp->exposure_slope);
+
+ if (dcp->exposure_radius > 0.0)
+ dcp->exposure_qscale = dcp->exposure_slope / (4.0 *
dcp->exposure_radius);
+ else
+ dcp->exposure_qscale = 0.0;
+}
+
+static void
get_property(GObject *object, guint property_id, GValue *value, GParamSpec
*pspec)
{
// RSDcp *dcp = RS_DCP(object);
@@ -375,6 +404,8 @@
else
tmp = g_object_ref(output);
+ init_exposure(dcp);
+
guint i, y_offset, y_per_thread, threaded_h;
const guint threads = rs_get_number_of_processor_cores();
ThreadInfo *t = g_new(ThreadInfo, threads);
@@ -475,6 +506,20 @@
}
}
+inline gfloat
+exposure_ramp (RSDcp *dcp, gfloat x)
+{
+ if (x <= dcp->exposure_black - dcp->exposure_radius)
+ return 0.0;
+
+ if (x >= dcp->exposure_black + dcp->exposure_radius)
+ return MIN((x - dcp->exposure_black) * dcp->exposure_slope,
1.0);
+
+ gfloat y = x - (dcp->exposure_black - dcp->exposure_radius);
+
+ return dcp->exposure_qscale * y * y;
+}
+
#if defined (__SSE2__)
static gfloat _zero_ps[4] __attribute__ ((aligned (16))) = {0.0f, 0.0f, 0.0f,
0.0f};
@@ -1275,11 +1320,20 @@
int xfer[4] __attribute__ ((aligned (16)));
- const gfloat exposure_comp = pow(2.0, dcp->exposure);
- __m128 exp = _mm_set_ps(exposure_comp, exposure_comp, exposure_comp,
exposure_comp);
__m128 hue_add = _mm_set_ps(dcp->hue, dcp->hue, dcp->hue, dcp->hue);
__m128 sat = _mm_set_ps(dcp->saturation, dcp->saturation,
dcp->saturation, dcp->saturation);
+ gfloat e = dcp->exposure_black - dcp->exposure_radius;
+ __m128 black_minus_radius = _mm_set_ps(e,e,e,e);
+ e = dcp->exposure_black + dcp->exposure_radius;
+ __m128 black_plus_radius = _mm_set_ps(e,e,e,e);
+ e = dcp->exposure_black;
+ __m128 exposure_black = _mm_set_ps(e,e,e,e);
+ e = dcp->exposure_slope;
+ __m128 exposure_slope = _mm_set_ps(e,e,e,e);
+ e = dcp->exposure_qscale;
+ __m128 exposure_qscale = _mm_set_ps(e,e,e,e);
+
float cam_prof[4*4*3] __attribute__ ((aligned (16)));
for (x = 0; x < 4; x++ ) {
cam_prof[x] = dcp->camera_to_prophoto.coeff[0][0];
@@ -1376,10 +1430,37 @@
r = h; g = s; b = v;
/* Exposure */
- r = _mm_min_ps(max_val, _mm_mul_ps(r, exp));
- g = _mm_min_ps(max_val, _mm_mul_ps(g, exp));
- b = _mm_min_ps(max_val, _mm_mul_ps(b, exp));
+ __m128 y_r = _mm_sub_ps(r, black_minus_radius);
+ __m128 y_g = _mm_sub_ps(g, black_minus_radius);
+ __m128 y_b = _mm_sub_ps(b, black_minus_radius);
+ y_r = _mm_mul_ps(exposure_qscale,_mm_mul_ps(y_r, y_r));
+ y_g = _mm_mul_ps(exposure_qscale,_mm_mul_ps(y_g, y_g));
+ y_b = _mm_mul_ps(exposure_qscale,_mm_mul_ps(y_b, y_b));
+ __m128 y2_r = _mm_mul_ps(exposure_slope, _mm_sub_ps(r,
exposure_black));
+ __m128 y2_g = _mm_mul_ps(exposure_slope, _mm_sub_ps(g,
exposure_black));
+ __m128 y2_b = _mm_mul_ps(exposure_slope, _mm_sub_ps(b,
exposure_black));
+ __m128 r_mask = _mm_cmpgt_ps(r, black_plus_radius);
+ __m128 g_mask = _mm_cmpgt_ps(g, black_plus_radius);
+ __m128 b_mask = _mm_cmpgt_ps(b, black_plus_radius);
+ y_r = _mm_andnot_ps(r_mask, y_r);
+ y_g = _mm_andnot_ps(g_mask, y_g);
+ y_b = _mm_andnot_ps(b_mask, y_b);
+ y_r = _mm_or_ps(y_r, _mm_and_ps(r_mask, y2_r));
+ y_g = _mm_or_ps(y_g, _mm_and_ps(g_mask, y2_g));
+ y_b = _mm_or_ps(y_b, _mm_and_ps(b_mask, y2_b));
+ r_mask = _mm_cmple_ps(r, black_minus_radius);
+ g_mask = _mm_cmple_ps(g, black_minus_radius);
+ b_mask = _mm_cmple_ps(b, black_minus_radius);
+ r = _mm_andnot_ps(r_mask, y_r);
+ g = _mm_andnot_ps(g_mask, y_g);
+ b = _mm_andnot_ps(b_mask, y_b);
+ /* Clamp */
+ max_val = _mm_load_ps(_ones_ps);
+ r = _mm_min_ps(r, max_val);
+ g = _mm_min_ps(g, max_val);
+ b = _mm_min_ps(b, max_val);
+
RGBtoHSV_SSE(&r, &g, &b);
h = r; s = g; v = b;
@@ -1476,8 +1557,6 @@
gfloat r, g, b;
RS_VECTOR3 pix;
- const gfloat exposure_comp = pow(2.0, dcp->exposure);
-
for(y = t->start_y ; y < t->end_y; y++)
{
for(x=t->start_x; x < image->w; x++)
@@ -1519,9 +1598,9 @@
HSVtoRGB(h, s, v, &r, &g, &b);
/* Exposure Compensation */
- r = MIN(r * exposure_comp, 1.0);
- g = MIN(g * exposure_comp, 1.0);
- b = MIN(b * exposure_comp, 1.0);
+ r = exposure_ramp(dcp, r);
+ g = exposure_ramp(dcp, g);
+ b = exposure_ramp(dcp, b);
/* To HSV */
RGBtoHSV(r, g, b, &h, &s, &v);
_______________________________________________
Rawstudio-commit mailing list
[email protected]
http://rawstudio.org/cgi-bin/mailman/listinfo/rawstudio-commit