Author: post
Date: 2009-11-25 19:25:11 +0100 (Wed, 25 Nov 2009)
New Revision: 2761

Modified:
   trunk/plugins/dcp/dcp.c
Log:
DCP: Enable contrast adjustment.

Modified: trunk/plugins/dcp/dcp.c
===================================================================
--- trunk/plugins/dcp/dcp.c     2009-11-24 20:08:56 UTC (rev 2760)
+++ trunk/plugins/dcp/dcp.c     2009-11-25 18:25:11 UTC (rev 2761)
@@ -55,6 +55,7 @@
 
        gfloat exposure;
        gfloat saturation;
+       gfloat contrast;
        gfloat hue;
 
        RS_xy_COORD white_xy;
@@ -200,6 +201,12 @@
                g_object_get(settings, "saturation", &dcp->saturation, NULL);
                changed = TRUE;
        }
+       
+       if (mask & MASK_CONTRAST)
+       {
+               g_object_get(settings, "contrast", &dcp->contrast, NULL);
+               changed = TRUE;
+       }
 
        if (mask & MASK_HUE)
        {
@@ -526,19 +533,27 @@
 static gfloat _ones_ps[4] __attribute__ ((aligned (16))) = {1.0f, 1.0f, 1.0f, 
1.0f};
 static gfloat _two_ps[4] __attribute__ ((aligned (16))) = {2.0f, 2.0f, 2.0f, 
2.0f};
 static gfloat _six_ps[4] __attribute__ ((aligned (16))) = {6.0f-1e-15, 
6.0f-1e-15, 6.0f-1e-15, 6.0f-1e-15};
+static gfloat _very_small_ps[4] __attribute__ ((aligned (16))) = {1e-15, 
1e-15, 1e-15, 1e-15};
 
 static inline void
 RGBtoHSV_SSE(__m128 *c0, __m128 *c1, __m128 *c2)
 {
 
        __m128 zero_ps = _mm_load_ps(_zero_ps);
+       __m128 small_ps = _mm_load_ps(_very_small_ps);
        __m128 ones_ps = _mm_load_ps(_ones_ps);
+       
        // Any number > 1
        __m128 add_v = _mm_load_ps(_two_ps);
 
        __m128 r = *c0;
        __m128 g = *c1;
        __m128 b = *c2;
+       
+       /* Clamp */
+       r = _mm_min_ps(_mm_max_ps(r, small_ps),ones_ps);
+       g =  _mm_min_ps(_mm_max_ps(g, small_ps),ones_ps);
+       b =  _mm_min_ps(_mm_max_ps(b, small_ps),ones_ps);
 
        __m128 h, v;
        v = _mm_max_ps(b,_mm_max_ps(r,g));
@@ -1130,7 +1145,6 @@
 #define DW(A) _mm_castps_si128(A)
 #define PS(A) _mm_castsi128_ps(A)
 
-static gfloat _very_small_ps[4] __attribute__ ((aligned (16))) = {1e-15, 
1e-15, 1e-15, 1e-15};
 static gfloat _16_bit_ps[4] __attribute__ ((aligned (16))) = {65535.0, 
65535.0, 65535.0, 65535.0};
 
 void inline
@@ -1141,7 +1155,15 @@
        __m128 r = *_r;
        __m128 g = *_g;
        __m128 b = *_b;
+       __m128 small_ps = _mm_load_ps(_very_small_ps);
+       __m128 ones_ps = _mm_load_ps(_ones_ps);
        
+       /* Clamp  to avoid lookups out of table */
+       r = _mm_min_ps(_mm_max_ps(r, small_ps),ones_ps);
+       g =  _mm_min_ps(_mm_max_ps(g, small_ps),ones_ps);
+       b =  _mm_min_ps(_mm_max_ps(b, small_ps),ones_ps);
+       
+       /* Find largest and smallest values */
        __m128 lg = _mm_max_ps(b, _mm_max_ps(r, g));
        __m128 sm = _mm_min_ps(b, _mm_min_ps(r, g));
        __m128i lookup_max = _mm_cvtps_epi32(_mm_mul_ps(lg,
@@ -1156,6 +1178,8 @@
        __m128 LG = _mm_set_ps(tone_lut[xfer[3]], tone_lut[xfer[2]], 
tone_lut[xfer[1]], tone_lut[xfer[0]]);
        __m128 SM = _mm_set_ps(tone_lut[xfer[7]], tone_lut[xfer[6]], 
tone_lut[xfer[5]], tone_lut[xfer[4]]);
 
+       /* Create masks for largest, smallest and medium values */
+       /* This is done in integer SSE2, since they have double the throughout 
*/
        __m128i ones = _mm_cmpeq_epi32(DW(r), DW(r));
        __m128i is_r_lg = _mm_cmpeq_epi32(DW(r), DW(lg));
        __m128i is_g_lg = _mm_cmpeq_epi32(DW(g), DW(lg));
@@ -1169,20 +1193,24 @@
        __m128i is_g_md = _mm_xor_si128(ones, _mm_or_si128(is_g_lg, is_g_sm));
        __m128i is_b_md = _mm_xor_si128(ones, _mm_or_si128(is_b_lg, is_b_sm));
 
+       /* Find all medium values based on masks */
        __m128 md = PS(_mm_or_si128(_mm_or_si128(
                                        _mm_and_si128(DW(r), is_r_md), 
                                        _mm_and_si128(DW(g), is_g_md)),
                                        _mm_and_si128(DW(b), is_b_md)));
-       
+
+       /* Calculate tone corrected medium value */
        __m128 p = _mm_rcp_ps(_mm_sub_ps(lg, sm));
        __m128 q = _mm_sub_ps(md, sm);
        __m128 o = _mm_sub_ps(LG, SM);
        __m128 MD = _mm_add_ps(SM, _mm_mul_ps(o, _mm_mul_ps(p, q)));
 
+       /* Inserted here again, to lighten register presssure */
        is_r_lg = _mm_cmpeq_epi32(DW(r), DW(lg));
        is_g_lg = _mm_cmpeq_epi32(DW(g), DW(lg));
        is_b_lg = _mm_cmpeq_epi32(DW(b), DW(lg));
 
+       /* Combine corrected values to output RGB */
        r = PS(_mm_or_si128( _mm_or_si128(
                        _mm_and_si128(DW(LG), is_r_lg),
                        _mm_and_si128(DW(SM), is_r_sm)), 
@@ -1197,6 +1225,7 @@
                        _mm_and_si128(DW(LG), is_b_lg),
                        _mm_and_si128(DW(SM), is_b_sm)), 
                        _mm_and_si128(DW(MD), is_b_md)));
+
        *_r = r;
        *_g = g;
        *_b = b;
@@ -1302,6 +1331,7 @@
        return acc;
 }
 
+static gfloat _half_ps[4] __attribute__ ((aligned (16))) = 
{0.5f,0.5f,0.5f,0.5f};
 static gfloat _rgb_div_ps[4] __attribute__ ((aligned (16))) = {1.0/65535.0, 
1.0/65535.0, 1.0/65535.0, 1.0/65535.0};
 static gint _15_bit_epi32[4] __attribute__ ((aligned (16))) = { 32768, 32768, 
32768, 32768};
 static guint _16_bit_sign[4] __attribute__ ((aligned (16))) = 
{0x80008000,0x80008000,0x80008000,0x80008000};
@@ -1320,6 +1350,7 @@
 
        int xfer[4] __attribute__ ((aligned (16)));
 
+       __m128 contrast = _mm_set_ps(dcp->contrast, dcp->contrast, 
dcp->contrast, dcp->contrast);
        __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);
        
@@ -1395,22 +1426,17 @@
                        g2 = sse_matrix3_mul(&cam_prof[12], r, g, b);
                        b2 = sse_matrix3_mul(&cam_prof[24], r, g, b);
 
-                       /* Set min/max before HSV conversion */
-                       __m128 min_val = _mm_load_ps(_very_small_ps);
-                       __m128 max_val = _mm_load_ps(_ones_ps);
-                       r = _mm_max_ps(_mm_min_ps(r2, max_val), min_val);
-                       g = _mm_max_ps(_mm_min_ps(g2, max_val), min_val);
-                       b = _mm_max_ps(_mm_min_ps(b2, max_val), min_val);
+                       RGBtoHSV_SSE(&r2, &g2, &b2);
+                       h = r2; s = g2; v = b2;
 
-                       RGBtoHSV_SSE(&r, &g, &b);
-                       h = r; s = g; v = b;
-
                        if (dcp->huesatmap)
                        {
                                huesat_map_SSE2(dcp->huesatmap, 
&dcp->huesatmap_precalc, &h, &s, &v);
                        }
 
                        /* Saturation */
+                       __m128 max_val = _mm_load_ps(_ones_ps);
+                       __m128 min_val = _mm_load_ps(_very_small_ps);
                        s = _mm_max_ps(min_val, _mm_min_ps(max_val, 
_mm_mul_ps(s, sat)));
 
                        /* Hue */
@@ -1455,18 +1481,24 @@
                        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);
-                       
+                       /* Contrast in gamma 2.0 */
+                       __m128 half_ps = _mm_load_ps(_half_ps);
+                       min_val = _mm_load_ps(_very_small_ps);
+                       r = _mm_add_ps(_mm_mul_ps(contrast, 
_mm_sub_ps(_mm_sqrt_ps(r), half_ps)), half_ps);
+                       g = _mm_add_ps(_mm_mul_ps(contrast, 
_mm_sub_ps(_mm_sqrt_ps(g), half_ps)), half_ps);
+                       b = _mm_add_ps(_mm_mul_ps(contrast, 
_mm_sub_ps(_mm_sqrt_ps(b), half_ps)), half_ps);
+                       r = _mm_max_ps(r, min_val);
+                       g = _mm_max_ps(g, min_val);
+                       b = _mm_max_ps(b, min_val);
+                       r = _mm_mul_ps(r,r);
+                       g = _mm_mul_ps(g,g);
+                       b = _mm_mul_ps(b,b);
+
+                       /* Convert to HSV */
                        RGBtoHSV_SSE(&r, &g, &b);
                        h = r; s = g; v = b;
 
-
                        /* Convert v to lookup values */
-
                        /* TODO: Use 8 bit fraction as interpolation, for 
interpolating
                         * a more precise lookup using linear interpolation. 
Maybe use less than
                         * 16 bits for lookup for speed, 10 bits with 
interpolation should be enough */
@@ -1602,6 +1634,14 @@
                        g = exposure_ramp(dcp, g);
                        b = exposure_ramp(dcp, b);
                        
+                       /* Contrast in gamma 2.0 */
+                       r = MAX((sqrtf(r) - 0.5) * dcp->contrast + 0.5, 0.0f);
+                       r *= r;
+                       g = MAX((sqrtf(g) - 0.5) * dcp->contrast + 0.5, 0.0f);
+                       g *= g;
+                       b = MAX((sqrtf(b) - 0.5) * dcp->contrast + 0.5, 0.0f);
+                       b *= 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

Reply via email to