Blender V4.5
node_composite_convert_color_space.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2021 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "BLI_string.h"
10
11#include "UI_interface.hh"
12#include "UI_resources.hh"
13
15
16#include "GPU_shader.hh"
17
18#include "COM_node_operation.hh"
20#include "COM_utilities.hh"
21
23
25
27
29{
30 b.add_input<decl::Color>("Image")
31 .default_value({1.0f, 1.0f, 1.0f, 1.0f})
32 .compositor_domain_priority(0);
33 b.add_output<decl::Color>("Image");
34}
35
37{
39 const char *first_colorspace = IMB_colormanagement_role_colorspace_name_get(
41 if (first_colorspace && first_colorspace[0]) {
42 STRNCPY(ncs->from_color_space, first_colorspace);
43 STRNCPY(ncs->to_color_space, first_colorspace);
44 }
45 else {
46 ncs->from_color_space[0] = 0;
47 ncs->to_color_space[0] = 0;
48 }
49 node->storage = ncs;
50}
51
53 bContext * /*C*/,
55{
56#ifndef WITH_OPENCOLORIO
57 layout->label(RPT_("Disabled, built without OpenColorIO"), ICON_ERROR);
58#endif
59
60 layout->prop(ptr, "from_color_space", UI_ITEM_R_SPLIT_EMPTY_NAME, std::nullopt, ICON_NONE);
61 layout->prop(ptr, "to_color_space", UI_ITEM_R_SPLIT_EMPTY_NAME, std::nullopt, ICON_NONE);
62}
63
64using namespace blender::compositor;
65
67 public:
69
70 void execute() override
71 {
72 const Result &input_image = this->get_input("Image");
73 if (this->is_identity()) {
74 Result &output_image = this->get_result("Image");
75 output_image.share_data(input_image);
76 return;
77 }
78
79 if (input_image.is_single_value()) {
81 return;
82 }
83 if (this->context().use_gpu()) {
85 }
86 else {
88 }
89 }
90
92 {
93 const char *source = node_storage(bnode()).from_color_space;
94 const char *target = node_storage(bnode()).to_color_space;
95
98 context(), source, target);
99
100 GPUShader *shader = ocio_shader.bind_shader_and_resources();
101
102 /* A null shader indicates that the conversion shader is just a stub implementation since OCIO
103 * is disabled at compile time, so pass the input through in that case. */
104 const Result &input_image = this->get_input("Image");
105 Result &output_image = this->get_result("Image");
106 if (!shader) {
107 output_image.share_data(input_image);
108 return;
109 }
110
111 input_image.bind_as_texture(shader, ocio_shader.input_sampler_name());
112
113 const Domain domain = compute_domain();
114 output_image.allocate_texture(domain);
115 output_image.bind_as_image(shader, ocio_shader.output_image_name());
116
118
119 input_image.unbind_as_texture();
120 output_image.unbind_as_image();
121 ocio_shader.unbind_shader_and_resources();
122 }
123
125 {
126 const char *source = node_storage(bnode()).from_color_space;
127 const char *target = node_storage(bnode()).to_color_space;
129 target);
130
131 Result &input_image = get_input("Image");
132
133 const Domain domain = compute_domain();
134 Result &output_image = get_result("Image");
135 output_image.allocate_texture(domain);
136
137 parallel_for(domain.size, [&](const int2 texel) {
138 output_image.store_pixel(texel, input_image.load_pixel<float4>(texel));
139 });
140
142 static_cast<float *>(output_image.cpu_data().data()),
143 domain.size.x,
144 domain.size.y,
145 input_image.channels_count(),
146 false);
147 IMB_colormanagement_processor_free(color_processor);
148 }
149
151 {
152 const char *source = node_storage(bnode()).from_color_space;
153 const char *target = node_storage(bnode()).to_color_space;
155 target);
156
157 Result &input_image = get_input("Image");
158 float4 color = input_image.get_single_value<float4>();
159
161 IMB_colormanagement_processor_free(color_processor);
162
163 Result &output_image = get_result("Image");
164 output_image.allocate_single_value();
165 output_image.set_single_value(color);
166 }
167
169 {
170 const char *source = node_storage(bnode()).from_color_space;
171 const char *target = node_storage(bnode()).to_color_space;
172
173 if (STREQ(source, target)) {
174 return true;
175 }
176
177 /* Data color spaces ignore any color transformation that gets applied to them. */
179 return true;
180 }
181
182 return false;
183 }
184};
185
187{
188 return new ConvertColorSpaceOperation(context, node);
189}
190
191} // namespace blender::nodes::node_composite_convert_color_space_cc
192
194{
196 static blender::bke::bNodeType ntype;
197
198 cmp_node_type_base(&ntype, "CompositorNodeConvertColorSpace", CMP_NODE_CONVERT_COLOR_SPACE);
199 ntype.ui_name = "Convert Colorspace";
200 ntype.ui_description = "Convert between color spaces";
201 ntype.enum_name_legacy = "CONVERT_COLORSPACE";
203 ntype.declare = file_ns::CMP_NODE_CONVERT_COLOR_SPACE_declare;
204 ntype.draw_buttons = file_ns::node_composit_buts_convert_colorspace;
206 ntype.initfunc = file_ns::node_composit_init_convert_colorspace;
208 ntype, "NodeConvertColorSpace", node_free_standard_storage, node_copy_standard_storage);
209 ntype.get_compositor_operation = file_ns::get_compositor_operation;
210
212}
#define NODE_CLASS_CONVERTER
Definition BKE_node.hh:439
#define NODE_STORAGE_FUNCS(StorageT)
Definition BKE_node.hh:1215
#define CMP_NODE_CONVERT_COLOR_SPACE
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:688
#define STREQ(a, b)
#define RPT_(msgid)
ColormanageProcessor * IMB_colormanagement_colorspace_processor_new(const char *from_colorspace, const char *to_colorspace)
bool IMB_colormanagement_space_name_is_data(const char *name)
void IMB_colormanagement_processor_apply(ColormanageProcessor *cm_processor, float *buffer, int width, int height, int channels, bool predivide)
@ COLOR_ROLE_SCENE_LINEAR
const char * IMB_colormanagement_role_colorspace_name_get(int role)
void IMB_colormanagement_processor_free(ColormanageProcessor *cm_processor)
void IMB_colormanagement_processor_apply_pixel(ColormanageProcessor *cm_processor, float *pixel, int channels)
#define NOD_REGISTER_NODE(REGISTER_FUNC)
@ UI_ITEM_R_SPLIT_EMPTY_NAME
const void * data() const
NodeOperation(Context &context, DNode node)
OCIOColorSpaceConversionShader & get(Context &context, std::string source, std::string target)
Result & get_result(StringRef identifier)
Definition operation.cc:39
Result & get_input(StringRef identifier) const
Definition operation.cc:138
virtual Domain compute_domain()
Definition operation.cc:56
void share_data(const Result &source)
Definition result.cc:401
void allocate_texture(Domain domain, bool from_pool=true)
Definition result.cc:309
void unbind_as_texture() const
Definition result.cc:389
void bind_as_texture(GPUShader *shader, const char *texture_name) const
Definition result.cc:365
void set_single_value(const T &value)
int64_t channels_count() const
void bind_as_image(GPUShader *shader, const char *image_name, bool read=false) const
Definition result.cc:376
void unbind_as_image() const
Definition result.cc:395
bool is_single_value() const
Definition result.cc:625
const T & get_single_value() const
OCIOColorSpaceConversionShaderContainer ocio_color_space_conversion_shaders
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void node_register_type(bNodeType &ntype)
Definition node.cc:2748
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))
Definition node.cc:5603
void node_type_size_preset(bNodeType &ntype, eNodeSizePreset size)
Definition node.cc:5585
void compute_dispatch_threads_at_least(GPUShader *shader, int2 threads_range, int2 local_size=int2(16))
Definition utilities.cc:170
void parallel_for(const int2 range, const Function &function)
static NodeOperation * get_compositor_operation(Context &context, DNode node)
static void node_composit_buts_convert_colorspace(uiLayout *layout, bContext *, PointerRNA *ptr)
VecBase< float, 4 > float4
VecBase< int32_t, 2 > int2
static void register_node_type_cmp_convert_color_space()
void cmp_node_type_base(blender::bke::bNodeType *ntype, std::string idname, const std::optional< int16_t > legacy_type)
void node_free_standard_storage(bNode *node)
Definition node_util.cc:42
void node_copy_standard_storage(bNodeTree *, bNode *dest_node, const bNode *src_node)
Definition node_util.cc:54
void * storage
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 label(blender::StringRef name, int icon)
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:4227