Fixes to Color Balance node:
authorMatt Ebb <matt@mke3.net>
Wed, 27 Jan 2010 00:22:29 +0000 (00:22 +0000)
committerMatt Ebb <matt@mke3.net>
Wed, 27 Jan 2010 00:22:29 +0000 (00:22 +0000)
* The Lift/Gamma/Gain formula previously was incorrect, fixed this and
removed conversions - now the RNA values are the same as what goes into
the formula.
* Because of this, added the ability for the Value slider to map to a wider range
than 0.0-1.0. The black/white gradient remains the same, in this case just
indicating darker/brighter rather than absolute colour values. Also added ability
for color wheels to be locked at full brightness (useful for this case, where the
color value itself is dark).
* Added an alternate formula - offset/power/slope (asc-cdl). This fits the standard
Color Decision List formula, here for compatibility with other systems, though
default Lift/Gamma/Gain is easier to use and gives nicer results.

source/blender/editors/include/UI_interface.h
source/blender/editors/interface/interface_handlers.c
source/blender/editors/interface/interface_templates.c
source/blender/editors/interface/interface_widgets.c
source/blender/editors/space_node/drawnode.c
source/blender/makesrna/intern/rna_nodetree.c
source/blender/makesrna/intern/rna_ui_api.c
source/blender/nodes/intern/CMP_nodes/CMP_colorbalance.c

index 309cee7cb9ce66dfffe9da290bb424c6fa09fa59..c94f20da459b3680e7e9ac6d0312a19be721ec39 100644 (file)
@@ -677,7 +677,7 @@ void uiTemplatePreview(uiLayout *layout, struct ID *id, struct ID *parent, struc
 void uiTemplateColorRamp(uiLayout *layout, struct PointerRNA *ptr, char *propname, int expand);
 void uiTemplateHistogram(uiLayout *layout, struct PointerRNA *ptr, char *propname, int expand);
 void uiTemplateCurveMapping(uiLayout *layout, struct PointerRNA *ptr, char *propname, int type, int levels, int brush);
-void uiTemplateColorWheel(uiLayout *layout, struct PointerRNA *ptr, char *propname, int value_slider);
+void uiTemplateColorWheel(uiLayout *layout, struct PointerRNA *ptr, char *propname, int value_slider, int lock);
 void uiTemplateTriColorSet(uiLayout *layout, struct PointerRNA *ptr, char *propname);
 void uiTemplateLayers(uiLayout *layout, struct PointerRNA *ptr, char *propname,
                      PointerRNA *used_ptr, char *used_propname, int active_layer);
index b84bdcd958e08e21b1e3c7ebb8321d40f748895a..bb3709295f8337a15692187a71f093bfa42b9faa 100644 (file)
@@ -2872,10 +2872,18 @@ static int ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, int mx,
                hsv[2]= x; 
        }
        else if (but->a1==9){
+               float range;
+               
                /* vertical 'value' strip */
                hsv[2]= y; 
+               
+               /* exception only for value strip - use the range set in but->min/max */
+               range = but->softmax - but->softmin;
+               hsv[2] = y*range + but->softmin;
+               
                if (color_profile)
                        hsv[2] = srgb_to_linearrgb(hsv[2]);
+               
        }
 
        hsv_to_rgb(hsv[0], hsv[1], hsv[2], rgb, rgb+1, rgb+2);
index 264bc724bce222bdab53f4e3671bc750568424d1..44f653669f2191e727959af6f4cc0caaadfe6883 100644 (file)
@@ -1965,26 +1965,29 @@ void uiTemplateCurveMapping(uiLayout *layout, PointerRNA *ptr, char *propname, i
 
 #define WHEEL_SIZE     100
 
-void uiTemplateColorWheel(uiLayout *layout, PointerRNA *ptr, char *propname, int value_slider)
+void uiTemplateColorWheel(uiLayout *layout, PointerRNA *ptr, char *propname, int value_slider, int lock)
 {
        PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
        uiBlock *block= uiLayoutGetBlock(layout);
        uiLayout *col, *row;
+       float softmin, softmax, step, precision;
        
        if (!prop) {
                printf("uiTemplateColorWheel: property not found: %s\n", propname);
                return;
        }
        
+       RNA_property_float_ui_range(ptr, prop, &softmin, &softmax, &step, &precision);
+       
        col = uiLayoutColumn(layout, 0);
        row= uiLayoutRow(col, 1);
        
-       uiDefButR(block, HSVCIRCLE, 0, "",      0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, propname, -1, 0.0, 0.0, 0, 0, "");
+       uiDefButR(block, HSVCIRCLE, 0, "",      0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, propname, -1, 0.0, 0.0, 0, lock, "");
        
        uiItemS(row);
        
        if (value_slider)
-               uiDefButR(block, HSVCUBE, 0, "", WHEEL_SIZE+6, 0, 14, WHEEL_SIZE, ptr, propname, -1, 0.0, 0.0, 9, 0, "");
+               uiDefButR(block, HSVCUBE, 0, "", WHEEL_SIZE+6, 0, 14, WHEEL_SIZE, ptr, propname, -1, softmin, softmax, 9, 0, "");
 
        /* maybe a switch for this?
        row= uiLayoutRow(col, 0);
index d9e8f6f55d240c791e05a456d1f3c6e85ae7a6e3..aeea7d4a354c2b7207ee414f7fd5080045b53cf7 100644 (file)
@@ -1577,6 +1577,11 @@ void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, rcti *rect)
        rgb_to_hsv(rgb[0], rgb[1], rgb[2], hsv, hsv+1, hsv+2);
        copy_v3_v3(hsvo, hsv);
        
+       /* exception: if 'lock' is set (stored in but->a2),
+        * lock the value of the color wheel to 1.
+        * Useful for color correction tools where you're only interested in hue. */
+       if (but->a2) hsv[2] = 1.f;
+       
        hsv_to_rgb(0.f, 0.f, hsv[2], colcent, colcent+1, colcent+2);
        
        glShadeModel(GL_SMOOTH);
@@ -1793,7 +1798,7 @@ static void ui_draw_but_HSV_v(uiBut *but, rcti *rect)
        uiWidgetBase wtb;
        float rad= 0.5f*(rect->xmax - rect->xmin);
        float x, y;
-       float rgb[3], hsv[3], v;
+       float rgb[3], hsv[3], v, range;
        int color_profile = but->block->color_profile;
        
        if (but->rnaprop) {
@@ -1808,6 +1813,10 @@ static void ui_draw_but_HSV_v(uiBut *but, rcti *rect)
        
        if (color_profile)
                v = linearrgb_to_srgb(v);
+
+       /* map v from property range to [0,1] */
+       range = but->softmax - but->softmin;
+       v =     (v - but->softmin)/range;
        
        widget_init(&wtb);
        
index 3092aaba5078374714bd21c563a1041703baeda9..fe5c7bca3a652140c027272591a2f0a9c945f868 100644 (file)
@@ -125,7 +125,7 @@ static void node_buts_rgb(uiLayout *layout, bContext *C, PointerRNA *ptr)
        RNA_property_collection_lookup_int(ptr, prop, 0, &sockptr);
        
        col = uiLayoutColumn(layout, 0);
-       uiTemplateColorWheel(col, &sockptr, "default_value", 1);
+       uiTemplateColorWheel(col, &sockptr, "default_value", 1, 0);
        uiItemR(col, "", 0, &sockptr, "default_value", 0);
 }
 
@@ -917,21 +917,44 @@ static void node_composit_buts_colorbalance(uiLayout *layout, bContext *C, Point
 {
        uiLayout *split, *col, *row;
        
-       split = uiLayoutSplit(layout, 0, 0);
-       col = uiLayoutColumn(split, 0);
-       uiTemplateColorWheel(col, ptr, "lift", 1);
-       row = uiLayoutRow(col, 0);
-       uiItemR(row, NULL, 0, ptr, "lift", 0);
+       uiItemR(layout, NULL, 0, ptr, "correction_formula", 0);
        
-       col = uiLayoutColumn(split, 0);
-       uiTemplateColorWheel(col, ptr, "gamma", 1);
-       row = uiLayoutRow(col, 0);
-       uiItemR(row, NULL, 0, ptr, "gamma", 0);
+       if (RNA_enum_get(ptr, "correction_formula")== 0) {
        
-       col = uiLayoutColumn(split, 0);
-       uiTemplateColorWheel(col, ptr, "gain", 1);
-       row = uiLayoutRow(col, 0);
-       uiItemR(row, NULL, 0, ptr, "gain", 0);
+               split = uiLayoutSplit(layout, 0, 0);
+               col = uiLayoutColumn(split, 0);
+               uiTemplateColorWheel(col, ptr, "lift", 1, 1);
+               row = uiLayoutRow(col, 0);
+               uiItemR(row, NULL, 0, ptr, "lift", 0);
+               
+               col = uiLayoutColumn(split, 0);
+               uiTemplateColorWheel(col, ptr, "gamma", 1, 1);
+               row = uiLayoutRow(col, 0);
+               uiItemR(row, NULL, 0, ptr, "gamma", 0);
+               
+               col = uiLayoutColumn(split, 0);
+               uiTemplateColorWheel(col, ptr, "gain", 1, 1);
+               row = uiLayoutRow(col, 0);
+               uiItemR(row, NULL, 0, ptr, "gain", 0);
+
+       } else {
+               
+               split = uiLayoutSplit(layout, 0, 0);
+               col = uiLayoutColumn(split, 0);
+               uiTemplateColorWheel(col, ptr, "offset", 1, 1);
+               row = uiLayoutRow(col, 0);
+               uiItemR(row, NULL, 0, ptr, "offset", 0);
+               
+               col = uiLayoutColumn(split, 0);
+               uiTemplateColorWheel(col, ptr, "power", 1, 1);
+               row = uiLayoutRow(col, 0);
+               uiItemR(row, NULL, 0, ptr, "power", 0);
+               
+               col = uiLayoutColumn(split, 0);
+               uiTemplateColorWheel(col, ptr, "slope", 1, 1);
+               row = uiLayoutRow(col, 0);
+               uiItemR(row, NULL, 0, ptr, "slope", 0);
+       }
 
 }
 
index fa14bea42286607a529e3a5517a1bdaabebf7771..8b9eb00e96acc82070e07f1d1a6fc0f4c14d3122 100644 (file)
@@ -300,24 +300,6 @@ static void rna_Node_image_layer_update(Main *bmain, Scene *scene, PointerRNA *p
        rna_Node_update(bmain, scene, ptr);
 }
 
-static void rna_Node_colorbalance_update(Main *bmain, Scene *scene, PointerRNA *ptr)
-{
-       bNode *node= (bNode*)ptr->data;
-       NodeColorBalance *ncb = node->storage;
-       float lift[3], gamma[3], gain[3];
-       
-       lift[0] = (ncb->lift[0] * 2.f - 1.f)*0.5f;
-       lift[1] = (ncb->lift[1] * 2.f - 1.f)*0.5f;
-       lift[2] = (ncb->lift[2] * 2.f - 1.f)*0.5f;
-       
-       mul_v3_v3fl(gamma, ncb->gamma, 2.f);
-       mul_v3_v3fl(gain, ncb->gain, 2.f);
-       
-       lift_gamma_gain_to_asc_cdl(lift, gamma, gain, ncb->offset, ncb->slope, ncb->power);
-       
-       rna_Node_update(bmain, scene, ptr);
-}
-
 static EnumPropertyItem *renderresult_layers_add_enum(RenderLayer *rl)
 {
        EnumPropertyItem *item= NULL;
@@ -1878,33 +1860,67 @@ static void def_cmp_lensdist(StructRNA *srna)
 static void def_cmp_colorbalance(StructRNA *srna)
 {
        PropertyRNA *prop;
-       static float default_col[3] = {0.5f, 0.5f, 0.5f};
+       static float default_1[3] = {1.f, 1.f, 1.f};
+       
+       static EnumPropertyItem type_items[] = {
+               {0, "LIFT_GAMMA_GAIN",      0, "Lift/Gamma/Gain",      ""},
+               {1, "OFFSET_POWER_SLOPE",     0, "Offset/Power/Slope (ASC-CDL)",     "ASC-CDL standard color correction"},
+               {0, NULL, 0, NULL, NULL}};
+       
+       prop = RNA_def_property(srna, "correction_formula", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_sdna(prop, NULL, "custom1");
+       RNA_def_property_enum_items(prop, type_items);
+       RNA_def_property_ui_text(prop, "Correction Formula", "");
+       RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update");
        
        RNA_def_struct_sdna_from(srna, "NodeColorBalance", "storage");
        
        prop = RNA_def_property(srna, "lift", PROP_FLOAT, PROP_COLOR_GAMMA);
        RNA_def_property_float_sdna(prop, NULL, "lift");
        RNA_def_property_array(prop, 3);
-       RNA_def_property_float_array_default(prop, default_col);
        RNA_def_property_ui_range(prop, 0, 1, 0.1, 3);
        RNA_def_property_ui_text(prop, "Lift", "Correction for Shadows");
-       RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_colorbalance_update");
+       RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update");
        
        prop = RNA_def_property(srna, "gamma", PROP_FLOAT, PROP_COLOR_GAMMA);
        RNA_def_property_float_sdna(prop, NULL, "gamma");
        RNA_def_property_array(prop, 3);
-       RNA_def_property_float_array_default(prop, default_col);
-       RNA_def_property_ui_range(prop, 0, 1, 0.1, 3);
+       RNA_def_property_float_array_default(prop, default_1);
+       RNA_def_property_ui_range(prop, 0, 2, 0.1, 3);
        RNA_def_property_ui_text(prop, "Gamma", "Correction for Midtones");
-       RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_colorbalance_update");
+       RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update");
        
        prop = RNA_def_property(srna, "gain", PROP_FLOAT, PROP_COLOR_GAMMA);
        RNA_def_property_float_sdna(prop, NULL, "gain");
        RNA_def_property_array(prop, 3);
-       RNA_def_property_float_array_default(prop, default_col);
-       RNA_def_property_ui_range(prop, 0, 1, 0.1, 3);
+       RNA_def_property_float_array_default(prop, default_1);
+       RNA_def_property_ui_range(prop, 0, 2, 0.1, 3);
        RNA_def_property_ui_text(prop, "Gain", "Correction for Highlights");
-       RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_colorbalance_update");
+       RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update");
+       
+       
+       prop = RNA_def_property(srna, "offset", PROP_FLOAT, PROP_COLOR_GAMMA);
+       RNA_def_property_float_sdna(prop, NULL, "lift");
+       RNA_def_property_array(prop, 3);
+       RNA_def_property_ui_range(prop, 0, 1, 0.1, 3);
+       RNA_def_property_ui_text(prop, "Offset", "Correction for Shadows");
+       RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update");
+       
+       prop = RNA_def_property(srna, "power", PROP_FLOAT, PROP_COLOR_GAMMA);
+       RNA_def_property_float_sdna(prop, NULL, "gamma");
+       RNA_def_property_array(prop, 3);
+       RNA_def_property_float_array_default(prop, default_1);
+       RNA_def_property_ui_range(prop, 0, 2, 0.1, 3);
+       RNA_def_property_ui_text(prop, "Power", "Correction for Midtones");
+       RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update");
+       
+       prop = RNA_def_property(srna, "slope", PROP_FLOAT, PROP_COLOR_GAMMA);
+       RNA_def_property_float_sdna(prop, NULL, "gain");
+       RNA_def_property_array(prop, 3);
+       RNA_def_property_float_array_default(prop, default_1);
+       RNA_def_property_ui_range(prop, 0, 2, 0.1, 3);
+       RNA_def_property_ui_text(prop, "Slope", "Correction for Highlights");
+       RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update");
 }
 
 static void def_cmp_huecorrect(StructRNA *srna)
index cd7051fc17157b7c67800add723d659ac153c723..07bf20b0c033be2a5dee5b7b7bb8e41cbba71186 100644 (file)
@@ -344,6 +344,7 @@ void RNA_api_ui_layout(StructRNA *srna)
        func= RNA_def_function(srna, "template_color_wheel", "uiTemplateColorWheel");
        api_ui_item_rna_common(func);
        RNA_def_boolean(func, "value_slider", 0, "", "Display the value slider to the right of the color wheel");
+       RNA_def_boolean(func, "lock", 0, "", "Lock the color wheel display to value 1.0 regardless of actual color");
        
        func= RNA_def_function(srna, "template_triColorSet", "uiTemplateTriColorSet");
        api_ui_item_rna_common(func);
index 9d3a670fad2b1b3908c09dc9465ed8b73f48046f..09dccd8e3c4783e61e82d5df1e592a99664a5eec 100644 (file)
@@ -43,34 +43,66 @@ static bNodeSocketType cmp_node_colorbalance_out[]={
        {-1,0,""}
 };
 
-DO_INLINE float colorbalance(float in, float slope, float offset, float 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;
        
-       return powf(x, power);
+       //powf(in * slope + offset, power)
+       return powf(x, 1.f/power);
 }
 
-static void do_colorbalance(bNode *node, float* out, float *in)
+DO_INLINE float colorbalance_lgg(float in, float lift, float gamma, float gain)
+{
+       float x = gain*(in+lift*(1-in));
+       
+       /* prevent NaN */
+       if (x < 0.f) x = 0.f;
+       
+       return powf(x, (1.f/gamma));
+}
+
+static void do_colorbalance_cdl(bNode *node, float* out, float *in)
 {
        NodeColorBalance *n= (NodeColorBalance *)node->storage;
        
-       out[0] = colorbalance(in[0], n->slope[0], n->offset[0], n->power[0]);
-       out[1] = colorbalance(in[1], n->slope[1], n->offset[1], n->power[1]);
-       out[2] = colorbalance(in[2], n->slope[2], n->offset[2], n->power[2]);
+       out[0] = colorbalance_cdl(in[0], n->lift[0], n->gamma[0], n->gain[0]);
+       out[1] = colorbalance_cdl(in[1], n->lift[1], n->gamma[1], n->gain[1]);
+       out[2] = colorbalance_cdl(in[2], n->lift[2], n->gamma[2], n->gain[2]);
        out[3] = in[3];
 }
 
-static void do_colorbalance_fac(bNode *node, float* out, float *in, float *fac)
+static void do_colorbalance_cdl_fac(bNode *node, float* out, float *in, float *fac)
 {
        NodeColorBalance *n= (NodeColorBalance *)node->storage;
        const float mfac= 1.0f - *fac;
        
-       out[0] = mfac*in[0] + *fac * colorbalance(in[0], n->slope[0], n->offset[0], n->power[0]);
-       out[1] = mfac*in[1] + *fac * colorbalance(in[1], n->slope[1], n->offset[1], n->power[1]);
-       out[2] = mfac*in[2] + *fac * colorbalance(in[2], n->slope[2], n->offset[2], n->power[2]);
+       out[0] = mfac*in[0] + *fac * colorbalance_cdl(in[0], n->lift[0], n->gamma[0], n->gain[0]);
+       out[1] = mfac*in[1] + *fac * colorbalance_cdl(in[1], n->lift[1], n->gamma[1], n->gain[1]);
+       out[2] = mfac*in[2] + *fac * colorbalance_cdl(in[2], n->lift[2], n->gamma[2], n->gain[2]);
+       out[3] = in[3];
+}
+
+static void do_colorbalance_lgg(bNode *node, float* out, float *in)
+{
+       NodeColorBalance *n= (NodeColorBalance *)node->storage;
+       
+       out[0] = colorbalance_lgg(in[0], n->lift[0], n->gamma[0], n->gain[0]);
+       out[1] = colorbalance_lgg(in[1], n->lift[1], n->gamma[1], n->gain[1]);
+       out[2] = colorbalance_lgg(in[2], n->lift[2], n->gamma[2], n->gain[2]);
+       out[3] = in[3];
+}
+
+static void do_colorbalance_lgg_fac(bNode *node, float* out, float *in, float *fac)
+{
+       NodeColorBalance *n= (NodeColorBalance *)node->storage;
+       const float mfac= 1.0f - *fac;
+       
+       out[0] = mfac*in[0] + *fac * colorbalance_lgg(in[0], n->lift[0], n->gamma[0], n->gain[0]);
+       out[1] = mfac*in[1] + *fac * colorbalance_lgg(in[1], n->lift[1], n->gamma[1], n->gain[1]);
+       out[2] = mfac*in[2] + *fac * colorbalance_lgg(in[2], n->lift[2], n->gamma[2], n->gain[2]);
        out[3] = in[3];
 }
 
@@ -90,12 +122,24 @@ static void node_composit_exec_colorbalance(void *data, bNode *node, bNodeStack
        
        if (cbuf) {
                stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* create output based on image input */
-                               
-               if ((in[0]->data==NULL) && (in[0]->vec[0] == 1.f)) {
-                       composit1_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, do_colorbalance, CB_RGBA);
-               }
-               else {
-                       composit2_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, in[0]->data, in[0]->vec, do_colorbalance_fac, CB_RGBA, CB_VAL);
+                       
+               if (node->custom1 == 0) {
+                       /* lift gamma gain */
+                       if ((in[0]->data==NULL) && (in[0]->vec[0] >= 1.f)) {
+                               composit1_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, do_colorbalance_lgg, CB_RGBA);
+                       }
+                       else {
+                               composit2_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, in[0]->data, in[0]->vec, do_colorbalance_lgg_fac, CB_RGBA, CB_VAL);
+                       }
+               } else {
+                       /* offset/power/slope : ASC-CDL */
+                       if ((in[0]->data==NULL) && (in[0]->vec[0] >= 1.f)) {
+                               composit1_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, do_colorbalance_cdl, CB_RGBA);
+                       }
+                       else {
+                               composit2_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, in[0]->data, in[0]->vec, do_colorbalance_cdl_fac, CB_RGBA, CB_VAL);
+                       }
+                       
                }
 
                out[0]->data=stackbuf;
@@ -105,14 +149,10 @@ static void node_composit_exec_colorbalance(void *data, bNode *node, bNodeStack
 static void node_composit_init_colorbalance(bNode *node)
 {
        NodeColorBalance *n= node->storage= MEM_callocN(sizeof(NodeColorBalance), "node colorbalance");
-       n->slope[0] = n->slope[1] = n->slope[2] = 1.f;
-       n->offset[0] = n->offset[1] = n->offset[2] = 0.f;
-       n->power[0] = n->power[1] = n->power[2] = 1.f;
-       
-       /* for ui, converted to slope/offset/power in RNA */
-       n->lift[0] = n->lift[1] = n->lift[2] = 0.5f;
-       n->gamma[0] = n->gamma[1] = n->gamma[2] = 0.5f;
-       n->gain[0] = n->gain[1] = n->gain[2] = 0.5f;
+
+       n->lift[0] = n->lift[1] = n->lift[2] = 0.0f;
+       n->gamma[0] = n->gamma[1] = n->gamma[2] = 1.0f;
+       n->gain[0] = n->gain[1] = n->gain[2] = 1.0f;
 }
 
 bNodeType cmp_node_colorbalance={