327015c11393a5c9438f2db077348ec7f1b2715e
[blender.git] / source / blender / compositor / operations / COM_ConvertOperation.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  */
22
23 #include "COM_ConvertOperation.h"
24
25 extern "C" {
26 #include "IMB_colormanagement.h"
27 }
28
29 ConvertBaseOperation::ConvertBaseOperation()
30 {
31         this->m_inputOperation = NULL;
32 }
33
34 void ConvertBaseOperation::initExecution()
35 {
36         this->m_inputOperation = this->getInputSocketReader(0);
37 }
38
39 void ConvertBaseOperation::deinitExecution()
40 {
41         this->m_inputOperation = NULL;
42 }
43
44
45 /* ******** Value to Color ******** */
46
47 ConvertValueToColorOperation::ConvertValueToColorOperation() : ConvertBaseOperation()
48 {
49         this->addInputSocket(COM_DT_VALUE);
50         this->addOutputSocket(COM_DT_COLOR);
51 }
52
53 void ConvertValueToColorOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
54 {
55         float value;
56         this->m_inputOperation->readSampled(&value, x, y, sampler);
57         output[0] = output[1] = output[2] = value;
58         output[3] = 1.0f;
59 }
60
61
62 /* ******** Color to Value ******** */
63
64 ConvertColorToValueOperation::ConvertColorToValueOperation() : ConvertBaseOperation()
65 {
66         this->addInputSocket(COM_DT_COLOR);
67         this->addOutputSocket(COM_DT_VALUE);
68 }
69
70 void ConvertColorToValueOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
71 {
72         float inputColor[4];
73         this->m_inputOperation->readSampled(inputColor, x, y, sampler);
74         output[0] = (inputColor[0] + inputColor[1] + inputColor[2]) / 3.0f;
75 }
76
77
78 /* ******** Color to BW ******** */
79
80 ConvertColorToBWOperation::ConvertColorToBWOperation() : ConvertBaseOperation()
81 {
82         this->addInputSocket(COM_DT_COLOR);
83         this->addOutputSocket(COM_DT_VALUE);
84 }
85
86 void ConvertColorToBWOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
87 {
88         float inputColor[4];
89         this->m_inputOperation->readSampled(inputColor, x, y, sampler);
90         output[0] = IMB_colormanagement_get_luminance(inputColor);
91 }
92
93
94 /* ******** Color to Vector ******** */
95
96 ConvertColorToVectorOperation::ConvertColorToVectorOperation() : ConvertBaseOperation()
97 {
98         this->addInputSocket(COM_DT_COLOR);
99         this->addOutputSocket(COM_DT_VECTOR);
100 }
101
102 void ConvertColorToVectorOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
103 {
104         float color[4];
105         this->m_inputOperation->readSampled(color, x, y, sampler);
106         copy_v3_v3(output, color);}
107
108
109 /* ******** Value to Vector ******** */
110
111 ConvertValueToVectorOperation::ConvertValueToVectorOperation() : ConvertBaseOperation()
112 {
113         this->addInputSocket(COM_DT_VALUE);
114         this->addOutputSocket(COM_DT_VECTOR);
115 }
116
117 void ConvertValueToVectorOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
118 {
119         float value;
120         this->m_inputOperation->readSampled(&value, x, y, sampler);
121         output[0] = output[1] = output[2] = value;
122 }
123
124
125 /* ******** Vector to Color ******** */
126
127 ConvertVectorToColorOperation::ConvertVectorToColorOperation() : ConvertBaseOperation()
128 {
129         this->addInputSocket(COM_DT_VECTOR);
130         this->addOutputSocket(COM_DT_COLOR);
131 }
132
133 void ConvertVectorToColorOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
134 {
135         this->m_inputOperation->readSampled(output, x, y, sampler);
136         output[3] = 1.0f;
137 }
138
139
140 /* ******** Vector to Value ******** */
141
142 ConvertVectorToValueOperation::ConvertVectorToValueOperation() : ConvertBaseOperation()
143 {
144         this->addInputSocket(COM_DT_VECTOR);
145         this->addOutputSocket(COM_DT_VALUE);
146 }
147
148 void ConvertVectorToValueOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
149 {
150         float input[4];
151         this->m_inputOperation->readSampled(input, x, y, sampler);
152         output[0] = (input[0] + input[1] + input[2]) / 3.0f;
153 }
154
155
156 /* ******** RGB to YCC ******** */
157
158 ConvertRGBToYCCOperation::ConvertRGBToYCCOperation() : ConvertBaseOperation()
159 {
160         this->addInputSocket(COM_DT_COLOR);
161         this->addOutputSocket(COM_DT_COLOR);
162 }
163
164 void ConvertRGBToYCCOperation::setMode(int mode)
165 {
166         switch (mode) {
167                 case 1:
168                         this->m_mode = BLI_YCC_ITU_BT709;
169                         break;
170                 case 2:
171                         this->m_mode = BLI_YCC_JFIF_0_255;
172                         break;
173                 case 0:
174                 default:
175                         this->m_mode = BLI_YCC_ITU_BT601;
176                         break;
177         }
178 }
179
180 void ConvertRGBToYCCOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
181 {
182         float inputColor[4];
183         float color[3];
184
185         this->m_inputOperation->readSampled(inputColor, x, y, sampler);
186         rgb_to_ycc(inputColor[0], inputColor[1], inputColor[2], &color[0], &color[1], &color[2], this->m_mode);
187
188         /* divided by 255 to normalize for viewing in */
189         /* R,G,B --> Y,Cb,Cr */
190         mul_v3_v3fl(output, color, 1.0f / 255.0f);
191         output[3] = inputColor[3];
192 }
193
194 /* ******** YCC to RGB ******** */
195
196 ConvertYCCToRGBOperation::ConvertYCCToRGBOperation() : ConvertBaseOperation()
197 {
198         this->addInputSocket(COM_DT_COLOR);
199         this->addOutputSocket(COM_DT_COLOR);
200 }
201
202 void ConvertYCCToRGBOperation::setMode(int mode)
203 {
204         switch (mode) {
205                 case 1:
206                         this->m_mode = BLI_YCC_ITU_BT709;
207                         break;
208                 case 2:
209                         this->m_mode = BLI_YCC_JFIF_0_255;
210                         break;
211                 case 0:
212                 default:
213                         this->m_mode = BLI_YCC_ITU_BT601;
214                         break;
215         }
216 }
217
218 void ConvertYCCToRGBOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
219 {
220         float inputColor[4];
221         this->m_inputOperation->readSampled(inputColor, x, y, sampler);
222
223         /* need to un-normalize the data */
224         /* R,G,B --> Y,Cb,Cr */
225         mul_v3_fl(inputColor, 255.0f);
226
227         ycc_to_rgb(inputColor[0], inputColor[1], inputColor[2], &output[0], &output[1], &output[2], this->m_mode);
228         output[3] = inputColor[3];
229 }
230
231
232 /* ******** RGB to YUV ******** */
233
234 ConvertRGBToYUVOperation::ConvertRGBToYUVOperation() : ConvertBaseOperation()
235 {
236         this->addInputSocket(COM_DT_COLOR);
237         this->addOutputSocket(COM_DT_COLOR);
238 }
239
240 void ConvertRGBToYUVOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
241 {
242         float inputColor[4];
243         this->m_inputOperation->readSampled(inputColor, x, y, sampler);
244         rgb_to_yuv(inputColor[0], inputColor[1], inputColor[2], &output[0], &output[1], &output[2], BLI_YUV_ITU_BT709);
245         output[3] = inputColor[3];
246 }
247
248
249 /* ******** YUV to RGB ******** */
250
251 ConvertYUVToRGBOperation::ConvertYUVToRGBOperation() : ConvertBaseOperation()
252 {
253         this->addInputSocket(COM_DT_COLOR);
254         this->addOutputSocket(COM_DT_COLOR);
255 }
256
257 void ConvertYUVToRGBOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
258 {
259         float inputColor[4];
260         this->m_inputOperation->readSampled(inputColor, x, y, sampler);
261         yuv_to_rgb(inputColor[0], inputColor[1], inputColor[2], &output[0], &output[1], &output[2], BLI_YUV_ITU_BT709);
262         output[3] = inputColor[3];
263 }
264
265
266 /* ******** RGB to HSV ******** */
267
268 ConvertRGBToHSVOperation::ConvertRGBToHSVOperation() : ConvertBaseOperation()
269 {
270         this->addInputSocket(COM_DT_COLOR);
271         this->addOutputSocket(COM_DT_COLOR);
272 }
273
274 void ConvertRGBToHSVOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
275 {
276         float inputColor[4];
277         this->m_inputOperation->readSampled(inputColor, x, y, sampler);
278         rgb_to_hsv_v(inputColor, output);
279         output[3] = inputColor[3];
280 }
281
282
283 /* ******** HSV to RGB ******** */
284
285 ConvertHSVToRGBOperation::ConvertHSVToRGBOperation() : ConvertBaseOperation()
286 {
287         this->addInputSocket(COM_DT_COLOR);
288         this->addOutputSocket(COM_DT_COLOR);
289 }
290
291 void ConvertHSVToRGBOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
292 {
293         float inputColor[4];
294         this->m_inputOperation->readSampled(inputColor, x, y, sampler);
295         hsv_to_rgb_v(inputColor, output);
296         output[0] = max_ff(output[0], 0.0f);
297         output[1] = max_ff(output[1], 0.0f);
298         output[2] = max_ff(output[2], 0.0f);
299         output[3] = inputColor[3];
300 }
301
302
303 /* ******** Premul to Straight ******** */
304
305 ConvertPremulToStraightOperation::ConvertPremulToStraightOperation() : ConvertBaseOperation()
306 {
307         this->addInputSocket(COM_DT_COLOR);
308         this->addOutputSocket(COM_DT_COLOR);
309 }
310
311 void ConvertPremulToStraightOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
312 {
313         float inputValue[4];
314         float alpha;
315
316         this->m_inputOperation->readSampled(inputValue, x, y, sampler);
317         alpha = inputValue[3];
318
319         if (fabsf(alpha) < 1e-5f) {
320                 zero_v3(output);
321         }
322         else {
323                 mul_v3_v3fl(output, inputValue, 1.0f / alpha);
324         }
325
326         /* never touches the alpha */
327         output[3] = alpha;
328 }
329
330
331 /* ******** Straight to Premul ******** */
332
333 ConvertStraightToPremulOperation::ConvertStraightToPremulOperation() : ConvertBaseOperation()
334 {
335         this->addInputSocket(COM_DT_COLOR);
336         this->addOutputSocket(COM_DT_COLOR);
337 }
338
339 void ConvertStraightToPremulOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
340 {
341         float inputValue[4];
342         float alpha;
343
344         this->m_inputOperation->readSampled(inputValue, x, y, sampler);
345         alpha = inputValue[3];
346
347         mul_v3_v3fl(output, inputValue, alpha);
348
349         /* never touches the alpha */
350         output[3] = alpha;
351 }
352
353
354 /* ******** Separate Channels ******** */
355
356 SeparateChannelOperation::SeparateChannelOperation() : NodeOperation()
357 {
358         this->addInputSocket(COM_DT_COLOR);
359         this->addOutputSocket(COM_DT_VALUE);
360         this->m_inputOperation = NULL;
361 }
362 void SeparateChannelOperation::initExecution()
363 {
364         this->m_inputOperation = this->getInputSocketReader(0);
365 }
366
367 void SeparateChannelOperation::deinitExecution()
368 {
369         this->m_inputOperation = NULL;
370 }
371
372
373 void SeparateChannelOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
374 {
375         float input[4];
376         this->m_inputOperation->readSampled(input, x, y, sampler);
377         output[0] = input[this->m_channel];
378 }
379
380
381 /* ******** Combine Channels ******** */
382
383 CombineChannelsOperation::CombineChannelsOperation() : NodeOperation()
384 {
385         this->addInputSocket(COM_DT_VALUE);
386         this->addInputSocket(COM_DT_VALUE);
387         this->addInputSocket(COM_DT_VALUE);
388         this->addInputSocket(COM_DT_VALUE);
389         this->addOutputSocket(COM_DT_COLOR);
390         this->setResolutionInputSocketIndex(0);
391         this->m_inputChannel1Operation = NULL;
392         this->m_inputChannel2Operation = NULL;
393         this->m_inputChannel3Operation = NULL;
394         this->m_inputChannel4Operation = NULL;
395 }
396
397 void CombineChannelsOperation::initExecution()
398 {
399         this->m_inputChannel1Operation = this->getInputSocketReader(0);
400         this->m_inputChannel2Operation = this->getInputSocketReader(1);
401         this->m_inputChannel3Operation = this->getInputSocketReader(2);
402         this->m_inputChannel4Operation = this->getInputSocketReader(3);
403 }
404
405 void CombineChannelsOperation::deinitExecution()
406 {
407         this->m_inputChannel1Operation = NULL;
408         this->m_inputChannel2Operation = NULL;
409         this->m_inputChannel3Operation = NULL;
410         this->m_inputChannel4Operation = NULL;
411 }
412
413
414 void CombineChannelsOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
415 {
416         float input[4];
417         if (this->m_inputChannel1Operation) {
418                 this->m_inputChannel1Operation->readSampled(input, x, y, sampler);
419                 output[0] = input[0];
420         }
421         if (this->m_inputChannel2Operation) {
422                 this->m_inputChannel2Operation->readSampled(input, x, y, sampler);
423                 output[1] = input[0];
424         }
425         if (this->m_inputChannel3Operation) {
426                 this->m_inputChannel3Operation->readSampled(input, x, y, sampler);
427                 output[2] = input[0];
428         }
429         if (this->m_inputChannel4Operation) {
430                 this->m_inputChannel4Operation->readSampled(input, x, y, sampler);
431                 output[3] = input[0];
432         }
433 }