~ubuntu-branches/ubuntu/utopic/blender/utopic-proposed

« back to all changes in this revision

Viewing changes to source/blender/compositor/operations/COM_MixOperation.cpp

  • Committer: Package Import Robot
  • Author(s): Matthias Klose
  • Date: 2014-02-19 11:24:23 UTC
  • mfrom: (14.2.23 sid)
  • Revision ID: package-import@ubuntu.com-20140219112423-rkmaz2m7ha06d4tk
Tags: 2.69-3ubuntu1
* Merge with Debian; remaining changes:
  - Configure without OpenImageIO on armhf, as it is not available on
    Ubuntu.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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_MixOperation.h"
 
24
 
 
25
extern "C" {
 
26
        #include "BLI_math.h"
 
27
}
 
28
 
 
29
/* ******** Mix Base Operation ******** */
 
30
 
 
31
MixBaseOperation::MixBaseOperation() : NodeOperation()
 
32
{
 
33
        this->addInputSocket(COM_DT_VALUE);
 
34
        this->addInputSocket(COM_DT_COLOR);
 
35
        this->addInputSocket(COM_DT_COLOR);
 
36
        this->addOutputSocket(COM_DT_COLOR);
 
37
        this->m_inputValueOperation = NULL;
 
38
        this->m_inputColor1Operation = NULL;
 
39
        this->m_inputColor2Operation = NULL;
 
40
        this->setUseValueAlphaMultiply(false);
 
41
        this->setUseClamp(false);
 
42
}
 
43
 
 
44
void MixBaseOperation::initExecution()
 
45
{
 
46
        this->m_inputValueOperation = this->getInputSocketReader(0);
 
47
        this->m_inputColor1Operation = this->getInputSocketReader(1);
 
48
        this->m_inputColor2Operation = this->getInputSocketReader(2);
 
49
}
 
50
 
 
51
void MixBaseOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
 
52
{
 
53
        float inputColor1[4];
 
54
        float inputColor2[4];
 
55
        float inputValue[4];
 
56
        
 
57
        this->m_inputValueOperation->read(inputValue, x, y, sampler);
 
58
        this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
 
59
        this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
 
60
        
 
61
        float value = inputValue[0];
 
62
        if (this->useValueAlphaMultiply()) {
 
63
                value *= inputColor2[3];
 
64
        }
 
65
        float valuem = 1.0f - value;
 
66
        output[0] = valuem * (inputColor1[0]) + value * (inputColor2[0]);
 
67
        output[1] = valuem * (inputColor1[1]) + value * (inputColor2[1]);
 
68
        output[2] = valuem * (inputColor1[2]) + value * (inputColor2[2]);
 
69
        output[3] = inputColor1[3];
 
70
}
 
71
 
 
72
void MixBaseOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2])
 
73
{
 
74
        InputSocket *socket;
 
75
        unsigned int tempPreferredResolution[2] = {0, 0};
 
76
        unsigned int tempResolution[2];
 
77
 
 
78
        socket = this->getInputSocket(1);
 
79
        socket->determineResolution(tempResolution, tempPreferredResolution);
 
80
        if ((tempResolution[0] != 0) && (tempResolution[1] != 0)) {
 
81
                this->setResolutionInputSocketIndex(1);
 
82
        }
 
83
        else {
 
84
                socket = this->getInputSocket(2);
 
85
                socket->determineResolution(tempResolution, tempPreferredResolution);
 
86
                if ((tempResolution[0] != 0) && (tempResolution[1] != 0)) {
 
87
                        this->setResolutionInputSocketIndex(2);
 
88
                }
 
89
                else {
 
90
                        this->setResolutionInputSocketIndex(0);
 
91
                }
 
92
        }
 
93
        NodeOperation::determineResolution(resolution, preferredResolution);
 
94
}
 
95
 
 
96
void MixBaseOperation::deinitExecution()
 
97
{
 
98
        this->m_inputValueOperation = NULL;
 
99
        this->m_inputColor1Operation = NULL;
 
100
        this->m_inputColor2Operation = NULL;
 
101
}
 
102
 
 
103
/* ******** Mix Add Operation ******** */
 
104
 
 
105
MixAddOperation::MixAddOperation() : MixBaseOperation()
 
106
{
 
107
        /* pass */
 
108
}
 
109
 
 
110
void MixAddOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
 
111
{
 
112
        float inputColor1[4];
 
113
        float inputColor2[4];
 
114
        float inputValue[4];
 
115
 
 
116
        this->m_inputValueOperation->read(inputValue, x, y, sampler);
 
117
        this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
 
118
        this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
 
119
 
 
120
        float value = inputValue[0];
 
121
        if (this->useValueAlphaMultiply()) {
 
122
                value *= inputColor2[3];
 
123
        }
 
124
        output[0] = inputColor1[0] + value * inputColor2[0];
 
125
        output[1] = inputColor1[1] + value * inputColor2[1];
 
126
        output[2] = inputColor1[2] + value * inputColor2[2];
 
127
        output[3] = inputColor1[3];
 
128
 
 
129
        clampIfNeeded(output);
 
130
}
 
131
 
 
132
/* ******** Mix Blend Operation ******** */
 
133
 
 
134
MixBlendOperation::MixBlendOperation() : MixBaseOperation()
 
135
{
 
136
        /* pass */
 
137
}
 
138
 
 
139
void MixBlendOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
 
140
{
 
141
        float inputColor1[4];
 
142
        float inputColor2[4];
 
143
        float inputValue[4];
 
144
        float value;
 
145
 
 
146
        this->m_inputValueOperation->read(inputValue, x, y, sampler);
 
147
        this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
 
148
        this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
 
149
        value = inputValue[0];
 
150
        
 
151
        if (this->useValueAlphaMultiply()) {
 
152
                value *= inputColor2[3];
 
153
        }
 
154
        float valuem = 1.0f - value;
 
155
        output[0] = valuem * (inputColor1[0]) + value * (inputColor2[0]);
 
156
        output[1] = valuem * (inputColor1[1]) + value * (inputColor2[1]);
 
157
        output[2] = valuem * (inputColor1[2]) + value * (inputColor2[2]);
 
158
        output[3] = inputColor1[3];
 
159
 
 
160
        clampIfNeeded(output);
 
161
}
 
162
 
 
163
/* ******** Mix Burn Operation ******** */
 
164
 
 
165
MixBurnOperation::MixBurnOperation() : MixBaseOperation()
 
166
{
 
167
        /* pass */
 
168
}
 
169
 
 
170
void MixBurnOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
 
171
{
 
172
        float inputColor1[4];
 
173
        float inputColor2[4];
 
174
        float inputValue[4];
 
175
        float tmp;
 
176
 
 
177
        this->m_inputValueOperation->read(inputValue, x, y, sampler);
 
178
        this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
 
179
        this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
 
180
 
 
181
        float value = inputValue[0];
 
182
        if (this->useValueAlphaMultiply()) {
 
183
                value *= inputColor2[3];
 
184
        }
 
185
        float valuem = 1.0f - value;
 
186
 
 
187
        tmp = valuem + value * inputColor2[0];
 
188
        if (tmp <= 0.0f)
 
189
                output[0] = 0.0f;
 
190
        else {
 
191
                tmp = 1.0f - (1.0f - inputColor1[0]) / tmp;
 
192
                if (tmp < 0.0f)
 
193
                        output[0] = 0.0f;
 
194
                else if (tmp > 1.0f)
 
195
                        output[0] = 1.0f;
 
196
                else
 
197
                        output[0] = tmp;
 
198
        }
 
199
 
 
200
        tmp = valuem + value * inputColor2[1];
 
201
        if (tmp <= 0.0f)
 
202
                output[1] = 0.0f;
 
203
        else {
 
204
                tmp = 1.0f - (1.0f - inputColor1[1]) / tmp;
 
205
                if (tmp < 0.0f)
 
206
                        output[1] = 0.0f;
 
207
                else if (tmp > 1.0f)
 
208
                        output[1] = 1.0f;
 
209
                else
 
210
                        output[1] = tmp;
 
211
        }
 
212
 
 
213
        tmp = valuem + value * inputColor2[2];
 
214
        if (tmp <= 0.0f)
 
215
                output[2] = 0.0f;
 
216
        else {
 
217
                tmp = 1.0f - (1.0f - inputColor1[2]) / tmp;
 
218
                if (tmp < 0.0f)
 
219
                        output[2] = 0.0f;
 
220
                else if (tmp > 1.0f)
 
221
                        output[2] = 1.0f;
 
222
                else
 
223
                        output[2] = tmp;
 
224
        }
 
225
 
 
226
        output[3] = inputColor1[3];
 
227
 
 
228
        clampIfNeeded(output);
 
229
}
 
230
 
 
231
/* ******** Mix Color Operation ******** */
 
232
 
 
233
MixColorOperation::MixColorOperation() : MixBaseOperation()
 
234
{
 
235
        /* pass */
 
236
}
 
237
 
 
238
void MixColorOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
 
239
{
 
240
        float inputColor1[4];
 
241
        float inputColor2[4];
 
242
        float inputValue[4];
 
243
 
 
244
        this->m_inputValueOperation->read(inputValue, x, y, sampler);
 
245
        this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
 
246
        this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
 
247
 
 
248
        float value = inputValue[0];
 
249
        if (this->useValueAlphaMultiply()) {
 
250
                value *= inputColor2[3];
 
251
        }
 
252
        float valuem = 1.0f - value;
 
253
 
 
254
        float colH, colS, colV;
 
255
        rgb_to_hsv(inputColor2[0], inputColor2[1], inputColor2[2], &colH, &colS, &colV);
 
256
        if (colS != 0.0f) {
 
257
                float rH, rS, rV;
 
258
                float tmpr, tmpg, tmpb;
 
259
                rgb_to_hsv(inputColor1[0], inputColor1[1], inputColor1[2], &rH, &rS, &rV);
 
260
                hsv_to_rgb(colH, colS, rV, &tmpr, &tmpg, &tmpb);
 
261
                output[0] = (valuem * inputColor1[0]) + (value * tmpr);
 
262
                output[1] = (valuem * inputColor1[1]) + (value * tmpg);
 
263
                output[2] = (valuem * inputColor1[2]) + (value * tmpb);
 
264
        }
 
265
        else {
 
266
                copy_v3_v3(output, inputColor1);
 
267
        }
 
268
        output[3] = inputColor1[3];
 
269
 
 
270
        clampIfNeeded(output);
 
271
}
 
272
 
 
273
/* ******** Mix Darken Operation ******** */
 
274
 
 
275
MixDarkenOperation::MixDarkenOperation() : MixBaseOperation()
 
276
{
 
277
        /* pass */
 
278
}
 
279
 
 
280
void MixDarkenOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
 
281
{
 
282
        float inputColor1[4];
 
283
        float inputColor2[4];
 
284
        float inputValue[4];
 
285
 
 
286
        this->m_inputValueOperation->read(inputValue, x, y, sampler);
 
287
        this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
 
288
        this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
 
289
 
 
290
        float value = inputValue[0];
 
291
        if (this->useValueAlphaMultiply()) {
 
292
                value *= inputColor2[3];
 
293
        }
 
294
        float valuem = 1.0f - value;
 
295
        float tmp;
 
296
        tmp = inputColor2[0] + ((1.0f - inputColor2[0]) * valuem);
 
297
        if (tmp < inputColor1[0]) output[0] = tmp;
 
298
        else output[0] = inputColor1[0];
 
299
        tmp = inputColor2[1] + ((1.0f - inputColor2[1]) * valuem);
 
300
        if (tmp < inputColor1[1]) output[1] = tmp;
 
301
        else output[1] = inputColor1[1];
 
302
        tmp = inputColor2[2] + ((1.0f - inputColor2[2]) * valuem);
 
303
        if (tmp < inputColor1[2]) output[2] = tmp;
 
304
        else output[2] = inputColor1[2];
 
305
 
 
306
        output[3] = inputColor1[3];
 
307
 
 
308
        clampIfNeeded(output);
 
309
}
 
310
 
 
311
/* ******** Mix Difference Operation ******** */
 
312
 
 
313
MixDifferenceOperation::MixDifferenceOperation() : MixBaseOperation()
 
314
{
 
315
        /* pass */
 
316
}
 
317
 
 
318
void MixDifferenceOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
 
319
{
 
320
        float inputColor1[4];
 
321
        float inputColor2[4];
 
322
        float inputValue[4];
 
323
 
 
324
        this->m_inputValueOperation->read(inputValue, x, y, sampler);
 
325
        this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
 
326
        this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
 
327
 
 
328
        float value = inputValue[0];
 
329
        if (this->useValueAlphaMultiply()) {
 
330
                value *= inputColor2[3];
 
331
        }
 
332
        float valuem = 1.0f - value;
 
333
        output[0] = valuem * inputColor1[0] + value *fabsf(inputColor1[0] - inputColor2[0]);
 
334
        output[1] = valuem * inputColor1[1] + value *fabsf(inputColor1[1] - inputColor2[1]);
 
335
        output[2] = valuem * inputColor1[2] + value *fabsf(inputColor1[2] - inputColor2[2]);
 
336
        output[3] = inputColor1[3];
 
337
 
 
338
        clampIfNeeded(output);
 
339
}
 
340
 
 
341
/* ******** Mix Difference Operation ******** */
 
342
 
 
343
MixDivideOperation::MixDivideOperation() : MixBaseOperation()
 
344
{
 
345
        /* pass */
 
346
}
 
347
 
 
348
void MixDivideOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
 
349
{
 
350
        float inputColor1[4];
 
351
        float inputColor2[4];
 
352
        float inputValue[4];
 
353
 
 
354
        this->m_inputValueOperation->read(inputValue, x, y, sampler);
 
355
        this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
 
356
        this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
 
357
 
 
358
        float value = inputValue[0];
 
359
        if (this->useValueAlphaMultiply()) {
 
360
                value *= inputColor2[3];
 
361
        }
 
362
        float valuem = 1.0f - value;
 
363
 
 
364
        if (inputColor2[0] != 0.0f)
 
365
                output[0] = valuem * (inputColor1[0]) + value * (inputColor1[0]) / inputColor2[0];
 
366
        else
 
367
                output[0] = 0.0f;
 
368
        if (inputColor2[1] != 0.0f)
 
369
                output[1] = valuem * (inputColor1[1]) + value * (inputColor1[1]) / inputColor2[1];
 
370
        else
 
371
                output[1] = 0.0f;
 
372
        if (inputColor2[2] != 0.0f)
 
373
                output[2] = valuem * (inputColor1[2]) + value * (inputColor1[2]) / inputColor2[2];
 
374
        else
 
375
                output[2] = 0.0f;
 
376
 
 
377
        output[3] = inputColor1[3];
 
378
 
 
379
        clampIfNeeded(output);
 
380
}
 
381
 
 
382
/* ******** Mix Dodge Operation ******** */
 
383
 
 
384
MixDodgeOperation::MixDodgeOperation() : MixBaseOperation()
 
385
{
 
386
        /* pass */
 
387
}
 
388
 
 
389
void MixDodgeOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
 
390
{
 
391
        float inputColor1[4];
 
392
        float inputColor2[4];
 
393
        float inputValue[4];
 
394
        float tmp;
 
395
 
 
396
        this->m_inputValueOperation->read(inputValue, x, y, sampler);
 
397
        this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
 
398
        this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
 
399
 
 
400
        float value = inputValue[0];
 
401
        if (this->useValueAlphaMultiply()) {
 
402
                value *= inputColor2[3];
 
403
        }
 
404
 
 
405
        if (inputColor1[0] != 0.0f) {
 
406
                tmp = 1.0f - value * inputColor2[0];
 
407
                if (tmp <= 0.0f)
 
408
                        output[0] = 1.0f;
 
409
                else {
 
410
                        tmp = inputColor1[0] / tmp;
 
411
                        if (tmp > 1.0f)
 
412
                                output[0] = 1.0f;
 
413
                        else
 
414
                                output[0] = tmp;
 
415
                }
 
416
        }
 
417
        else
 
418
                output[0] = 0.0f;
 
419
 
 
420
        if (inputColor1[1] != 0.0f) {
 
421
                tmp = 1.0f - value * inputColor2[1];
 
422
                if (tmp <= 0.0f)
 
423
                        output[1] = 1.0f;
 
424
                else {
 
425
                        tmp = inputColor1[1] / tmp;
 
426
                        if (tmp > 1.0f)
 
427
                                output[1] = 1.0f;
 
428
                        else
 
429
                                output[1] = tmp;
 
430
                }
 
431
        }
 
432
        else
 
433
                output[1] = 0.0f;
 
434
 
 
435
        if (inputColor1[2] != 0.0f) {
 
436
                tmp = 1.0f - value * inputColor2[2];
 
437
                if (tmp <= 0.0f)
 
438
                        output[2] = 1.0f;
 
439
                else {
 
440
                        tmp = inputColor1[2] / tmp;
 
441
                        if (tmp > 1.0f)
 
442
                                output[2] = 1.0f;
 
443
                        else
 
444
                                output[2] = tmp;
 
445
                }
 
446
        }
 
447
        else
 
448
                output[2] = 0.0f;
 
449
 
 
450
        output[3] = inputColor1[3];
 
451
 
 
452
        clampIfNeeded(output);
 
453
}
 
454
 
 
455
/* ******** Mix Glare Operation ******** */
 
456
 
 
457
MixGlareOperation::MixGlareOperation() : MixBaseOperation()
 
458
{
 
459
        /* pass */
 
460
}
 
461
 
 
462
void MixGlareOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
 
463
{
 
464
        float inputColor1[4];
 
465
        float inputColor2[4];
 
466
        float inputValue[4];
 
467
        float value;
 
468
 
 
469
        this->m_inputValueOperation->read(inputValue, x, y, sampler);
 
470
        this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
 
471
        this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
 
472
        value = inputValue[0];
 
473
        float mf = 2.f - 2.f * fabsf(value - 0.5f);
 
474
 
 
475
        if (inputColor1[0] < 0.0f) inputColor1[0] = 0.0f;
 
476
        if (inputColor1[1] < 0.0f) inputColor1[1] = 0.0f;
 
477
        if (inputColor1[2] < 0.0f) inputColor1[2] = 0.0f;
 
478
 
 
479
        output[0] = mf * max(inputColor1[0] + value * (inputColor2[0] - inputColor1[0]), 0.0f);
 
480
        output[1] = mf * max(inputColor1[1] + value * (inputColor2[1] - inputColor1[1]), 0.0f);
 
481
        output[2] = mf * max(inputColor1[2] + value * (inputColor2[2] - inputColor1[2]), 0.0f);
 
482
        output[3] = inputColor1[3];
 
483
 
 
484
        clampIfNeeded(output);
 
485
}
 
486
 
 
487
/* ******** Mix Hue Operation ******** */
 
488
 
 
489
MixHueOperation::MixHueOperation() : MixBaseOperation()
 
490
{
 
491
        /* pass */
 
492
}
 
493
 
 
494
void MixHueOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
 
495
{
 
496
        float inputColor1[4];
 
497
        float inputColor2[4];
 
498
        float inputValue[4];
 
499
 
 
500
        this->m_inputValueOperation->read(inputValue, x, y, sampler);
 
501
        this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
 
502
        this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
 
503
 
 
504
        float value = inputValue[0];
 
505
        if (this->useValueAlphaMultiply()) {
 
506
                value *= inputColor2[3];
 
507
        }
 
508
        float valuem = 1.0f - value;
 
509
 
 
510
        float colH, colS, colV;
 
511
        rgb_to_hsv(inputColor2[0], inputColor2[1], inputColor2[2], &colH, &colS, &colV);
 
512
        if (colS != 0.0f) {
 
513
                float rH, rS, rV;
 
514
                float tmpr, tmpg, tmpb;
 
515
                rgb_to_hsv(inputColor1[0], inputColor1[1], inputColor1[2], &rH, &rS, &rV);
 
516
                hsv_to_rgb(colH, rS, rV, &tmpr, &tmpg, &tmpb);
 
517
                output[0] = valuem * (inputColor1[0]) + value * tmpr;
 
518
                output[1] = valuem * (inputColor1[1]) + value * tmpg;
 
519
                output[2] = valuem * (inputColor1[2]) + value * tmpb;
 
520
        }
 
521
        else {
 
522
                copy_v3_v3(output, inputColor1);
 
523
        }
 
524
        output[3] = inputColor1[3];
 
525
 
 
526
        clampIfNeeded(output);
 
527
}
 
528
 
 
529
/* ******** Mix Lighten Operation ******** */
 
530
 
 
531
MixLightenOperation::MixLightenOperation() : MixBaseOperation()
 
532
{
 
533
        /* pass */
 
534
}
 
535
 
 
536
void MixLightenOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
 
537
{
 
538
        float inputColor1[4];
 
539
        float inputColor2[4];
 
540
        float inputValue[4];
 
541
 
 
542
        this->m_inputValueOperation->read(inputValue, x, y, sampler);
 
543
        this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
 
544
        this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
 
545
 
 
546
        float value = inputValue[0];
 
547
        if (this->useValueAlphaMultiply()) {
 
548
                value *= inputColor2[3];
 
549
        }
 
550
        float tmp;
 
551
        tmp = value * inputColor2[0];
 
552
        if (tmp > inputColor1[0]) output[0] = tmp;
 
553
        else output[0] = inputColor1[0];
 
554
        tmp = value * inputColor2[1];
 
555
        if (tmp > inputColor1[1]) output[1] = tmp;
 
556
        else output[1] = inputColor1[1];
 
557
        tmp = value * inputColor2[2];
 
558
        if (tmp > inputColor1[2]) output[2] = tmp;
 
559
        else output[2] = inputColor1[2];
 
560
        output[3] = inputColor1[3];
 
561
 
 
562
        clampIfNeeded(output);
 
563
}
 
564
 
 
565
/* ******** Mix Linear Light Operation ******** */
 
566
 
 
567
MixLinearLightOperation::MixLinearLightOperation() : MixBaseOperation()
 
568
{
 
569
        /* pass */
 
570
}
 
571
 
 
572
void MixLinearLightOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
 
573
{
 
574
        float inputColor1[4];
 
575
        float inputColor2[4];
 
576
        float inputValue[4];
 
577
 
 
578
        this->m_inputValueOperation->read(inputValue, x, y, sampler);
 
579
        this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
 
580
        this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
 
581
 
 
582
        float value = inputValue[0];
 
583
        if (this->useValueAlphaMultiply()) {
 
584
                value *= inputColor2[3];
 
585
        }
 
586
        if (inputColor2[0] > 0.5f)
 
587
                output[0] = inputColor1[0] + value * (2.0f * (inputColor2[0] - 0.5f));
 
588
        else
 
589
                output[0] = inputColor1[0] + value * (2.0f * (inputColor2[0]) - 1.0f);
 
590
        if (inputColor2[1] > 0.5f)
 
591
                output[1] = inputColor1[1] + value * (2.0f * (inputColor2[1] - 0.5f));
 
592
        else
 
593
                output[1] = inputColor1[1] + value * (2.0f * (inputColor2[1]) - 1.0f);
 
594
        if (inputColor2[2] > 0.5f)
 
595
                output[2] = inputColor1[2] + value * (2.0f * (inputColor2[2] - 0.5f));
 
596
        else
 
597
                output[2] = inputColor1[2] + value * (2.0f * (inputColor2[2]) - 1.0f);
 
598
 
 
599
        output[3] = inputColor1[3];
 
600
 
 
601
        clampIfNeeded(output);
 
602
}
 
603
 
 
604
/* ******** Mix Multiply Operation ******** */
 
605
 
 
606
MixMultiplyOperation::MixMultiplyOperation() : MixBaseOperation()
 
607
{
 
608
        /* pass */
 
609
}
 
610
 
 
611
void MixMultiplyOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
 
612
{
 
613
        float inputColor1[4];
 
614
        float inputColor2[4];
 
615
        float inputValue[4];
 
616
 
 
617
        this->m_inputValueOperation->read(inputValue, x, y, sampler);
 
618
        this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
 
619
        this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
 
620
 
 
621
        float value = inputValue[0];
 
622
        if (this->useValueAlphaMultiply()) {
 
623
                value *= inputColor2[3];
 
624
        }
 
625
        float valuem = 1.0f - value;
 
626
        output[0] = inputColor1[0] * (valuem + value * inputColor2[0]);
 
627
        output[1] = inputColor1[1] * (valuem + value * inputColor2[1]);
 
628
        output[2] = inputColor1[2] * (valuem + value * inputColor2[2]);
 
629
        output[3] = inputColor1[3];
 
630
 
 
631
        clampIfNeeded(output);
 
632
}
 
633
 
 
634
/* ******** Mix Ovelray Operation ******** */
 
635
 
 
636
MixOverlayOperation::MixOverlayOperation() : MixBaseOperation()
 
637
{
 
638
        /* pass */
 
639
}
 
640
 
 
641
void MixOverlayOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
 
642
{
 
643
        float inputColor1[4];
 
644
        float inputColor2[4];
 
645
        float inputValue[4];
 
646
 
 
647
        this->m_inputValueOperation->read(inputValue, x, y, sampler);
 
648
        this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
 
649
        this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
 
650
 
 
651
        float value = inputValue[0];
 
652
        if (this->useValueAlphaMultiply()) {
 
653
                value *= inputColor2[3];
 
654
        }
 
655
 
 
656
        float valuem = 1.0f - value;
 
657
 
 
658
        if (inputColor1[0] < 0.5f) {
 
659
                output[0] = inputColor1[0] * (valuem + 2.0f * value * inputColor2[0]);
 
660
        }
 
661
        else {
 
662
                output[0] = 1.0f - (valuem + 2.0f * value * (1.0f - inputColor2[0])) * (1.0f - inputColor1[0]);
 
663
        }
 
664
        if (inputColor1[1] < 0.5f) {
 
665
                output[1] = inputColor1[1] * (valuem + 2.0f * value * inputColor2[1]);
 
666
        }
 
667
        else {
 
668
                output[1] = 1.0f - (valuem + 2.0f * value * (1.0f - inputColor2[1])) * (1.0f - inputColor1[1]);
 
669
        }
 
670
        if (inputColor1[2] < 0.5f) {
 
671
                output[2] = inputColor1[2] * (valuem + 2.0f * value * inputColor2[2]);
 
672
        }
 
673
        else {
 
674
                output[2] = 1.0f - (valuem + 2.0f * value * (1.0f - inputColor2[2])) * (1.0f - inputColor1[2]);
 
675
        }
 
676
        output[3] = inputColor1[3];
 
677
 
 
678
        clampIfNeeded(output);
 
679
}
 
680
 
 
681
/* ******** Mix Saturation Operation ******** */
 
682
 
 
683
MixSaturationOperation::MixSaturationOperation() : MixBaseOperation()
 
684
{
 
685
        /* pass */
 
686
}
 
687
 
 
688
void MixSaturationOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
 
689
{
 
690
        float inputColor1[4];
 
691
        float inputColor2[4];
 
692
        float inputValue[4];
 
693
 
 
694
        this->m_inputValueOperation->read(inputValue, x, y, sampler);
 
695
        this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
 
696
        this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
 
697
 
 
698
        float value = inputValue[0];
 
699
        if (this->useValueAlphaMultiply()) {
 
700
                value *= inputColor2[3];
 
701
        }
 
702
        float valuem = 1.0f - value;
 
703
 
 
704
        float rH, rS, rV;
 
705
        rgb_to_hsv(inputColor1[0], inputColor1[1], inputColor1[2], &rH, &rS, &rV);
 
706
        if (rS != 0.0f) {
 
707
                float colH, colS, colV;
 
708
                rgb_to_hsv(inputColor2[0], inputColor2[1], inputColor2[2], &colH, &colS, &colV);
 
709
                hsv_to_rgb(rH, (valuem * rS + value * colS), rV, &output[0], &output[1], &output[2]);
 
710
        }
 
711
        else {
 
712
                copy_v3_v3(output, inputColor1);
 
713
        }
 
714
 
 
715
        output[3] = inputColor1[3];
 
716
 
 
717
        clampIfNeeded(output);
 
718
}
 
719
 
 
720
/* ******** Mix Screen Operation ******** */
 
721
 
 
722
MixScreenOperation::MixScreenOperation() : MixBaseOperation()
 
723
{
 
724
        /* pass */
 
725
}
 
726
 
 
727
void MixScreenOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
 
728
{
 
729
        float inputColor1[4];
 
730
        float inputColor2[4];
 
731
        float inputValue[4];
 
732
 
 
733
        this->m_inputValueOperation->read(inputValue, x, y, sampler);
 
734
        this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
 
735
        this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
 
736
 
 
737
        float value = inputValue[0];
 
738
        if (this->useValueAlphaMultiply()) {
 
739
                value *= inputColor2[3];
 
740
        }
 
741
        float valuem = 1.0f - value;
 
742
 
 
743
        output[0] = 1.0f - (valuem + value * (1.0f - inputColor2[0])) * (1.0f - inputColor1[0]);
 
744
        output[1] = 1.0f - (valuem + value * (1.0f - inputColor2[1])) * (1.0f - inputColor1[1]);
 
745
        output[2] = 1.0f - (valuem + value * (1.0f - inputColor2[2])) * (1.0f - inputColor1[2]);
 
746
        output[3] = inputColor1[3];
 
747
 
 
748
        clampIfNeeded(output);
 
749
}
 
750
 
 
751
/* ******** Mix Soft Light Operation ******** */
 
752
 
 
753
MixSoftLightOperation::MixSoftLightOperation() : MixBaseOperation()
 
754
{
 
755
        /* pass */
 
756
}
 
757
 
 
758
void MixSoftLightOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) \
 
759
{
 
760
        float inputColor1[4];
 
761
        float inputColor2[4];
 
762
        float inputValue[4];
 
763
 
 
764
        this->m_inputValueOperation->read(inputValue, x, y, sampler);
 
765
        this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
 
766
        this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
 
767
 
 
768
        float value = inputValue[0];
 
769
        if (this->useValueAlphaMultiply()) {
 
770
                value *= inputColor2[3];
 
771
        }
 
772
        float valuem = 1.0f - value;
 
773
        float scr, scg, scb;
 
774
 
 
775
        /* first calculate non-fac based Screen mix */
 
776
        scr = 1.0f - (1.0f - inputColor2[0]) * (1.0f - inputColor1[0]);
 
777
        scg = 1.0f - (1.0f - inputColor2[1]) * (1.0f - inputColor1[1]);
 
778
        scb = 1.0f - (1.0f - inputColor2[2]) * (1.0f - inputColor1[2]);
 
779
 
 
780
        output[0] = valuem * (inputColor1[0]) + value * (((1.0f - inputColor1[0]) * inputColor2[0] * (inputColor1[0])) + (inputColor1[0] * scr));
 
781
        output[1] = valuem * (inputColor1[1]) + value * (((1.0f - inputColor1[1]) * inputColor2[1] * (inputColor1[1])) + (inputColor1[1] * scg));
 
782
        output[2] = valuem * (inputColor1[2]) + value * (((1.0f - inputColor1[2]) * inputColor2[2] * (inputColor1[2])) + (inputColor1[2] * scb));
 
783
        output[3] = inputColor1[3];
 
784
 
 
785
        clampIfNeeded(output);
 
786
}
 
787
 
 
788
/* ******** Mix Subtract Operation ******** */
 
789
 
 
790
MixSubtractOperation::MixSubtractOperation() : MixBaseOperation()
 
791
{
 
792
        /* pass */
 
793
}
 
794
 
 
795
void MixSubtractOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
 
796
{
 
797
        float inputColor1[4];
 
798
        float inputColor2[4];
 
799
        float inputValue[4];
 
800
 
 
801
        this->m_inputValueOperation->read(inputValue,   x, y, sampler);
 
802
        this->m_inputColor1Operation->read(inputColor1,   x, y, sampler);
 
803
        this->m_inputColor2Operation->read(inputColor2,   x, y, sampler);
 
804
 
 
805
        float value = inputValue[0];
 
806
        if (this->useValueAlphaMultiply()) {
 
807
                value *= inputColor2[3];
 
808
        }
 
809
        output[0] = inputColor1[0] - value * (inputColor2[0]);
 
810
        output[1] = inputColor1[1] - value * (inputColor2[1]);
 
811
        output[2] = inputColor1[2] - value * (inputColor2[2]);
 
812
        output[3] = inputColor1[3];
 
813
 
 
814
        clampIfNeeded(output);
 
815
}
 
816
 
 
817
/* ******** Mix Value Operation ******** */
 
818
 
 
819
MixValueOperation::MixValueOperation() : MixBaseOperation()
 
820
{
 
821
        /* pass */
 
822
}
 
823
 
 
824
void MixValueOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
 
825
{
 
826
        float inputColor1[4];
 
827
        float inputColor2[4];
 
828
        float inputValue[4];
 
829
 
 
830
        this->m_inputValueOperation->read(inputValue, x, y, sampler);
 
831
        this->m_inputColor1Operation->read(inputColor1, x, y, sampler);
 
832
        this->m_inputColor2Operation->read(inputColor2, x, y, sampler);
 
833
 
 
834
        float value = inputValue[0];
 
835
        if (this->useValueAlphaMultiply()) {
 
836
                value *= inputColor2[3];
 
837
        }
 
838
        float valuem = 1.0f - value;
 
839
 
 
840
        float rH, rS, rV;
 
841
        float colH, colS, colV;
 
842
        rgb_to_hsv(inputColor1[0], inputColor1[1], inputColor1[2], &rH, &rS, &rV);
 
843
        rgb_to_hsv(inputColor2[0], inputColor2[1], inputColor2[2], &colH, &colS, &colV);
 
844
        hsv_to_rgb(rH, rS, (valuem * rV + value * colV), &output[0], &output[1], &output[2]);
 
845
        output[3] = inputColor1[3];
 
846
 
 
847
        clampIfNeeded(output);
 
848
}