Blender V4.3
COM_ImageNode.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "BLI_assert.h"
6
8#include "COM_ImageNode.h"
10
14
15namespace blender::compositor {
16
17ImageNode::ImageNode(bNode *editor_node) : Node(editor_node)
18{
19 /* pass */
20}
21NodeOperation *ImageNode::do_multilayer_check(NodeConverter &converter,
22 const CompositorContext &context,
23 const char *layer_name,
24 const char *pass_name,
25 Image *image,
26 ImageUser *user,
27 int framenumber,
28 int outputsocket_index,
29 DataType datatype) const
30{
31 NodeOutput *output_socket = this->get_output_socket(outputsocket_index);
32 MultilayerBaseOperation *operation = nullptr;
33 switch (datatype) {
34 case DataType::Value:
35 operation = new MultilayerValueOperation();
36 break;
38 operation = new MultilayerVectorOperation();
39 break;
40 case DataType::Color:
41 operation = new MultilayerColorOperation();
42 break;
43 default:
44 break;
45 }
46 operation->set_image(image);
47 operation->set_image_user(*user);
48 operation->set_framenumber(framenumber);
49 operation->set_render_data(context.get_render_data());
50 operation->set_view_name(context.get_view_name());
51 operation->set_layer_name(layer_name);
52 operation->set_pass_name(pass_name);
53
54 converter.add_operation(operation);
55 converter.map_output_socket(output_socket, operation->get_output_socket());
56
57 return operation;
58}
59
61 const CompositorContext &context) const
62{
64 NodeOutput *output_image = this->get_output_socket(0);
65 const bNode *editor_node = this->get_bnode();
66 Image *image = (Image *)editor_node->id;
67 ImageUser *imageuser = (ImageUser *)editor_node->storage;
68 int framenumber = context.get_framenumber();
69 bool output_straight_alpha = (editor_node->custom1 & CMP_NODE_IMAGE_USE_STRAIGHT_OUTPUT) != 0;
70 BKE_image_user_frame_calc(image, imageuser, context.get_framenumber());
71 /* Force a load, we assume #ImageUser index will be set OK anyway. */
72 if (image && image->type == IMA_TYPE_MULTILAYER) {
73 bool is_multilayer_ok = false;
74 ImBuf *ibuf = BKE_image_acquire_ibuf(image, imageuser, nullptr);
75 RenderResult *rr = BKE_image_acquire_renderresult(nullptr, image);
76 if (rr) {
77 RenderLayer *rl = (RenderLayer *)BLI_findlink(&rr->layers, imageuser->layer);
78 if (rl) {
79 is_multilayer_ok = true;
80
81 for (int64_t index = 0; index < outputs_.size(); index++) {
82 NodeOutput *socket = outputs_[index];
83 NodeOperation *operation = nullptr;
84 bNodeSocket *bnode_socket = socket->get_bnode_socket();
85 NodeImageLayer *storage = (NodeImageLayer *)bnode_socket->storage;
87 &rl->passes, storage->pass_name, offsetof(RenderPass, name));
88
89 if (STREQ(storage->pass_name, RE_PASSNAME_COMBINED) &&
90 STREQ(bnode_socket->name, "Alpha"))
91 {
92 /* Alpha output is already handled with the associated combined output. */
93 continue;
94 }
95
96 if (rpass) {
97 switch (rpass->channels) {
98 case 1:
99 operation = do_multilayer_check(converter,
100 context,
101 rl->name,
102 rpass->name,
103 image,
104 imageuser,
105 framenumber,
106 index,
108 break;
109 /* using image operations for both 3 and 4 channels (RGB and RGBA respectively) */
110 /* XXX any way to detect actual vector images? */
111 case 3:
112 operation = do_multilayer_check(converter,
113 context,
114 rl->name,
115 rpass->name,
116 image,
117 imageuser,
118 framenumber,
119 index,
121 break;
122 case 4:
123 operation = do_multilayer_check(converter,
124 context,
125 rl->name,
126 rpass->name,
127 image,
128 imageuser,
129 framenumber,
130 index,
132 break;
133 default:
134 /* dummy operation is added below */
135 break;
136 }
137 if (operation && index == 0) {
138 converter.add_preview(operation->get_output_socket());
139 }
140 if (operation && STREQ(rpass->name, RE_PASSNAME_COMBINED) &&
141 !(bnode_socket->flag & SOCK_UNAVAIL))
142 {
143 for (NodeOutput *alpha_socket : get_output_sockets()) {
144 bNodeSocket *bnode_alpha_socket = alpha_socket->get_bnode_socket();
145 if (!STREQ(bnode_alpha_socket->name, "Alpha")) {
146 continue;
147 }
148 NodeImageLayer *alpha_storage = (NodeImageLayer *)bnode_socket->storage;
149 if (!STREQ(alpha_storage->pass_name, RE_PASSNAME_COMBINED)) {
150 continue;
151 }
152 SeparateChannelOperation *separate_operation;
153 separate_operation = new SeparateChannelOperation();
154 separate_operation->set_channel(3);
155 converter.add_operation(separate_operation);
156 converter.add_link(operation->get_output_socket(),
157 separate_operation->get_input_socket(0));
158 converter.map_output_socket(alpha_socket, separate_operation->get_output_socket());
159 break;
160 }
161 }
162 }
163
164 /* In case we can't load the layer. */
165 if (operation == nullptr) {
166 converter.set_invalid_output(get_output_socket(index));
167 }
168 }
169 }
170 }
171 BKE_image_release_renderresult(nullptr, image, rr);
172 BKE_image_release_ibuf(image, ibuf, nullptr);
173
174 /* without this, multilayer that fail to load will crash blender #32490. */
175 if (is_multilayer_ok == false) {
176 for (NodeOutput *output : get_output_sockets()) {
177 converter.set_invalid_output(output);
178 }
179 }
180 }
181 else {
182 const int64_t number_of_outputs = get_output_sockets().size();
183 if (number_of_outputs > 0) {
184 ImageOperation *operation = new ImageOperation();
185 operation->set_image(image);
186 operation->set_image_user(*imageuser);
187 operation->set_framenumber(framenumber);
188 operation->set_render_data(context.get_render_data());
189 operation->set_view_name(context.get_view_name());
190 converter.add_operation(operation);
191
192 if (output_straight_alpha) {
193 NodeOperation *alpha_convert_operation = new ConvertPremulToStraightOperation();
194
195 converter.add_operation(alpha_convert_operation);
196 converter.map_output_socket(output_image, alpha_convert_operation->get_output_socket());
197 converter.add_link(operation->get_output_socket(0),
198 alpha_convert_operation->get_input_socket(0));
199 }
200 else {
201 converter.map_output_socket(output_image, operation->get_output_socket());
202 }
203
204 converter.add_preview(operation->get_output_socket());
205 }
206
207 if (number_of_outputs > 1) {
208 NodeOutput *alpha_image = this->get_output_socket(1);
209 ImageAlphaOperation *alpha_operation = new ImageAlphaOperation();
210 alpha_operation->set_image(image);
211 alpha_operation->set_image_user(*imageuser);
212 alpha_operation->set_framenumber(framenumber);
213 alpha_operation->set_render_data(context.get_render_data());
214 alpha_operation->set_view_name(context.get_view_name());
215 converter.add_operation(alpha_operation);
216
217 converter.map_output_socket(alpha_image, alpha_operation->get_output_socket());
218 }
219 else {
220 /* happens when unlinking image datablock from multilayer node */
221 for (int i = 2; i < number_of_outputs; i++) {
222 NodeOutput *output = this->get_output_socket(i);
223 NodeOperation *operation = nullptr;
224 switch (output->get_data_type()) {
225 case DataType::Value: {
226 SetValueOperation *valueoperation = new SetValueOperation();
227 valueoperation->set_value(0.0f);
228 operation = valueoperation;
229 break;
230 }
231 case DataType::Vector: {
232 SetVectorOperation *vectoroperation = new SetVectorOperation();
233 vectoroperation->setX(0.0f);
234 vectoroperation->setY(0.0f);
235 vectoroperation->setW(0.0f);
236 operation = vectoroperation;
237 break;
238 }
239 case DataType::Color: {
240 SetColorOperation *coloroperation = new SetColorOperation();
241 coloroperation->set_channel1(0.0f);
242 coloroperation->set_channel2(0.0f);
243 coloroperation->set_channel3(0.0f);
244 coloroperation->set_channel4(0.0f);
245 operation = coloroperation;
246 break;
247 }
248 case DataType::Float2:
249 /* An internal type that needn't be handled. */
251 break;
252 }
253
254 if (operation) {
255 /* not supporting multiview for this generic case */
256 converter.add_operation(operation);
257 converter.map_output_socket(output, operation->get_output_socket());
258 }
259 }
260 }
261 }
262} // namespace blender::compositor
263
264} // namespace blender::compositor
ImBuf * BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
void BKE_image_user_frame_calc(Image *ima, ImageUser *iuser, int cfra)
void BKE_image_release_ibuf(Image *ima, ImBuf *ibuf, void *lock)
void BKE_image_release_renderresult(Scene *scene, Image *ima, RenderResult *render_result)
RenderResult * BKE_image_acquire_renderresult(Scene *scene, Image *ima)
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
void * BLI_findstring(const struct ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
#define STREQ(a, b)
@ IMA_TYPE_MULTILAYER
@ CMP_NODE_IMAGE_USE_STRAIGHT_OUTPUT
@ SOCK_UNAVAIL
#define RE_PASSNAME_COMBINED
void set_render_data(const RenderData *rd)
void set_image_user(const ImageUser &imageuser)
void set_view_name(const char *view_name)
Overall context of the compositor.
ImageNode(bNode *editor_node)
void convert_to_operations(NodeConverter &converter, const CompositorContext &context) const override
convert node to operation
void add_link(NodeOperationOutput *from, NodeOperationInput *to)
void map_output_socket(NodeOutput *node_socket, NodeOperationOutput *operation_socket)
void add_preview(NodeOperationOutput *output)
void add_operation(NodeOperation *operation)
NodeOperation * set_invalid_output(NodeOutput *output)
NodeOperation contains calculation logic.
NodeOperationOutput * get_output_socket(unsigned int index=0)
NodeOperationInput * get_input_socket(unsigned int index)
NodeOutput are sockets that can send data/input.
Definition COM_Node.h:239
bNodeSocket * get_bnode_socket() const
Definition COM_Node.h:257
NodeOutput * get_output_socket(unsigned int index=0) const
Definition COM_Node.cc:85
const bNode * get_bnode() const
get the reference to the SDNA bNode struct
Definition COM_Node.h:65
Span< NodeOutput * > get_output_sockets() const
get access to the vector of input sockets
Definition COM_Node.h:109
Vector< NodeOutput * > outputs_
the list of actual output-sockets
Definition COM_Node.h:56
#define offsetof(t, d)
DataType
possible data types for sockets
Definition COM_defines.h:21
@ Vector
Vector data type.
@ Float2
Float2 data type.
__int64 int64_t
Definition stdint.h:89
ListBase passes
Definition RE_pipeline.h:97
char name[RE_MAXNAME]
Definition RE_pipeline.h:89
char name[64]
Definition RE_pipeline.h:58
ListBase layers
int16_t custom1
struct ID * id
void * storage