Blender V4.5
node_composite_levels.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2006 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <cmath>
10
11#include "BLI_assert.h"
12#include "BLI_math_vector.hh"
14
15#include "UI_interface.hh"
16#include "UI_resources.hh"
17
19
21#include "COM_node_operation.hh"
22
24
25/* **************** LEVELS ******************** */
26
28
30{
31 b.add_input<decl::Color>("Image")
32 .default_value({0.0f, 0.0f, 0.0f, 1.0f})
33 .compositor_domain_priority(0);
34 b.add_output<decl::Float>("Mean");
35 b.add_output<decl::Float>("Std Dev");
36}
37
38static void node_composit_init_view_levels(bNodeTree * /*ntree*/, bNode *node)
39{
40 node->custom1 = 1; /* All channels. */
41}
42
44{
45 layout->prop(ptr, "channel", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
46}
47
48using namespace blender::compositor;
49
51 private:
52 constexpr static float luminance_coefficients_bt709_[3] = {0.2126f, 0.7152f, 0.0722f};
53
54 public:
56
57 void execute() override
58 {
59 if (get_input("Image").is_single_value()) {
61 return;
62 }
63
64 const float mean = compute_mean();
65
66 Result &mean_result = get_result("Mean");
67 if (mean_result.should_compute()) {
68 mean_result.allocate_single_value();
69 mean_result.set_single_value(mean);
70 }
71
72 Result &standard_deviation_result = get_result("Std Dev");
73 if (standard_deviation_result.should_compute()) {
74 const float standard_deviation = compute_standard_deviation(mean);
75 standard_deviation_result.allocate_single_value();
76 standard_deviation_result.set_single_value(standard_deviation);
77 }
78 }
79
81 {
82 Result &standard_deviation_result = get_result("Std Dev");
83 if (standard_deviation_result.should_compute()) {
84 standard_deviation_result.allocate_single_value();
85 standard_deviation_result.set_single_value(0.0f);
86 }
87
88 Result &mean_result = get_result("Mean");
89 if (!mean_result.should_compute()) {
90 return;
91 }
92
93 mean_result.allocate_single_value();
94 const float3 input = float3(get_input("Image").get_single_value<float4>());
95
96 switch (get_channel()) {
98 mean_result.set_single_value(input.x);
99 break;
101 mean_result.set_single_value(input.y);
102 break;
104 mean_result.set_single_value(input.z);
105 break;
107 mean_result.set_single_value(math::dot(input, float3(luminance_coefficients_bt709_)));
108 break;
110 float luminance_coefficients[3];
112 mean_result.set_single_value(math::dot(input, float3(luminance_coefficients)));
113 break;
114 }
115 default:
117 break;
118 }
119 }
120
122 {
123 const Result &input = get_input("Image");
124 return compute_sum() / (input.domain().size.x * input.domain().size.y);
125 }
126
128 {
129 const Result &input = get_input("Image");
130 switch (get_channel()) {
132 return sum_red(context(), input);
134 return sum_green(context(), input);
136 return sum_blue(context(), input);
138 return sum_luminance(context(), input, float3(luminance_coefficients_bt709_));
140 float luminance_coefficients[3];
142 return sum_luminance(context(), input, float3(luminance_coefficients));
143 }
144 default:
146 return 0.0f;
147 }
148 }
149
151 {
152 const Result &input = get_input("Image");
153 const float sum = compute_sum_squared_difference(mean);
154 return std::sqrt(sum / (input.domain().size.x * input.domain().size.y));
155 }
156
157 float compute_sum_squared_difference(float subtrahend)
158 {
159 const Result &input = get_input("Image");
160 switch (get_channel()) {
162 return sum_red_squared_difference(context(), input, subtrahend);
164 return sum_green_squared_difference(context(), input, subtrahend);
166 return sum_blue_squared_difference(context(), input, subtrahend);
169 context(), input, float3(luminance_coefficients_bt709_), subtrahend);
171 float luminance_coefficients[3];
174 context(), input, float3(luminance_coefficients), subtrahend);
175 }
176 default:
178 return 0.0f;
179 }
180 }
181
183 {
184 return static_cast<CMPNodeLevelsChannel>(bnode().custom1);
185 }
186};
187
189{
190 return new LevelsOperation(context, node);
191}
192
193} // namespace blender::nodes::node_composite_levels_cc
194
196{
198
199 static blender::bke::bNodeType ntype;
200
201 cmp_node_type_base(&ntype, "CompositorNodeLevels", CMP_NODE_VIEW_LEVELS);
202 ntype.ui_name = "Levels";
203 ntype.ui_description = "Compute average and standard deviation of pixel values";
204 ntype.enum_name_legacy = "LEVELS";
206 ntype.declare = file_ns::cmp_node_levels_declare;
207 ntype.draw_buttons = file_ns::node_composit_buts_view_levels;
208 ntype.flag |= NODE_PREVIEW;
209 ntype.initfunc = file_ns::node_composit_init_view_levels;
210 ntype.get_compositor_operation = file_ns::get_compositor_operation;
211
213}
#define NODE_CLASS_OUTPUT
Definition BKE_node.hh:434
#define CMP_NODE_VIEW_LEVELS
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
@ NODE_PREVIEW
CMPNodeLevelsChannel
@ CMP_NODE_LEVLES_LUMINANCE
@ CMP_NODE_LEVLES_GREEN
@ CMP_NODE_LEVLES_LUMINANCE_BT709
@ CMP_NODE_LEVLES_RED
@ CMP_NODE_LEVLES_BLUE
BLI_INLINE void IMB_colormanagement_get_luminance_coefficients(float r_rgb[3])
#define NOD_REGISTER_NODE(REGISTER_FUNC)
@ UI_ITEM_R_SPLIT_EMPTY_NAME
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
static T sum(const btAlignedObjectArray< T > &items)
NodeOperation(Context &context, DNode node)
Result & get_result(StringRef identifier)
Definition operation.cc:39
Result & get_input(StringRef identifier) const
Definition operation.cc:138
void set_single_value(const T &value)
#define input
void node_register_type(bNodeType &ntype)
Definition node.cc:2748
float sum_red(Context &context, const Result &result)
float sum_red_squared_difference(Context &context, const Result &result, const float subtrahend)
float sum_luminance(Context &context, const Result &result, const float3 &luminance_coefficients)
float sum_blue_squared_difference(Context &context, const Result &result, const float subtrahend)
float sum_luminance_squared_difference(Context &context, const Result &result, const float3 &luminance_coefficients, const float subtrahend)
float sum_green_squared_difference(Context &context, const Result &result, const float subtrahend)
float sum_green(Context &context, const Result &result)
float sum_blue(Context &context, const Result &result)
T dot(const QuaternionBase< T > &a, const QuaternionBase< T > &b)
static void node_composit_init_view_levels(bNodeTree *, bNode *node)
static void cmp_node_levels_declare(NodeDeclarationBuilder &b)
static void node_composit_buts_view_levels(uiLayout *layout, bContext *, PointerRNA *ptr)
static NodeOperation * get_compositor_operation(Context &context, DNode node)
VecBase< float, 3 > float3
static void register_node_type_cmp_view_levels()
void cmp_node_type_base(blender::bke::bNodeType *ntype, std::string idname, const std::optional< int16_t > legacy_type)
int16_t custom1
Defines a node type.
Definition BKE_node.hh:226
std::string ui_description
Definition BKE_node.hh:232
NodeGetCompositorOperationFunction get_compositor_operation
Definition BKE_node.hh:336
void(* initfunc)(bNodeTree *ntree, bNode *node)
Definition BKE_node.hh:277
const char * enum_name_legacy
Definition BKE_node.hh:235
void(* draw_buttons)(uiLayout *, bContext *C, PointerRNA *ptr)
Definition BKE_node.hh:247
NodeDeclareFunction declare
Definition BKE_node.hh:355
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)
PointerRNA * ptr
Definition wm_files.cc:4226