diff options
Diffstat (limited to 'source/blender/nodes/composite/nodes/node_composite_levels.cc')
-rw-r--r-- | source/blender/nodes/composite/nodes/node_composite_levels.cc | 144 |
1 files changed, 141 insertions, 3 deletions
diff --git a/source/blender/nodes/composite/nodes/node_composite_levels.cc b/source/blender/nodes/composite/nodes/node_composite_levels.cc index a4fe1f33813..4c901372b9f 100644 --- a/source/blender/nodes/composite/nodes/node_composite_levels.cc +++ b/source/blender/nodes/composite/nodes/node_composite_levels.cc @@ -5,9 +5,18 @@ * \ingroup cmpnodes */ +#include <cmath> + +#include "BLI_assert.h" +#include "BLI_math_vec_types.hh" +#include "BLI_math_vector.hh" + #include "UI_interface.h" #include "UI_resources.h" +#include "IMB_colormanagement.h" + +#include "COM_algorithm_parallel_reduction.hh" #include "COM_node_operation.hh" #include "node_composite_util.hh" @@ -18,7 +27,9 @@ namespace blender::nodes::node_composite_levels_cc { static void cmp_node_levels_declare(NodeDeclarationBuilder &b) { - b.add_input<decl::Color>(N_("Image")).default_value({0.0f, 0.0f, 0.0f, 1.0f}); + b.add_input<decl::Color>(N_("Image")) + .default_value({0.0f, 0.0f, 0.0f, 1.0f}) + .compositor_domain_priority(0); b.add_output<decl::Float>(N_("Mean")); b.add_output<decl::Float>(N_("Std Dev")); } @@ -36,13 +47,140 @@ static void node_composit_buts_view_levels(uiLayout *layout, bContext * /*C*/, P using namespace blender::realtime_compositor; class LevelsOperation : public NodeOperation { + private: + constexpr static float luminance_coefficients_bt709_[3] = {0.2126f, 0.7152f, 0.0722f}; + public: using NodeOperation::NodeOperation; void execute() override { - get_result("Mean").allocate_invalid(); - get_result("Std Dev").allocate_invalid(); + if (get_input("Image").is_single_value()) { + execute_single_value(); + return; + } + + const float mean = compute_mean(); + + Result &mean_result = get_result("Mean"); + if (mean_result.should_compute()) { + mean_result.allocate_single_value(); + mean_result.set_float_value(mean); + } + + Result &standard_deviation_result = get_result("Std Dev"); + if (standard_deviation_result.should_compute()) { + const float standard_deviation = compute_standard_deviation(mean); + standard_deviation_result.allocate_single_value(); + standard_deviation_result.set_float_value(standard_deviation); + } + } + + void execute_single_value() + { + Result &standard_deviation_result = get_result("Std Dev"); + if (standard_deviation_result.should_compute()) { + standard_deviation_result.allocate_single_value(); + standard_deviation_result.set_float_value(0.0f); + } + + Result &mean_result = get_result("Mean"); + if (!mean_result.should_compute()) { + return; + } + + mean_result.allocate_single_value(); + const float3 input = float3(get_input("Image").get_color_value()); + + switch (get_channel()) { + case CMP_NODE_LEVLES_RED: + mean_result.set_float_value(input.x); + break; + case CMP_NODE_LEVLES_GREEN: + mean_result.set_float_value(input.y); + break; + case CMP_NODE_LEVLES_BLUE: + mean_result.set_float_value(input.z); + break; + case CMP_NODE_LEVLES_LUMINANCE_BT709: + mean_result.set_float_value(math::dot(input, float3(luminance_coefficients_bt709_))); + break; + case CMP_NODE_LEVLES_LUMINANCE: { + float luminance_coefficients[3]; + IMB_colormanagement_get_luminance_coefficients(luminance_coefficients); + mean_result.set_float_value(math::dot(input, float3(luminance_coefficients))); + break; + } + default: + BLI_assert_unreachable(); + break; + } + } + + float compute_mean() + { + const Result &input = get_input("Image"); + return compute_sum() / (input.domain().size.x * input.domain().size.y); + } + + float compute_sum() + { + const Result &input = get_input("Image"); + switch (get_channel()) { + case CMP_NODE_LEVLES_RED: + return sum_red(context(), input.texture()); + case CMP_NODE_LEVLES_GREEN: + return sum_green(context(), input.texture()); + case CMP_NODE_LEVLES_BLUE: + return sum_blue(context(), input.texture()); + case CMP_NODE_LEVLES_LUMINANCE_BT709: + return sum_luminance(context(), input.texture(), float3(luminance_coefficients_bt709_)); + case CMP_NODE_LEVLES_LUMINANCE: { + float luminance_coefficients[3]; + IMB_colormanagement_get_luminance_coefficients(luminance_coefficients); + return sum_luminance(context(), input.texture(), float3(luminance_coefficients)); + } + default: + BLI_assert_unreachable(); + return 0.0f; + } + } + + float compute_standard_deviation(float mean) + { + const Result &input = get_input("Image"); + const float sum = compute_sum_squared_difference(mean); + return std::sqrt(sum / (input.domain().size.x * input.domain().size.y)); + } + + float compute_sum_squared_difference(float subtrahend) + { + const Result &input = get_input("Image"); + switch (get_channel()) { + case CMP_NODE_LEVLES_RED: + return sum_red_squared_difference(context(), input.texture(), subtrahend); + case CMP_NODE_LEVLES_GREEN: + return sum_green_squared_difference(context(), input.texture(), subtrahend); + case CMP_NODE_LEVLES_BLUE: + return sum_blue_squared_difference(context(), input.texture(), subtrahend); + case CMP_NODE_LEVLES_LUMINANCE_BT709: + return sum_luminance_squared_difference( + context(), input.texture(), float3(luminance_coefficients_bt709_), subtrahend); + case CMP_NODE_LEVLES_LUMINANCE: { + float luminance_coefficients[3]; + IMB_colormanagement_get_luminance_coefficients(luminance_coefficients); + return sum_luminance_squared_difference( + context(), input.texture(), float3(luminance_coefficients), subtrahend); + } + default: + BLI_assert_unreachable(); + return 0.0f; + } + } + + CMPNodeLevelsChannel get_channel() + { + return static_cast<CMPNodeLevelsChannel>(bnode().custom1); } }; |