Blender  V2.93
COM_ImageNode.cc
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * Copyright 2011, Blender Foundation.
17  */
18 
19 #include "COM_ImageNode.h"
20 #include "BKE_node.h"
21 #include "BLI_utildefines.h"
22 #include "COM_ConvertOperation.h"
23 #include "COM_ExecutionSystem.h"
24 #include "COM_ImageOperation.h"
26 
27 #include "COM_SeparateColorNode.h"
28 #include "COM_SetColorOperation.h"
29 #include "COM_SetValueOperation.h"
30 #include "COM_SetVectorOperation.h"
31 
32 namespace blender::compositor {
33 
34 ImageNode::ImageNode(bNode *editorNode) : Node(editorNode)
35 {
36  /* pass */
37 }
38 NodeOperation *ImageNode::doMultilayerCheck(NodeConverter &converter,
39  RenderLayer *render_layer,
40  RenderPass *render_pass,
41  Image *image,
42  ImageUser *user,
43  int framenumber,
44  int outputsocketIndex,
45  int view,
46  DataType datatype) const
47 {
48  NodeOutput *outputSocket = this->getOutputSocket(outputsocketIndex);
49  MultilayerBaseOperation *operation = nullptr;
50  switch (datatype) {
51  case DataType::Value:
52  operation = new MultilayerValueOperation(render_layer, render_pass, view);
53  break;
54  case DataType::Vector:
55  operation = new MultilayerVectorOperation(render_layer, render_pass, view);
56  break;
57  case DataType::Color:
58  operation = new MultilayerColorOperation(render_layer, render_pass, view);
59  break;
60  default:
61  break;
62  }
63  operation->setImage(image);
64  operation->setImageUser(user);
65  operation->setFramenumber(framenumber);
66 
67  converter.addOperation(operation);
68  converter.mapOutputSocket(outputSocket, operation->getOutputSocket());
69 
70  return operation;
71 }
72 
74  const CompositorContext &context) const
75 {
77  NodeOutput *outputImage = this->getOutputSocket(0);
78  bNode *editorNode = this->getbNode();
79  Image *image = (Image *)editorNode->id;
80  ImageUser *imageuser = (ImageUser *)editorNode->storage;
81  int framenumber = context.getFramenumber();
82  bool outputStraightAlpha = (editorNode->custom1 & CMP_NODE_IMAGE_USE_STRAIGHT_OUTPUT) != 0;
83  BKE_image_user_frame_calc(image, imageuser, context.getFramenumber());
84  /* force a load, we assume iuser index will be set OK anyway */
85  if (image && image->type == IMA_TYPE_MULTILAYER) {
86  bool is_multilayer_ok = false;
87  ImBuf *ibuf = BKE_image_acquire_ibuf(image, imageuser, nullptr);
88  if (image->rr) {
89  RenderLayer *rl = (RenderLayer *)BLI_findlink(&image->rr->layers, imageuser->layer);
90  if (rl) {
91  is_multilayer_ok = true;
92 
93  for (int64_t index = 0; index < outputs.size(); index++) {
94  NodeOutput *socket = outputs[index];
95  NodeOperation *operation = nullptr;
96  bNodeSocket *bnodeSocket = socket->getbNodeSocket();
97  NodeImageLayer *storage = (NodeImageLayer *)bnodeSocket->storage;
99  &rl->passes, storage->pass_name, offsetof(RenderPass, name));
100  int view = 0;
101 
102  if (STREQ(storage->pass_name, RE_PASSNAME_COMBINED) &&
103  STREQ(bnodeSocket->name, "Alpha")) {
104  /* Alpha output is already handled with the associated combined output. */
105  continue;
106  }
107 
108  /* returns the image view to use for the current active view */
109  if (BLI_listbase_count_at_most(&image->rr->views, 2) > 1) {
110  const int view_image = imageuser->view;
111  const bool is_allview = (view_image == 0); /* if view selected == All (0) */
112 
113  if (is_allview) {
114  /* heuristic to match image name with scene names
115  * check if the view name exists in the image */
117  &image->rr->views, context.getViewName(), offsetof(RenderView, name));
118  if (view == -1) {
119  view = 0;
120  }
121  }
122  else {
123  view = view_image - 1;
124  }
125  }
126 
127  if (rpass) {
128  switch (rpass->channels) {
129  case 1:
130  operation = doMultilayerCheck(converter,
131  rl,
132  rpass,
133  image,
134  imageuser,
135  framenumber,
136  index,
137  view,
139  break;
140  /* using image operations for both 3 and 4 channels (RGB and RGBA respectively) */
141  /* XXX any way to detect actual vector images? */
142  case 3:
143  operation = doMultilayerCheck(converter,
144  rl,
145  rpass,
146  image,
147  imageuser,
148  framenumber,
149  index,
150  view,
152  break;
153  case 4:
154  operation = doMultilayerCheck(converter,
155  rl,
156  rpass,
157  image,
158  imageuser,
159  framenumber,
160  index,
161  view,
163  break;
164  default:
165  /* dummy operation is added below */
166  break;
167  }
168  if (index == 0 && operation) {
169  converter.addPreview(operation->getOutputSocket());
170  }
171  if (STREQ(rpass->name, RE_PASSNAME_COMBINED)) {
172  for (NodeOutput *alphaSocket : getOutputSockets()) {
173  bNodeSocket *bnodeAlphaSocket = alphaSocket->getbNodeSocket();
174  if (!STREQ(bnodeAlphaSocket->name, "Alpha")) {
175  continue;
176  }
177  NodeImageLayer *alphaStorage = (NodeImageLayer *)bnodeSocket->storage;
178  if (!STREQ(alphaStorage->pass_name, RE_PASSNAME_COMBINED)) {
179  continue;
180  }
181  SeparateChannelOperation *separate_operation;
182  separate_operation = new SeparateChannelOperation();
183  separate_operation->setChannel(3);
184  converter.addOperation(separate_operation);
185  converter.addLink(operation->getOutputSocket(),
186  separate_operation->getInputSocket(0));
187  converter.mapOutputSocket(alphaSocket, separate_operation->getOutputSocket());
188  break;
189  }
190  }
191  }
192 
193  /* In case we can't load the layer. */
194  if (operation == nullptr) {
195  converter.setInvalidOutput(getOutputSocket(index));
196  }
197  }
198  }
199  }
200  BKE_image_release_ibuf(image, ibuf, nullptr);
201 
202  /* without this, multilayer that fail to load will crash blender T32490. */
203  if (is_multilayer_ok == false) {
204  for (NodeOutput *output : getOutputSockets()) {
205  converter.setInvalidOutput(output);
206  }
207  }
208  }
209  else {
210  const int64_t numberOfOutputs = getOutputSockets().size();
211  if (numberOfOutputs > 0) {
212  ImageOperation *operation = new ImageOperation();
213  operation->setImage(image);
214  operation->setImageUser(imageuser);
215  operation->setFramenumber(framenumber);
216  operation->setRenderData(context.getRenderData());
217  operation->setViewName(context.getViewName());
218  converter.addOperation(operation);
219 
220  if (outputStraightAlpha) {
221  NodeOperation *alphaConvertOperation = new ConvertPremulToStraightOperation();
222 
223  converter.addOperation(alphaConvertOperation);
224  converter.mapOutputSocket(outputImage, alphaConvertOperation->getOutputSocket());
225  converter.addLink(operation->getOutputSocket(0), alphaConvertOperation->getInputSocket(0));
226  }
227  else {
228  converter.mapOutputSocket(outputImage, operation->getOutputSocket());
229  }
230 
231  converter.addPreview(operation->getOutputSocket());
232  }
233 
234  if (numberOfOutputs > 1) {
235  NodeOutput *alphaImage = this->getOutputSocket(1);
236  ImageAlphaOperation *alphaOperation = new ImageAlphaOperation();
237  alphaOperation->setImage(image);
238  alphaOperation->setImageUser(imageuser);
239  alphaOperation->setFramenumber(framenumber);
240  alphaOperation->setRenderData(context.getRenderData());
241  alphaOperation->setViewName(context.getViewName());
242  converter.addOperation(alphaOperation);
243 
244  converter.mapOutputSocket(alphaImage, alphaOperation->getOutputSocket());
245  }
246  if (numberOfOutputs > 2) {
247  NodeOutput *depthImage = this->getOutputSocket(2);
248  ImageDepthOperation *depthOperation = new ImageDepthOperation();
249  depthOperation->setImage(image);
250  depthOperation->setImageUser(imageuser);
251  depthOperation->setFramenumber(framenumber);
252  depthOperation->setRenderData(context.getRenderData());
253  depthOperation->setViewName(context.getViewName());
254  converter.addOperation(depthOperation);
255 
256  converter.mapOutputSocket(depthImage, depthOperation->getOutputSocket());
257  }
258  if (numberOfOutputs > 3) {
259  /* happens when unlinking image datablock from multilayer node */
260  for (int i = 3; i < numberOfOutputs; i++) {
261  NodeOutput *output = this->getOutputSocket(i);
262  NodeOperation *operation = nullptr;
263  switch (output->getDataType()) {
264  case DataType::Value: {
265  SetValueOperation *valueoperation = new SetValueOperation();
266  valueoperation->setValue(0.0f);
267  operation = valueoperation;
268  break;
269  }
270  case DataType::Vector: {
271  SetVectorOperation *vectoroperation = new SetVectorOperation();
272  vectoroperation->setX(0.0f);
273  vectoroperation->setY(0.0f);
274  vectoroperation->setW(0.0f);
275  operation = vectoroperation;
276  break;
277  }
278  case DataType::Color: {
279  SetColorOperation *coloroperation = new SetColorOperation();
280  coloroperation->setChannel1(0.0f);
281  coloroperation->setChannel2(0.0f);
282  coloroperation->setChannel3(0.0f);
283  coloroperation->setChannel4(0.0f);
284  operation = coloroperation;
285  break;
286  }
287  }
288 
289  if (operation) {
290  /* not supporting multiview for this generic case */
291  converter.addOperation(operation);
292  converter.mapOutputSocket(output, operation->getOutputSocket());
293  }
294  }
295  }
296  }
297 } // namespace blender::compositor
298 
299 } // namespace blender::compositor
void BKE_image_release_ibuf(struct Image *ima, struct ImBuf *ibuf, void *lock)
Definition: image.c:5113
struct ImBuf * BKE_image_acquire_ibuf(struct Image *ima, struct ImageUser *iuser, void **r_lock)
Definition: image.c:5100
void BKE_image_user_frame_calc(struct Image *ima, struct ImageUser *iuser, int cfra)
Definition: image.c:5335
int BLI_listbase_count_at_most(const struct ListBase *listbase, const int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void * BLI_findstring(const struct ListBase *listbase, const char *id, const 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)
int BLI_findstringindex(const struct ListBase *listbase, const char *id, const int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
#define STREQ(a, b)
@ IMA_TYPE_MULTILAYER
#define CMP_NODE_IMAGE_USE_STRAIGHT_OUTPUT
#define RE_PASSNAME_COMBINED
static AppView * view
#define output
short type
struct RenderResult * rr
void setViewName(const char *viewName)
void setImageUser(ImageUser *imageuser)
void setRenderData(const RenderData *rd)
Overall context of the compositor.
ImageNode(bNode *editorNode)
void convertToOperations(NodeConverter &converter, const CompositorContext &context) const override
convert node to operation
NodeOperation * setInvalidOutput(NodeOutput *output)
void addPreview(NodeOperationOutput *output)
void addOperation(NodeOperation *operation)
void mapOutputSocket(NodeOutput *node_socket, NodeOperationOutput *operation_socket)
void addLink(NodeOperationOutput *from, NodeOperationInput *to)
NodeOperation contains calculation logic.
NodeOperationInput * getInputSocket(unsigned int index)
NodeOperationOutput * getOutputSocket(unsigned int index=0)
NodeOutput are sockets that can send data/input.
Definition: COM_Node.h:258
bNodeSocket * getbNodeSocket() const
Definition: COM_Node.h:276
Vector< NodeOutput * > outputs
the list of actual output-sockets
Definition: COM_Node.h:73
NodeOutput * getOutputSocket(const unsigned int index=0) const
Definition: COM_Node.cc:108
bNode * getbNode() const
get the reference to the SDNA bNode struct
Definition: COM_Node.h:82
const Vector< NodeOutput * > & getOutputSockets() const
get access to the vector of input sockets
Definition: COM_Node.h:126
DataType
possible data types for sockets
Definition: COM_defines.h:27
@ Vector
Vector data type.
__int64 int64_t
Definition: stdint.h:92
char pass_name[64]
ListBase passes
Definition: RE_pipeline.h:108
ListBase views
Definition: RE_pipeline.h:138
ListBase layers
Definition: RE_pipeline.h:135
char name[64]
void * storage
short custom1
struct ID * id
void * storage