28 N_(
"HSV (Hue, Saturation, Value) color space")},
33 N_(
"YUV (Y - luma, U V - chroma) color space")},
38 N_(
"YCbCr (Y - luma, Cb - blue-difference chroma, Cr - red-difference chroma) color space")},
39 {0,
nullptr, 0,
nullptr,
nullptr},
52 {0,
nullptr, 0,
nullptr,
nullptr},
65 {0,
nullptr, 0,
nullptr,
nullptr},
78 {0,
nullptr, 0,
nullptr,
nullptr},
91 {0,
nullptr, 0,
nullptr,
nullptr},
99 "Limit by single channel"},
104 "Limit by maximum of other channels"},
105 {0,
nullptr, 0,
nullptr,
nullptr},
110 b.use_custom_socket_order();
111 b.allow_any_socket_order();
112 b.is_function_node();
113 b.add_input<
decl::Color>(
"Image").default_value({1.0f, 1.0f, 1.0f, 1.0f}).hide_value();
114 b.add_output<
decl::Color>(
"Image").align_with_previous();
122 .description(
"Channel values lower than this minimum are keyed");
128 .description(
"Channel values higher than this maximum are not keyed");
172 .make_available([](
bNode &node) {
174 node,
SOCK_IN,
"Limit Method");
185 return params.menu_input_may_be(
"Limit Method",
194 .make_available([](
bNode &node) {
196 node,
SOCK_IN,
"Limit Method");
207 return params.menu_input_may_be(
"Limit Method",
216 .make_available([](
bNode &node) {
218 node,
SOCK_IN,
"Limit Method");
229 return params.menu_input_may_be(
"Limit Method",
238 .make_available([](
bNode &node) {
240 node,
SOCK_IN,
"Limit Method");
251 return params.menu_input_may_be(
"Limit Method",
276 switch (color_space) {
302 const int rgb_channel,
303 const int hsv_channel,
304 const int yuv_channel,
305 const int ycc_channel)
307 switch (color_space) {
325 const int matte_channel,
326 const int limit_channel)
331 return int2((matte_channel + 1) % 3, (matte_channel + 2) % 3);
335 return int2(limit_channel);
342 const int rgb_key_channel,
343 const int hsv_key_channel,
344 const int yuv_key_channel,
345 const int ycc_key_channel,
347 const int rgb_limit_channel,
348 const int hsv_limit_channel,
349 const int yuv_limit_channel,
350 const int ycc_limit_channel,
356 color_space, rgb_key_channel, hsv_key_channel, yuv_key_channel, ycc_key_channel);
358 color_space, rgb_limit_channel, hsv_limit_channel, yuv_limit_channel, ycc_limit_channel);
361 float matte_value = channels[matte_channel];
362 float limit_value =
math::max(channels[limit_channels.x], channels[limit_channels.y]);
364 float alpha = 1.0f - (matte_value - limit_value);
365 if (alpha > maximum) {
368 else if (alpha < minimum) {
372 alpha = (alpha - minimum) / (maximum - minimum);
376 output_color =
color * matte;
381 static auto function =
382 mf::build::detail::build_multi_function_with_n_inputs_two_outputs<float4, float>(
385 const float &minimum,
386 const float &maximum,
398 float &matte) ->
void {
403 rgb_key_channel.
value,
404 hsv_key_channel.
value,
405 yuv_key_channel.
value,
406 ycc_key_channel.
value,
408 rgb_limit_channel.
value,
409 hsv_limit_channel.
value,
410 yuv_limit_channel.
value,
411 ycc_limit_channel.
value,
415 mf::build::exec_presets::SomeSpanOrSingle<0>(),
443 ntype.
ui_description =
"Create matte based on differences in color channels";
446 ntype.
declare = file_ns::cmp_node_channel_matte_declare;
448 ntype.
initfunc = file_ns::node_composit_init_channel_matte;
451 ntype.
gpu_fn = file_ns::node_gpu_material;
#define CMP_NODE_CHANNEL_MATTE
void rgb_to_hsv_v(const float rgb[3], float r_hsv[3])
#define BLI_YUV_ITU_BT709
void rgb_to_ycc(float r, float g, float b, float *r_y, float *r_cb, float *r_cr, int colorspace)
void rgb_to_yuv(float r, float g, float b, float *r_y, float *r_u, float *r_v, int colorspace)
#define BLI_YCC_ITU_BT709
#define BLT_I18NCONTEXT_COLOR
CMPNodeChannelMatteLimitAlgorithm
@ CMP_NODE_CHANNEL_MATTE_LIMIT_ALGORITHM_MAX
@ CMP_NODE_CHANNEL_MATTE_LIMIT_ALGORITHM_SINGLE
CMPNodeChannelMatteColorSpace
@ CMP_NODE_CHANNEL_MATTE_CS_YUV
@ CMP_NODE_CHANNEL_MATTE_CS_RGB
@ CMP_NODE_CHANNEL_MATTE_CS_HSV
@ CMP_NODE_CHANNEL_MATTE_CS_YCC
bool GPU_stack_link(GPUMaterial *mat, const bNode *node, const char *name, GPUNodeStack *in, GPUNodeStack *out,...)
#define NOD_REGISTER_NODE(REGISTER_FUNC)
void set_matching_fn(const mf::MultiFunction *fn)
std::optional< std::string > translation_context
void * MEM_callocN(size_t len, const char *str)
bNodeSocket * node_find_socket(bNode &node, eNodeSocketInOut in_out, StringRef identifier)
void node_register_type(bNodeType &ntype)
void node_type_storage(bNodeType &ntype, std::optional< StringRefNull > storagename, void(*freefunc)(bNode *node), void(*copyfunc)(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node))
T min(const T &a, const T &b)
T max(const T &a, const T &b)
static const EnumPropertyItem hsv_channel_items[]
static int node_gpu_material(GPUMaterial *material, bNode *node, bNodeExecData *, GPUNodeStack *inputs, GPUNodeStack *outputs)
static float3 compute_channels(const float4 color, const CMPNodeChannelMatteColorSpace color_space)
static const EnumPropertyItem yuv_channel_items[]
static void cmp_node_channel_matte_declare(NodeDeclarationBuilder &b)
static const EnumPropertyItem color_space_items[]
static void channel_key(const float4 color, const float minimum, const float maximum, const CMPNodeChannelMatteColorSpace color_space, const int rgb_key_channel, const int hsv_key_channel, const int yuv_key_channel, const int ycc_key_channel, const CMPNodeChannelMatteLimitAlgorithm limit_method, const int rgb_limit_channel, const int hsv_limit_channel, const int yuv_limit_channel, const int ycc_limit_channel, float4 &output_color, float &matte)
static int2 compute_limit_channels(const CMPNodeChannelMatteLimitAlgorithm limit_method, const int matte_channel, const int limit_channel)
static int get_channel_index(const CMPNodeChannelMatteColorSpace color_space, const int rgb_channel, const int hsv_channel, const int yuv_channel, const int ycc_channel)
static const EnumPropertyItem rgb_channel_items[]
static void node_composit_init_channel_matte(bNodeTree *, bNode *node)
static void node_build_multi_function(blender::nodes::NodeMultiFunctionBuilder &builder)
static const EnumPropertyItem limit_method_items[]
static const EnumPropertyItem ycbcr_channel_items[]
VecBase< float, 4 > float4
VecBase< int32_t, 2 > int2
VecBase< float, 3 > float3
static void register_node_type_cmp_channel_matte()
void cmp_node_type_base(blender::bke::bNodeType *ntype, std::string idname, const std::optional< int16_t > legacy_type)
static blender::bke::bNodeSocketTemplate outputs[]
static blender::bke::bNodeSocketTemplate inputs[]
void node_free_standard_storage(bNode *node)
void node_copy_standard_storage(bNodeTree *, bNode *dest_node, const bNode *src_node)
VecBase< T, 3 > xyz() const
std::string ui_description
void(* initfunc)(bNodeTree *ntree, bNode *node)
NodeGPUExecFunction gpu_fn
NodeMultiFunctionBuildFunction build_multi_function
const char * enum_name_legacy
NodeDeclareFunction declare
CCL_NAMESPACE_BEGIN struct Window V