# HG changeset patch
# User Edouard Gomez <[EMAIL PROTECTED]>
# Date 1187904914 -7200
# Node ID c08eac5446299e71a965adf68a0861aa1db56e4b
# Parent  46d39ed470f675b7426169ee931a3c88feafbf96
Use the curve as a luminance curve only

diff --git a/src/rs-color-transform.c b/src/rs-color-transform.c
--- a/src/rs-color-transform.c
+++ b/src/rs-color-transform.c
@@ -25,6 +25,13 @@ static void make_tables(RS_COLOR_TRANSFO
 static void make_tables(RS_COLOR_TRANSFORM *rct);
 static gboolean select_render(RS_COLOR_TRANSFORM *rct);
 
+#define LUM_PRECISION 15
+#define RLUMF ((gint)(0.212671f*(1<<LUM_PRECISION)))
+#define GLUMF ((gint)(0.715160f*(1<<LUM_PRECISION)))
+#define BLUMF ((gint)(0.072169f*(1<<LUM_PRECISION)))
+#define HALFF (1<<(LUM_PRECISION-1))
+#define LUM_FIXED(a) ((guint)((a)*(1<<LUM_PRECISION)))
+
 /* Function pointers - initialized by arch binders */
 COLOR_TRANSFORM(*transform_nocms8);
 COLOR_TRANSFORM(*transform_cms8);
@@ -50,6 +57,7 @@ struct _RS_COLOR_TRANSFORM_PRIVATE {
        gint nknots;
        gfloat *knots;
        gfloat curve_samples[65536];
+       guint luminance[65536];
        void *transform;
 };
 
@@ -308,8 +316,39 @@ make_tables(RS_COLOR_TRANSFORM *rct)
                nd = ((gdouble) n) * rec65535;
                nd = pow(nd, gammavalue);
 
-               if (likely(rct->priv->curve_samples))
-                       nd = (gdouble) rct->priv->curve_samples[((gint) 
(nd*65535.0f))];
+               if (likely(rct->priv->curve_samples)) {
+                       n = (n>0) ? n : 1;
+
+                       /* The idea is to use the curve to boost/dcrease
+                        * luminance only.
+                        * So we have to compute Y, map it to its new value
+                        * and then compute a factor that would keep this
+                        * new luminance if applied to the RGB triplet.
+                        *
+                        * Quite straight forward; let's do it quick...
+                        * Y  = a.R + b.G + c.B
+                        *
+                        * We map Y to Y' according to the curve:
+                        * Y' = curve(Y)
+                        *
+                        * let's compute a real 'd' such that:
+                        * Y' = d.Y
+                        *
+                        * Then we have
+                        * Y' = d.(a.R + b.G + c.B)
+                        * or written a bit differently:
+                        * Y' = a.(d.R) + b.(d.G) + c.(d.B)
+                        *
+                        * So the RGB triplet we are looking for is (d.R, d.G, 
d.B)
+                        *
+                        * The luminance LUT stores curve(Y)/Y as a fixed point
+                        * value so that it becomes very easy to compute 
d.(R,G,B)
+                        * even on SIMD CPUs
+                        *
+                        * NB: luminance curve is applied in linear space before
+                        * any gamma */
+                       rct->priv->luminance[n] = 
LUM_FIXED(rct->priv->curve_samples[n]*65535.f/(float)n);
+               }
 
                nd = nd*contrast+postadd;
 
@@ -901,6 +940,8 @@ COLOR_TRANSFORM(transform_cms_c)
                srcoffset = y * in_rowstride;
                for(x=0 ; x<width ; x++)
                {
+                       guint Y;
+
                        rr = (in[srcoffset+R]*pre_muli[R])>>7;
                        gg = (in[srcoffset+G]*pre_muli[G])>>7;
                        bb = (in[srcoffset+B]*pre_muli[B])>>7;
@@ -915,6 +956,20 @@ COLOR_TRANSFORM(transform_cms_c)
                                + gg*mati.coeff[2][1]
                                + bb*mati.coeff[2][2])>>MATRIX_RESOLUTION;
                        _CLAMP65535_TRIPLET(r,g,b);
+
+                       // Compute luminance
+                       Y = (RLUMF*r + GLUMF*g + BLUMF*b + 
HALFF)>>LUM_PRECISION;
+
+                       // Find the factor to apply to the RGB triplet
+                       Y = rct->priv->luminance[Y];
+
+                       // Multiplythe RGB triplet using fixed point arithmetic
+                       r = (r*Y)>>LUM_PRECISION;
+                       g = (g*Y)>>LUM_PRECISION;
+                       b = (b*Y)>>LUM_PRECISION;
+
+                       _CLAMP65535_TRIPLET(r,g,b);
+
                        buffer[destoffset++] = rct->priv->table16[r];
                        buffer[destoffset++] = rct->priv->table16[g];
                        buffer[destoffset++] = rct->priv->table16[b];
@@ -945,6 +1000,8 @@ COLOR_TRANSFORM(transform_nocms_c)
                srcoffset = y * in_rowstride;
                for(x=0 ; x<width ; x++)
                {
+                       guint Y;
+
                        rr = (in[srcoffset+R]*pre_muli[R]+64)>>7;
                        gg = (in[srcoffset+G]*pre_muli[G]+64)>>7;
                        bb = (in[srcoffset+B]*pre_muli[B]+64)>>7;
@@ -959,6 +1016,20 @@ COLOR_TRANSFORM(transform_nocms_c)
                                + gg*mati.coeff[2][1]
                                + bb*mati.coeff[2][2])>>MATRIX_RESOLUTION;
                        _CLAMP65535_TRIPLET(r,g,b);
+
+                       // Compute luminance
+                       Y = (RLUMF*r + GLUMF*g + BLUMF*b + 
HALFF)>>LUM_PRECISION;
+
+                       // Find the factor to apply to the RGB triplet
+                       Y = rct->priv->luminance[Y];
+
+                       // Multiplythe RGB triplet using fixed point arithmetic
+                       r = (r*Y)>>LUM_PRECISION;
+                       g = (g*Y)>>LUM_PRECISION;
+                       b = (b*Y)>>LUM_PRECISION;
+
+                       _CLAMP65535_TRIPLET(r,g,b);
+                               
                        d[destoffset++] = rct->priv->table8[r];
                        d[destoffset++] = rct->priv->table8[g];
                        d[destoffset++] = rct->priv->table8[b];

_______________________________________________
Rawstudio-dev mailing list
[email protected]
http://rawstudio.org/cgi-bin/mailman/listinfo/rawstudio-dev

Reply via email to