Blender  V3.3
COM_ImageNode.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2011 Blender Foundation. */
3 
4 #include "COM_ImageNode.h"
5 #include "COM_ConvertOperation.h"
7 
10 #include "COM_SetVectorOperation.h"
11 
12 namespace blender::compositor {
13 
14 ImageNode::ImageNode(bNode *editor_node) : Node(editor_node)
15 {
16  /* pass */
17 }
18 NodeOperation *ImageNode::do_multilayer_check(NodeConverter &converter,
19  RenderLayer *render_layer,
20  RenderPass *render_pass,
21  Image *image,
22  ImageUser *user,
23  int framenumber,
24  int outputsocket_index,
25  int view,
26  DataType datatype) const
27 {
28  NodeOutput *output_socket = this->get_output_socket(outputsocket_index);
29  MultilayerBaseOperation *operation = nullptr;
30  switch (datatype) {
31  case DataType::Value:
32  operation = new MultilayerValueOperation(render_layer, render_pass, view);
33  break;
34  case DataType::Vector:
35  operation = new MultilayerVectorOperation(render_layer, render_pass, view);
36  break;
37  case DataType::Color:
38  operation = new MultilayerColorOperation(render_layer, render_pass, view);
39  break;
40  default:
41  break;
42  }
43  operation->set_image(image);
44  operation->set_image_user(user);
45  operation->set_framenumber(framenumber);
46 
47  converter.add_operation(operation);
48  converter.map_output_socket(output_socket, operation->get_output_socket());
49 
50  return operation;
51 }
52 
54  const CompositorContext &context) const
55 {
57  NodeOutput *output_image = this->get_output_socket(0);
58  bNode *editor_node = this->get_bnode();
59  Image *image = (Image *)editor_node->id;
60  ImageUser *imageuser = (ImageUser *)editor_node->storage;
61  int framenumber = context.get_framenumber();
62  bool output_straight_alpha = (editor_node->custom1 & CMP_NODE_IMAGE_USE_STRAIGHT_OUTPUT) != 0;
63  BKE_image_user_frame_calc(image, imageuser, context.get_framenumber());
64  /* force a load, we assume iuser index will be set OK anyway */
65  if (image && image->type == IMA_TYPE_MULTILAYER) {
66  bool is_multilayer_ok = false;
67  ImBuf *ibuf = BKE_image_acquire_ibuf(image, imageuser, nullptr);
68  if (image->rr) {
69  RenderLayer *rl = (RenderLayer *)BLI_findlink(&image->rr->layers, imageuser->layer);
70  if (rl) {
71  is_multilayer_ok = true;
72 
73  for (int64_t index = 0; index < outputs_.size(); index++) {
74  NodeOutput *socket = outputs_[index];
75  NodeOperation *operation = nullptr;
76  bNodeSocket *bnode_socket = socket->get_bnode_socket();
77  NodeImageLayer *storage = (NodeImageLayer *)bnode_socket->storage;
79  &rl->passes, storage->pass_name, offsetof(RenderPass, name));
80  int view = 0;
81 
82  if (STREQ(storage->pass_name, RE_PASSNAME_COMBINED) &&
83  STREQ(bnode_socket->name, "Alpha")) {
84  /* Alpha output is already handled with the associated combined output. */
85  continue;
86  }
87 
88  /* returns the image view to use for the current active view */
89  if (BLI_listbase_count_at_most(&image->rr->views, 2) > 1) {
90  const int view_image = imageuser->view;
91  const bool is_allview = (view_image == 0); /* if view selected == All (0) */
92 
93  if (is_allview) {
94  /* heuristic to match image name with scene names
95  * check if the view name exists in the image */
97  &image->rr->views, context.get_view_name(), offsetof(RenderView, name));
98  if (view == -1) {
99  view = 0;
100  }
101  }
102  else {
103  view = view_image - 1;
104  }
105  }
106 
107  if (rpass) {
108  switch (rpass->channels) {
109  case 1:
110  operation = do_multilayer_check(converter,
111  rl,
112  rpass,
113  image,
114  imageuser,
115  framenumber,
116  index,
117  view,
119  break;
120  /* using image operations for both 3 and 4 channels (RGB and RGBA respectively) */
121  /* XXX any way to detect actual vector images? */
122  case 3:
123  operation = do_multilayer_check(converter,
124  rl,
125  rpass,
126  image,
127  imageuser,
128  framenumber,
129  index,
130  view,
132  break;
133  case 4:
134  operation = do_multilayer_check(converter,
135  rl,
136  rpass,
137  image,
138  imageuser,
139  framenumber,
140  index,
141  view,
143  break;
144  default:
145  /* dummy operation is added below */
146  break;
147  }
148  if (index == 0 && operation) {
149  converter.add_preview(operation->get_output_socket());
150  }
151  if (STREQ(rpass->name, RE_PASSNAME_COMBINED) && !(bnode_socket->flag & SOCK_UNAVAIL)) {
152  for (NodeOutput *alpha_socket : get_output_sockets()) {
153  bNodeSocket *bnode_alpha_socket = alpha_socket->get_bnode_socket();
154  if (!STREQ(bnode_alpha_socket->name, "Alpha")) {
155  continue;
156  }
157  NodeImageLayer *alpha_storage = (NodeImageLayer *)bnode_socket->storage;
158  if (!STREQ(alpha_storage->pass_name, RE_PASSNAME_COMBINED)) {
159  continue;
160  }
161  SeparateChannelOperation *separate_operation;
162  separate_operation = new SeparateChannelOperation();
163  separate_operation->set_channel(3);
164  converter.add_operation(separate_operation);
165  converter.add_link(operation->get_output_socket(),
166  separate_operation->get_input_socket(0));
167  converter.map_output_socket(alpha_socket, separate_operation->get_output_socket());
168  break;
169  }
170  }
171  }
172 
173  /* In case we can't load the layer. */
174  if (operation == nullptr) {
175  converter.set_invalid_output(get_output_socket(index));
176  }
177  }
178  }
179  }
180  BKE_image_release_ibuf(image, ibuf, nullptr);
181 
182  /* without this, multilayer that fail to load will crash blender T32490. */
183  if (is_multilayer_ok == false) {
185  converter.set_invalid_output(output);
186  }
187  }
188  }
189  else {
190  const int64_t number_of_outputs = get_output_sockets().size();
191  if (number_of_outputs > 0) {
192  ImageOperation *operation = new ImageOperation();
193  operation->set_image(image);
194  operation->set_image_user(imageuser);
195  operation->set_framenumber(framenumber);
196  operation->set_render_data(context.get_render_data());
197  operation->set_view_name(context.get_view_name());
198  converter.add_operation(operation);
199 
200  if (output_straight_alpha) {
201  NodeOperation *alpha_convert_operation = new ConvertPremulToStraightOperation();
202 
203  converter.add_operation(alpha_convert_operation);
204  converter.map_output_socket(output_image, alpha_convert_operation->get_output_socket());
205  converter.add_link(operation->get_output_socket(0),
206  alpha_convert_operation->get_input_socket(0));
207  }
208  else {
209  converter.map_output_socket(output_image, operation->get_output_socket());
210  }
211 
212  converter.add_preview(operation->get_output_socket());
213  }
214 
215  if (number_of_outputs > 1) {
216  NodeOutput *alpha_image = this->get_output_socket(1);
217  ImageAlphaOperation *alpha_operation = new ImageAlphaOperation();
218  alpha_operation->set_image(image);
219  alpha_operation->set_image_user(imageuser);
220  alpha_operation->set_framenumber(framenumber);
221  alpha_operation->set_render_data(context.get_render_data());
222  alpha_operation->set_view_name(context.get_view_name());
223  converter.add_operation(alpha_operation);
224 
225  converter.map_output_socket(alpha_image, alpha_operation->get_output_socket());
226  }
227  if (number_of_outputs > 2) {
228  NodeOutput *depth_image = this->get_output_socket(2);
229  ImageDepthOperation *depth_operation = new ImageDepthOperation();
230  depth_operation->set_image(image);
231  depth_operation->set_image_user(imageuser);
232  depth_operation->set_framenumber(framenumber);
233  depth_operation->set_render_data(context.get_render_data());
234  depth_operation->set_view_name(context.get_view_name());
235  converter.add_operation(depth_operation);
236 
237  converter.map_output_socket(depth_image, depth_operation->get_output_socket());
238  }
239  if (number_of_outputs > 3) {
240  /* happens when unlinking image datablock from multilayer node */
241  for (int i = 3; i < number_of_outputs; i++) {
242  NodeOutput *output = this->get_output_socket(i);
243  NodeOperation *operation = nullptr;
244  switch (output->get_data_type()) {
245  case DataType::Value: {
246  SetValueOperation *valueoperation = new SetValueOperation();
247  valueoperation->set_value(0.0f);
248  operation = valueoperation;
249  break;
250  }
251  case DataType::Vector: {
252  SetVectorOperation *vectoroperation = new SetVectorOperation();
253  vectoroperation->setX(0.0f);
254  vectoroperation->setY(0.0f);
255  vectoroperation->setW(0.0f);
256  operation = vectoroperation;
257  break;
258  }
259  case DataType::Color: {
260  SetColorOperation *coloroperation = new SetColorOperation();
261  coloroperation->set_channel1(0.0f);
262  coloroperation->set_channel2(0.0f);
263  coloroperation->set_channel3(0.0f);
264  coloroperation->set_channel4(0.0f);
265  operation = coloroperation;
266  break;
267  }
268  }
269 
270  if (operation) {
271  /* not supporting multiview for this generic case */
272  converter.add_operation(operation);
273  converter.map_output_socket(output, operation->get_output_socket());
274  }
275  }
276  }
277  }
278 } // namespace blender::compositor
279 
280 } // namespace blender::compositor
void BKE_image_release_ibuf(struct Image *ima, struct ImBuf *ibuf, void *lock)
struct ImBuf * BKE_image_acquire_ibuf(struct Image *ima, struct ImageUser *iuser, void **r_lock)
void BKE_image_user_frame_calc(struct Image *ima, struct ImageUser *iuser, int cfra)
int BLI_listbase_count_at_most(const struct ListBase *listbase, int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
int BLI_findstringindex(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)
void * BLI_findstring(const struct ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
#define STREQ(a, b)
@ IMA_TYPE_MULTILAYER
#define CMP_NODE_IMAGE_USE_STRAIGHT_OUTPUT
@ SOCK_UNAVAIL
#define RE_PASSNAME_COMBINED
static AppView * view
void set_render_data(const RenderData *rd)
void set_image_user(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:238
bNodeSocket * get_bnode_socket() const
Definition: COM_Node.h:256
NodeOutput * get_output_socket(unsigned int index=0) const
Definition: COM_Node.cc:84
bNode * get_bnode() const
get the reference to the SDNA bNode struct
Definition: COM_Node.h:64
const Vector< NodeOutput * > & get_output_sockets() const
get access to the vector of input sockets
Definition: COM_Node.h:108
Vector< NodeOutput * > outputs_
the list of actual output-sockets
Definition: COM_Node.h:55
depth_tx normal_tx diffuse_light_tx specular_light_tx volume_light_tx environment_tx ambient_occlusion_tx aov_value_tx in_weight_img image(1, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D_ARRAY, "out_weight_img") .image(3
DataType
possible data types for sockets
Definition: COM_defines.h:30
@ Vector
Vector data type.
ccl_global KernelShaderEvalInput ccl_global float * output
__int64 int64_t
Definition: stdint.h:89
char pass_name[64]
ListBase passes
Definition: RE_pipeline.h:95
char name[64]
short custom1
struct ID * id
void * storage