doxygen: prevent GPL license block from being parsed as doxygen comment.
[blender.git] / source / blender / nodes / intern / CMP_nodes / CMP_colorbalance.c
index efd49172f953c677144296594d620080c1170c9d..0cecb764722a44ae5748839fca81ad5bc61252de 100644 (file)
@@ -1,4 +1,4 @@
-/**
+/*
  * 
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
@@ -43,26 +43,39 @@ static bNodeSocketType cmp_node_colorbalance_out[]={
        {-1,0,""}
 };
 
+/* this function implements ASC-CDL according to the spec at http://www.asctech.org/
+ Slope
+       S = in * slope
+ Offset
+       O = S + offset 
+         = (in * slope) + offset
+ Power
+     out = Clamp(O) ^ power
+         = Clamp((in * slope) + offset) ^ power
+ */
 DO_INLINE float colorbalance_cdl(float in, float offset, float power, float slope)
 {
        float x = in * slope + offset;
        
        /* prevent NaN */
-       if (x < 0.f) x = 0.f;
+       CLAMP(x, 0.0, 1.0);
        
-       //powf(in * slope + offset, power)
-       return powf(x, 1.f/power);
+       return powf(x, power);
 }
 
-/* note: lift_lgg is just 2-lift */
-DO_INLINE float colorbalance_lgg(float in, float lift_lgg, float gamma, float gain)
-{      
-       float x= (((in - 1.0f) * lift_lgg) + 1.0f) * gain;
+/* note: lift_lgg is just 2-lift, gamma_inv is 1.0/gamma */
+DO_INLINE float colorbalance_lgg(float in, float lift_lgg, float gamma_inv, float gain)
+{
+       /* 1:1 match with the sequencer with linear/srgb conversions, the conversion isnt pretty
+        * but best keep it this way, sice testing for durian shows a similar calculation
+        * without lin/srgb conversions gives bad results (over-saturated shadows) with colors
+        * slightly below 1.0. some correction can be done but it ends up looking bad for shadows or lighter tones - campbell */
+       float x= (((linearrgb_to_srgb(in) - 1.0f) * lift_lgg) + 1.0f) * gain;
 
        /* prevent NaN */
        if (x < 0.f) x = 0.f;
-       
-       return powf(x, (1.f/gamma));
+
+       return powf(srgb_to_linearrgb(x), gamma_inv);
 }
 
 static void do_colorbalance_cdl(bNode *node, float* out, float *in)
@@ -90,9 +103,9 @@ static void do_colorbalance_lgg(bNode *node, float* out, float *in)
 {
        NodeColorBalance *n= (NodeColorBalance *)node->storage;
 
-       out[0] = colorbalance_lgg(in[0], n->lift_lgg[0], n->gamma[0], n->gain[0]);
-       out[1] = colorbalance_lgg(in[1], n->lift_lgg[1], n->gamma[1], n->gain[1]);
-       out[2] = colorbalance_lgg(in[2], n->lift_lgg[2], n->gamma[2], n->gain[2]);
+       out[0] = colorbalance_lgg(in[0], n->lift_lgg[0], n->gamma_inv[0], n->gain[0]);
+       out[1] = colorbalance_lgg(in[1], n->lift_lgg[1], n->gamma_inv[1], n->gain[1]);
+       out[2] = colorbalance_lgg(in[2], n->lift_lgg[2], n->gamma_inv[2], n->gain[2]);
        out[3] = in[3];
 }
 
@@ -101,13 +114,13 @@ static void do_colorbalance_lgg_fac(bNode *node, float* out, float *in, float *f
        NodeColorBalance *n= (NodeColorBalance *)node->storage;
        const float mfac= 1.0f - *fac;
 
-       out[0] = mfac*in[0] + *fac * colorbalance_lgg(in[0], n->lift_lgg[0], n->gamma[0], n->gain[0]);
-       out[1] = mfac*in[1] + *fac * colorbalance_lgg(in[1], n->lift_lgg[1], n->gamma[1], n->gain[1]);
-       out[2] = mfac*in[2] + *fac * colorbalance_lgg(in[2], n->lift_lgg[2], n->gamma[2], n->gain[2]);
+       out[0] = mfac*in[0] + *fac * colorbalance_lgg(in[0], n->lift_lgg[0], n->gamma_inv[0], n->gain[0]);
+       out[1] = mfac*in[1] + *fac * colorbalance_lgg(in[1], n->lift_lgg[1], n->gamma_inv[1], n->gain[1]);
+       out[2] = mfac*in[2] + *fac * colorbalance_lgg(in[2], n->lift_lgg[2], n->gamma_inv[2], n->gain[2]);
        out[3] = in[3];
 }
 
-static void node_composit_exec_colorbalance(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void node_composit_exec_colorbalance(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
 {
        CompBuf *cbuf= in[1]->data;
        CompBuf *stackbuf;
@@ -125,15 +138,9 @@ static void node_composit_exec_colorbalance(void *data, bNode *node, bNodeStack
                NodeColorBalance *n= (NodeColorBalance *)node->storage;
                int c;
 
-               copy_v3_v3(n->lift_lgg, n->lift);
-
                for (c = 0; c < 3; c++) {
-                       /* tweak to give more subtle results
-                        * values above 1.0 are scaled */
-                       if(n->lift_lgg[c] > 1.0f)
-                               n->lift_lgg[c] = pow(n->lift_lgg[c] - 1.0f, 2.0f) + 1.0f;
-
-                       n->lift_lgg[c] = 2.0f - n->lift_lgg[c];
+                       n->lift_lgg[c] = 2.0f - n->lift[c];
+                       n->gamma_inv[c] = (n->gamma[c] != 0.0f) ? 1.0f/n->gamma[c] : 1000000.0f;
                }
        }
 
@@ -172,20 +179,18 @@ static void node_composit_init_colorbalance(bNode *node)
        n->gain[0] = n->gain[1] = n->gain[2] = 1.0f;
 }
 
-bNodeType cmp_node_colorbalance={
-       /* *next,*prev */       NULL, NULL,
-       /* type code   */       CMP_NODE_COLORBALANCE,
-       /* name        */       "Color Balance",
-       /* width+range */       400, 200, 400,
-       /* class+opts  */       NODE_CLASS_OP_COLOR, NODE_OPTIONS,
-       /* input sock  */       cmp_node_colorbalance_in,
-       /* output sock */       cmp_node_colorbalance_out,
-       /* storage     */       "NodeColorBalance",
-       /* execfunc    */       node_composit_exec_colorbalance,
-       /* butfunc     */       NULL,
-       /* initfunc    */       node_composit_init_colorbalance,
-       /* freestoragefunc    */        node_free_standard_storage,
-       /* copystoragefunc    */        node_copy_standard_storage,
-       /* id          */       NULL
-};
+void register_node_type_cmp_colorbalance(ListBase *lb)
+{
+       static bNodeType ntype;
+
+       node_type_base(&ntype, CMP_NODE_COLORBALANCE, "Color Balance", NODE_CLASS_OP_COLOR, NODE_OPTIONS,
+               cmp_node_colorbalance_in, cmp_node_colorbalance_out);
+       node_type_size(&ntype, 400, 200, 400);
+       node_type_init(&ntype, node_composit_init_colorbalance);
+       node_type_storage(&ntype, "NodeColorBalance", node_free_standard_storage, node_copy_standard_storage);
+       node_type_exec(&ntype, node_composit_exec_colorbalance);
+
+       nodeRegisterType(lb, &ntype);
+}
+