e4dd72d79e9cb27a8906f790b8ef2ba1c4424e57
[blender.git] / source / blender / compositor / nodes / COM_ImageNode.cpp
1 /*
2  * Copyright 2011, Blender Foundation.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor: 
19  *              Jeroen Bakker 
20  *              Monique Dewanchand
21  *              Lukas Tönne
22  */
23
24 #include "COM_ImageNode.h"
25 #include "COM_ExecutionSystem.h"
26 #include "COM_ImageOperation.h"
27 #include "COM_MultilayerImageOperation.h"
28 #include "COM_ConvertPremulToStraightOperation.h"
29 #include "BKE_node.h"
30 #include "BLI_utildefines.h"
31
32 #include "COM_SetValueOperation.h"
33 #include "COM_SetVectorOperation.h"
34 #include "COM_SetColorOperation.h"
35
36 ImageNode::ImageNode(bNode *editorNode) : Node(editorNode)
37 {
38         /* pass */
39
40 }
41 NodeOperation *ImageNode::doMultilayerCheck(ExecutionSystem *system, RenderLayer *rl, Image *image, ImageUser *user, int framenumber, int outputsocketIndex, int pass, DataType datatype)
42 {
43         OutputSocket *outputSocket = this->getOutputSocket(outputsocketIndex);
44         MultilayerBaseOperation *operation = NULL;
45         switch (datatype) {
46                 case COM_DT_VALUE:
47                         operation = new MultilayerValueOperation(pass);
48                         break;
49                 case COM_DT_VECTOR:
50                         operation = new MultilayerVectorOperation(pass);
51                         break;
52                 case COM_DT_COLOR:
53                         operation = new MultilayerColorOperation(pass);
54                         break;
55                 default:
56                         break;
57         }
58         operation->setImage(image);
59         operation->setRenderLayer(rl);
60         operation->setImageUser(user);
61         operation->setFramenumber(framenumber);
62         outputSocket->relinkConnections(operation->getOutputSocket());
63         system->addOperation(operation);
64         return operation;
65 }
66
67 void ImageNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
68 {
69         /// Image output
70         OutputSocket *outputImage = this->getOutputSocket(0);
71         bNode *editorNode = this->getbNode();
72         Image *image = (Image *)editorNode->id;
73         ImageUser *imageuser = (ImageUser *)editorNode->storage;
74         int framenumber = context->getFramenumber();
75         int numberOfOutputs = this->getNumberOfOutputSockets();
76         bool outputStraightAlpha = editorNode->custom1 & CMP_NODE_IMAGE_USE_STRAIGHT_OUTPUT;
77         BKE_image_user_frame_calc(imageuser, context->getFramenumber(), 0);
78
79         /* force a load, we assume iuser index will be set OK anyway */
80         if (image && image->type == IMA_TYPE_MULTILAYER) {
81                 bool is_multilayer_ok = false;
82                 ImBuf *ibuf = BKE_image_acquire_ibuf(image, imageuser, NULL);
83                 if (image->rr) {
84                         RenderLayer *rl = (RenderLayer *)BLI_findlink(&image->rr->layers, imageuser->layer);
85                         if (rl) {
86                                 OutputSocket *socket;
87                                 int index;
88
89                                 is_multilayer_ok = true;
90
91                                 for (index = 0; index < numberOfOutputs; index++) {
92                                         NodeOperation *operation = NULL;
93                                         socket = this->getOutputSocket(index);
94                                         if (socket->isConnected() || index == 0) {
95                                                 bNodeSocket *bnodeSocket = socket->getbNodeSocket();
96                                                 NodeImageLayer *storage = (NodeImageLayer *)bnodeSocket->storage;
97                                                 int passindex = storage->pass_index;
98                                                 
99                                                 RenderPass *rpass = (RenderPass *)BLI_findlink(&rl->passes, passindex);
100                                                 if (rpass) {
101                                                         imageuser->pass = passindex;
102                                                         switch (rpass->channels) {
103                                                                 case 1:
104                                                                         operation = doMultilayerCheck(graph, rl, image, imageuser, framenumber, index, passindex, COM_DT_VALUE);
105                                                                         break;
106                                                                 /* using image operations for both 3 and 4 channels (RGB and RGBA respectively) */
107                                                                 /* XXX any way to detect actual vector images? */
108                                                                 case 3:
109                                                                         operation = doMultilayerCheck(graph, rl, image, imageuser, framenumber, index, passindex, COM_DT_VECTOR);
110                                                                         break;
111                                                                 case 4:
112                                                                         operation = doMultilayerCheck(graph, rl, image, imageuser, framenumber, index, passindex, COM_DT_COLOR);
113                                                                         break;
114                                                                 default:
115                                                                         /* dummy operation is added below */
116                                                                         break;
117                                                         }
118
119                                                         if (index == 0 && operation) {
120                                                                 addPreviewOperation(graph, context, operation->getOutputSocket());
121                                                         }
122                                                 }
123                                         }
124
125                                         /* incase we can't load the layer */
126                                         if (operation == NULL) {
127                                                 convertToOperations_invalid_index(graph, index);
128                                         }
129                                 }
130                         }
131                 }
132                 BKE_image_release_ibuf(image, ibuf, NULL);
133
134                 /* without this, multilayer that fail to load will crash blender [#32490] */
135                 if (is_multilayer_ok == false) {
136                         convertToOperations_invalid(graph, context);
137                 }
138         }
139         else {
140                 if (numberOfOutputs >  0) {
141                         ImageOperation *operation = new ImageOperation();
142                         if (outputImage->isConnected()) {
143                                 if (outputStraightAlpha) {
144                                         NodeOperation *alphaConvertOperation = new ConvertPremulToStraightOperation();
145                                         addLink(graph, operation->getOutputSocket(0), alphaConvertOperation->getInputSocket(0));
146                                         outputImage->relinkConnections(alphaConvertOperation->getOutputSocket());
147                                         graph->addOperation(alphaConvertOperation);
148                                 }
149                                 else {
150                                         outputImage->relinkConnections(operation->getOutputSocket());
151                                 }
152                         }
153                         operation->setImage(image);
154                         operation->setImageUser(imageuser);
155                         operation->setFramenumber(framenumber);
156                         graph->addOperation(operation);
157                         addPreviewOperation(graph, context, operation->getOutputSocket());
158                 }
159                 
160                 if (numberOfOutputs > 1) {
161                         OutputSocket *alphaImage = this->getOutputSocket(1);
162                         if (alphaImage->isConnected()) {
163                                 ImageAlphaOperation *alphaOperation = new ImageAlphaOperation();
164                                 alphaOperation->setImage(image);
165                                 alphaOperation->setImageUser(imageuser);
166                                 alphaOperation->setFramenumber(framenumber);
167                                 alphaImage->relinkConnections(alphaOperation->getOutputSocket());
168                                 graph->addOperation(alphaOperation);
169                         }
170                 }
171                 if (numberOfOutputs > 2) {
172                         OutputSocket *depthImage = this->getOutputSocket(2);
173                         if (depthImage->isConnected()) {
174                                 ImageDepthOperation *depthOperation = new ImageDepthOperation();
175                                 depthOperation->setImage(image);
176                                 depthOperation->setImageUser(imageuser);
177                                 depthOperation->setFramenumber(framenumber);
178                                 depthImage->relinkConnections(depthOperation->getOutputSocket());
179                                 graph->addOperation(depthOperation);
180                         }
181                 }
182                 if (numberOfOutputs > 3) {
183                         /* happens when unlinking image datablock from multilayer node */
184                         for (int i = 3; i < numberOfOutputs; i++) {
185                                 OutputSocket *output = this->getOutputSocket(i);
186                                 NodeOperation *operation = NULL;
187                                 switch (output->getDataType()) {
188                                         case COM_DT_VALUE:
189                                         {
190                                                 SetValueOperation *valueoperation = new SetValueOperation();
191                                                 valueoperation->setValue(0.0f);
192                                                 operation = valueoperation;
193                                                 break;
194                                         }
195                                         case COM_DT_VECTOR:
196                                         {
197                                                 SetVectorOperation *vectoroperation = new SetVectorOperation();
198                                                 vectoroperation->setX(0.0f);
199                                                 vectoroperation->setY(0.0f);
200                                                 vectoroperation->setW(0.0f);
201                                                 operation = vectoroperation;
202                                                 break;
203                                         }
204                                         case COM_DT_COLOR:
205                                         {
206                                                 SetColorOperation *coloroperation = new SetColorOperation();
207                                                 coloroperation->setChannel1(0.0f);
208                                                 coloroperation->setChannel2(0.0f);
209                                                 coloroperation->setChannel3(0.0f);
210                                                 coloroperation->setChannel4(0.0f);
211                                                 operation = coloroperation;
212                                                 break;
213                                         }
214                                 }
215
216                                 if (operation) {
217                                         output->relinkConnections(operation->getOutputSocket());
218                                         graph->addOperation(operation);
219                                 }
220                         }
221                 }
222         }
223 }
224