Tomato keying screen: small fixes and improvements
authorSergey Sharybin <sergey.vfx@gmail.com>
Fri, 6 Jul 2012 12:59:00 +0000 (12:59 +0000)
committerSergey Sharybin <sergey.vfx@gmail.com>
Fri, 6 Jul 2012 12:59:00 +0000 (12:59 +0000)
- Fixed issues with calculating matte with balance != 0.5
  It used to be used concave combination of minimal and maximal
  channel values which could be inpredictable.
  Use concave combination of two non-major channels sorted
  by their index, so such combination would always use the same
  coefficients for particular non-major channels.

- Added despill balance slider which defines balance between
  non-major channels used for calculating average of two
  colors. Difference between average value and pixel value of
  major screen channel defines amount of despill. Balance of
  0.5 gives the same behavior as it was before this slider
  was added.

source/blender/blenloader/intern/readfile.c
source/blender/compositor/nodes/COM_KeyingNode.cpp
source/blender/compositor/nodes/COM_KeyingNode.h
source/blender/compositor/operations/COM_KeyingDespillOperation.cpp
source/blender/compositor/operations/COM_KeyingDespillOperation.h
source/blender/compositor/operations/COM_KeyingOperation.cpp
source/blender/editors/space_node/drawnode.c
source/blender/makesdna/DNA_node_types.h
source/blender/makesrna/intern/rna_nodetree.c

index 21714540defd12f19328bb13c5a39bdab9bd8d06..6baf4cc435f164da01c340856f5a355040059dc0 100644 (file)
@@ -7061,6 +7061,21 @@ static void do_version_ntree_dilateerode_264(void *UNUSED(data), ID *UNUSED(id),
        }
 }
 
+static void do_version_ntree_keying_despill_balance(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree)
+{
+       bNode *node;
+
+       for (node = ntree->nodes.first; node; node = node->next) {
+               if (node->type == CMP_NODE_KEYING) {
+                       NodeKeyingData *data = node->storage;
+
+                       if (data->despill_balance == 0.0f) {
+                               data->despill_balance = 0.5f;
+                       }
+               }
+       }
+}
+
 static void do_versions(FileData *fd, Library *lib, Main *main)
 {
        /* WATCH IT!!!: pointers from libdata have not been converted */
@@ -7875,6 +7890,13 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                        ntreetype->foreach_nodetree(main, NULL, do_version_ntree_dilateerode_264);
        }
 
+       {
+               bNodeTreeType *ntreetype = ntreeGetType(NTREE_COMPOSIT);
+
+               if (ntreetype && ntreetype->foreach_nodetree)
+                       ntreetype->foreach_nodetree(main, NULL, do_version_ntree_keying_despill_balance);
+       }
+
        /* WATCH IT!!!: pointers from libdata have not been converted yet here! */
        /* WATCH IT 2!: Userdef struct init has to be in editors/interface/resources.c! */
 
index 7c39765fbf1f4f8fc305c42408240aea91110e71..efd50a44a515e4d837b8ba4cfe7e4b57b3b01b2f 100644 (file)
@@ -184,11 +184,13 @@ OutputSocket *KeyingNode::setupFeather(ExecutionSystem *graph, CompositorContext
        return operationy->getOutputSocket();
 }
 
-OutputSocket *KeyingNode::setupDespill(ExecutionSystem *graph, OutputSocket *despillInput, OutputSocket *inputScreen, float factor)
+OutputSocket *KeyingNode::setupDespill(ExecutionSystem *graph, OutputSocket *despillInput, OutputSocket *inputScreen,
+                                       float factor, float colorBalance)
 {
        KeyingDespillOperation *despillOperation = new KeyingDespillOperation();
 
        despillOperation->setDespillFactor(factor);
+       despillOperation->setColorBalance(colorBalance);
 
        addLink(graph, despillInput, despillOperation->getInputSocket(0));
        addLink(graph, inputScreen, despillOperation->getInputSocket(1));
@@ -292,7 +294,8 @@ void KeyingNode::convertToOperations(ExecutionSystem *graph, CompositorContext *
        if (keying_data->despill_factor > 0.0f) {
                postprocessedImage = setupDespill(graph, postprocessedImage,
                                                  keyingOperation->getInputSocket(1)->getConnection()->getFromSocket(),
-                                                 keying_data->despill_factor);
+                                                 keying_data->despill_factor,
+                                                 keying_data->despill_balance);
        }
 
        /* connect result to output sockets */
index 294a27bb52ce05157e1a19771f8ad6801073564a..6ab6a60a44dce2ae57b8f691590b2ad40c0228f7 100644 (file)
@@ -36,7 +36,8 @@ protected:
        OutputSocket *setupDilateErode(ExecutionSystem *graph, OutputSocket *dilateErodeInput, int distance);
        OutputSocket *setupFeather(ExecutionSystem *graph, CompositorContext *context, OutputSocket *featherInput,
                                   int falloff, int distance);
-       OutputSocket *setupDespill(ExecutionSystem *graph, OutputSocket *despillInput, OutputSocket *inputSrceen, float factor);
+       OutputSocket *setupDespill(ExecutionSystem *graph, OutputSocket *despillInput, OutputSocket *inputSrceen,
+                                  float factor, float colorBalance);
        OutputSocket *setupClip(ExecutionSystem *graph, OutputSocket *clipInput, int kernelRadius, float kernelTolerance,
                                float clipBlack, float clipWhite, bool edgeMatte);
 public:
index 081d9f723e8392ab6bcf865149a7e65c321e06e7..9798ddcee94dfc77f0f57e14e75df4169accfabe 100644 (file)
@@ -47,6 +47,7 @@ KeyingDespillOperation::KeyingDespillOperation() : NodeOperation()
        this->addOutputSocket(COM_DT_COLOR);
 
        this->m_despillFactor = 0.5f;
+       this->m_colorBalance = 0.5f;
 
        this->m_pixelReader = NULL;
        this->m_screenReader = NULL;
@@ -73,16 +74,22 @@ void KeyingDespillOperation::executePixel(float *color, float x, float y, PixelS
        this->m_screenReader->read(screenColor, x, y, sampler, inputBuffers);
 
        int screen_primary_channel = get_pixel_primary_channel(screenColor);
+       int other_1 = (screen_primary_channel + 1) % 3;
+       int other_2 = (screen_primary_channel + 2) % 3;
+
+       int min_channel = MIN2(other_1, other_2);
+       int max_channel = MAX2(other_1, other_2);
+
        float average_value, amount;
 
-       average_value = (pixelColor[0] + pixelColor[1] + pixelColor[2] - pixelColor[screen_primary_channel]) / 2.0f;
-       amount = pixelColor[screen_primary_channel] - average_value;
+       average_value = this->m_colorBalance * pixelColor[min_channel] + (1.0f - this->m_colorBalance) * pixelColor[max_channel];
+       amount = (pixelColor[screen_primary_channel] - average_value);
 
        color[0] = pixelColor[0];
        color[1] = pixelColor[1];
        color[2] = pixelColor[2];
        color[3] = pixelColor[3];
-       
+
        if (this->m_despillFactor * amount > 0) {
                color[screen_primary_channel] = pixelColor[screen_primary_channel] - this->m_despillFactor * amount;
        }
index 4fea9b578a117876b0ff1f7932894f9da1d4bdbb..3485bf1952fc921cfd9e40d5b6ddeba604ba4e34 100644 (file)
@@ -34,6 +34,7 @@ protected:
        SocketReader *m_pixelReader;
        SocketReader *m_screenReader;
        float m_despillFactor;
+       float m_colorBalance;
 
 public:
        KeyingDespillOperation();
@@ -42,6 +43,7 @@ public:
        void deinitExecution();
 
        void setDespillFactor(float value) {this->m_despillFactor = value;}
+       void setColorBalance(float value) {this->m_colorBalance = value;}
 
        void executePixel(float *color, float x, float y, PixelSampler sampler, MemoryBuffer *inputBuffers[]);
 };
index e92e5c84c2d42ffe22f2b52a9a44eaa53a33958f..48d1967b5b3714d95081cb886f31be4a2a1c43ca 100644 (file)
@@ -45,9 +45,10 @@ static float get_pixel_saturation(float pixelColor[4], float screen_balance, int
        int other_1 = (primary_channel + 1) % 3;
        int other_2 = (primary_channel + 2) % 3;
 
-       float min = MIN2(pixelColor[other_1], pixelColor[other_2]);
-       float max = MAX2(pixelColor[other_1], pixelColor[other_2]);
-       float val = screen_balance * min + (1.0f - screen_balance) * max;
+       int min_channel = MIN2(other_1, other_2);
+       int max_channel = MAX2(other_1, other_2);
+
+       float val = screen_balance * pixelColor[min_channel] + (1.0f - screen_balance) * pixelColor[max_channel];
 
        return (pixelColor[primary_channel] - val) * fabsf(1.0f - val);
 }
index 31485463f4f674795f9b231dd2b49bd9c04348ec..8b0264da4fa9b41a0e9cbc5e6f5149220448075d 100644 (file)
@@ -2481,6 +2481,7 @@ static void node_composit_buts_keying(uiLayout *layout, bContext *UNUSED(C), Poi
        uiItemR(layout, ptr, "blur_pre", 0, NULL, ICON_NONE);
        uiItemR(layout, ptr, "screen_balance", 0, NULL, ICON_NONE);
        uiItemR(layout, ptr, "despill_factor", 0, NULL, ICON_NONE);
+       uiItemR(layout, ptr, "despill_balance", 0, NULL, ICON_NONE);
        uiItemR(layout, ptr, "edge_kernel_radius", 0, NULL, ICON_NONE);
        uiItemR(layout, ptr, "edge_kernel_tolerance", 0, NULL, ICON_NONE);
        uiItemR(layout, ptr, "clip_black", 0, NULL, ICON_NONE);
index ea894ff7a0dc0bf6addf4bbaeafc1aac2538ebf3..add0c2fe899b07318f0a969d918e78b886270184 100644 (file)
@@ -654,6 +654,7 @@ typedef struct NodeKeyingScreenData {
 typedef struct NodeKeyingData {
        float screen_balance;
        float despill_factor;
+       float despill_balance;
        int edge_kernel_radius;
        float edge_kernel_tolerance;
        float clip_black, clip_white;
index 20310f06466c76c47f5aa40f5b62f56d99fc0e81..3646e4d2a13d9438b6a9ca13d5226789dca9d23e 100644 (file)
@@ -3580,7 +3580,13 @@ static void def_cmp_keying(StructRNA *srna)
        prop = RNA_def_property(srna, "despill_factor", PROP_FLOAT, PROP_FACTOR);
        RNA_def_property_float_sdna(prop, NULL, "despill_factor");
        RNA_def_property_range(prop, 0.0f, 1.0f);
-       RNA_def_property_ui_text(prop, "Despill", "Factor of despilling screen color from image");
+       RNA_def_property_ui_text(prop, "Despill Factor", "Factor of despilling screen color from image");
+       RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+
+       prop = RNA_def_property(srna, "despill_balance", PROP_FLOAT, PROP_FACTOR);
+       RNA_def_property_float_sdna(prop, NULL, "despill_balance");
+       RNA_def_property_range(prop, 0.0f, 1.0f);
+       RNA_def_property_ui_text(prop, "Despill Balance", "Balance between non-key colors used to detect amount of key color to be removed");
        RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
 
        prop = RNA_def_property(srna, "clip_black", PROP_FLOAT, PROP_FACTOR);