1 /* GIMP - The GNU Image Manipulation Program
2 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3 *
4 * gimpoperationlayermode-blend.c
5 * Copyright (C) 2017 Michael Natterer <mitch@gimp.org>
6 * 2017 Øyvind Kolås <pippin@gimp.org>
7 * 2017 Ell
8 *
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 */
22
23 #include "config.h"
24
25 #include <gegl-plugin.h>
26 #include <cairo.h>
27 #include <gdk-pixbuf/gdk-pixbuf.h>
28
29 #include "libgimpcolor/gimpcolor.h"
30 #include "libgimpbase/gimpbase.h"
31 #include "libgimpmath/gimpmath.h"
32
33 #include "../operations-types.h"
34
35 #include "gimpoperationlayermode-blend.h"
36
37
38 #define EPSILON 1e-6f
39
40 #define SAFE_DIV_MIN EPSILON
41 #define SAFE_DIV_MAX (1.0f / SAFE_DIV_MIN)
42
43
44 /* local function prototypes */
45
46 static inline gfloat safe_div (gfloat a,
47 gfloat b);
48
49
50 /* private functions */
51
52
53 /* returns a / b, clamped to [-SAFE_DIV_MAX, SAFE_DIV_MAX].
54 * if -SAFE_DIV_MIN <= a <= SAFE_DIV_MIN, returns 0.
55 */
56 static inline gfloat
safe_div(gfloat a,gfloat b)57 safe_div (gfloat a,
58 gfloat b)
59 {
60 gfloat result = 0.0f;
61
62 if (fabsf (a) > SAFE_DIV_MIN)
63 {
64 result = a / b;
65 result = CLAMP (result, -SAFE_DIV_MAX, SAFE_DIV_MAX);
66 }
67
68 return result;
69 }
70
71
72 /* public functions */
73
74
75 /* non-subtractive blending functions. these functions must set comp[ALPHA]
76 * to the same value as layer[ALPHA]. when in[ALPHA] or layer[ALPHA] are
77 * zero, the value of comp[RED..BLUE] is unconstrained (in particular, it may
78 * be NaN).
79 */
80
81
82 void /* aka linear_dodge */
gimp_operation_layer_mode_blend_addition(GeglOperation * operation,const gfloat * in,const gfloat * layer,gfloat * comp,gint samples)83 gimp_operation_layer_mode_blend_addition (GeglOperation *operation,
84 const gfloat *in,
85 const gfloat *layer,
86 gfloat *comp,
87 gint samples)
88 {
89 while (samples--)
90 {
91 if (in[ALPHA] != 0.0f && layer[ALPHA] != 0.0f)
92 {
93 gint c;
94
95 for (c = 0; c < 3; c++)
96 comp[c] = in[c] + layer[c];
97 }
98
99 comp[ALPHA] = layer[ALPHA];
100
101 comp += 4;
102 layer += 4;
103 in += 4;
104 }
105 }
106
107 void
gimp_operation_layer_mode_blend_burn(GeglOperation * operation,const gfloat * in,const gfloat * layer,gfloat * comp,gint samples)108 gimp_operation_layer_mode_blend_burn (GeglOperation *operation,
109 const gfloat *in,
110 const gfloat *layer,
111 gfloat *comp,
112 gint samples)
113 {
114 while (samples--)
115 {
116 if (in[ALPHA] != 0.0f && layer[ALPHA] != 0.0f)
117 {
118 gint c;
119
120 for (c = 0; c < 3; c++)
121 comp[c] = 1.0f - safe_div (1.0f - in[c], layer[c]);
122 }
123
124 comp[ALPHA] = layer[ALPHA];
125
126 comp += 4;
127 layer += 4;
128 in += 4;
129 }
130 }
131
132 void
gimp_operation_layer_mode_blend_darken_only(GeglOperation * operation,const gfloat * in,const gfloat * layer,gfloat * comp,gint samples)133 gimp_operation_layer_mode_blend_darken_only (GeglOperation *operation,
134 const gfloat *in,
135 const gfloat *layer,
136 gfloat *comp,
137 gint samples)
138 {
139 while (samples--)
140 {
141 if (in[ALPHA] != 0.0f && layer[ALPHA] != 0.0f)
142 {
143 gint c;
144
145 for (c = 0; c < 3; c++)
146 comp[c] = MIN (in[c], layer[c]);
147 }
148
149 comp[ALPHA] = layer[ALPHA];
150
151 comp += 4;
152 layer += 4;
153 in += 4;
154 }
155 }
156
157 void
gimp_operation_layer_mode_blend_difference(GeglOperation * operation,const gfloat * in,const gfloat * layer,gfloat * comp,gint samples)158 gimp_operation_layer_mode_blend_difference (GeglOperation *operation,
159 const gfloat *in,
160 const gfloat *layer,
161 gfloat *comp,
162 gint samples)
163 {
164 while (samples--)
165 {
166 if (in[ALPHA] != 0.0f && layer[ALPHA] != 0.0f)
167 {
168 gint c;
169
170 for (c = 0; c < 3; c++)
171 comp[c] = fabsf (in[c] - layer[c]);
172 }
173
174 comp[ALPHA] = layer[ALPHA];
175
176 comp += 4;
177 layer += 4;
178 in += 4;
179 }
180 }
181
182 void
gimp_operation_layer_mode_blend_divide(GeglOperation * operation,const gfloat * in,const gfloat * layer,gfloat * comp,gint samples)183 gimp_operation_layer_mode_blend_divide (GeglOperation *operation,
184 const gfloat *in,
185 const gfloat *layer,
186 gfloat *comp,
187 gint samples)
188 {
189 while (samples--)
190 {
191 if (in[ALPHA] != 0.0f && layer[ALPHA] != 0.0f)
192 {
193 gint c;
194
195 for (c = 0; c < 3; c++)
196 comp[c] = safe_div (in[c], layer[c]);
197 }
198
199 comp[ALPHA] = layer[ALPHA];
200
201 comp += 4;
202 layer += 4;
203 in += 4;
204 }
205 }
206
207 void
gimp_operation_layer_mode_blend_dodge(GeglOperation * operation,const gfloat * in,const gfloat * layer,gfloat * comp,gint samples)208 gimp_operation_layer_mode_blend_dodge (GeglOperation *operation,
209 const gfloat *in,
210 const gfloat *layer,
211 gfloat *comp,
212 gint samples)
213 {
214 while (samples--)
215 {
216 if (in[ALPHA] != 0.0f && layer[ALPHA] != 0.0f)
217 {
218 gint c;
219
220 for (c = 0; c < 3; c++)
221 comp[c] = safe_div (in[c], 1.0f - layer[c]);
222 }
223
224 comp[ALPHA] = layer[ALPHA];
225
226 comp += 4;
227 layer += 4;
228 in += 4;
229 }
230 }
231
232 void
gimp_operation_layer_mode_blend_exclusion(GeglOperation * operation,const gfloat * in,const gfloat * layer,gfloat * comp,gint samples)233 gimp_operation_layer_mode_blend_exclusion (GeglOperation *operation,
234 const gfloat *in,
235 const gfloat *layer,
236 gfloat *comp,
237 gint samples)
238 {
239 while (samples--)
240 {
241 if (in[ALPHA] != 0.0f && layer[ALPHA] != 0.0f)
242 {
243 gint c;
244
245 for (c = 0; c < 3; c++)
246 comp[c] = 0.5f - 2.0f * (in[c] - 0.5f) * (layer[c] - 0.5f);
247 }
248
249 comp[ALPHA] = layer[ALPHA];
250
251 comp += 4;
252 layer += 4;
253 in += 4;
254 }
255 }
256
257 void
gimp_operation_layer_mode_blend_grain_extract(GeglOperation * operation,const gfloat * in,const gfloat * layer,gfloat * comp,gint samples)258 gimp_operation_layer_mode_blend_grain_extract (GeglOperation *operation,
259 const gfloat *in,
260 const gfloat *layer,
261 gfloat *comp,
262 gint samples)
263 {
264 while (samples--)
265 {
266 if (in[ALPHA] != 0.0f && layer[ALPHA] != 0.0f)
267 {
268 gint c;
269
270 for (c = 0; c < 3; c++)
271 comp[c] = in[c] - layer[c] + 0.5f;
272 }
273
274 comp[ALPHA] = layer[ALPHA];
275
276 comp += 4;
277 layer += 4;
278 in += 4;
279 }
280 }
281
282 void
gimp_operation_layer_mode_blend_grain_merge(GeglOperation * operation,const gfloat * in,const gfloat * layer,gfloat * comp,gint samples)283 gimp_operation_layer_mode_blend_grain_merge (GeglOperation *operation,
284 const gfloat *in,
285 const gfloat *layer,
286 gfloat *comp,
287 gint samples)
288 {
289 while (samples--)
290 {
291 if (in[ALPHA] != 0.0f && layer[ALPHA] != 0.0f)
292 {
293 gint c;
294
295 for (c = 0; c < 3; c++)
296 comp[c] = in[c] + layer[c] - 0.5f;
297 }
298
299 comp[ALPHA] = layer[ALPHA];
300
301 comp += 4;
302 layer += 4;
303 in += 4;
304 }
305 }
306
307 void
gimp_operation_layer_mode_blend_hard_mix(GeglOperation * operation,const gfloat * in,const gfloat * layer,gfloat * comp,gint samples)308 gimp_operation_layer_mode_blend_hard_mix (GeglOperation *operation,
309 const gfloat *in,
310 const gfloat *layer,
311 gfloat *comp,
312 gint samples)
313 {
314 while (samples--)
315 {
316 if (in[ALPHA] != 0.0f && layer[ALPHA] != 0.0f)
317 {
318 gint c;
319
320 for (c = 0; c < 3; c++)
321 comp[c] = in[c] + layer[c] < 1.0f ? 0.0f : 1.0f;
322 }
323
324 comp[ALPHA] = layer[ALPHA];
325
326 comp += 4;
327 layer += 4;
328 in += 4;
329 }
330 }
331
332 void
gimp_operation_layer_mode_blend_hardlight(GeglOperation * operation,const gfloat * in,const gfloat * layer,gfloat * comp,gint samples)333 gimp_operation_layer_mode_blend_hardlight (GeglOperation *operation,
334 const gfloat *in,
335 const gfloat *layer,
336 gfloat *comp,
337 gint samples)
338 {
339 while (samples--)
340 {
341 if (in[ALPHA] != 0.0f && layer[ALPHA] != 0.0f)
342 {
343 gint c;
344
345 for (c = 0; c < 3; c++)
346 {
347 gfloat val;
348
349 if (layer[c] > 0.5f)
350 {
351 val = (1.0f - in[c]) * (1.0f - (layer[c] - 0.5f) * 2.0f);
352 val = MIN (1.0f - val, 1.0f);
353 }
354 else
355 {
356 val = in[c] * (layer[c] * 2.0f);
357 val = MIN (val, 1.0f);
358 }
359
360 comp[c] = val;
361 }
362 }
363 comp[ALPHA] = layer[ALPHA];
364
365 comp += 4;
366 layer += 4;
367 in += 4;
368 }
369 }
370
371 void
gimp_operation_layer_mode_blend_hsl_color(GeglOperation * operation,const gfloat * in,const gfloat * layer,gfloat * comp,gint samples)372 gimp_operation_layer_mode_blend_hsl_color (GeglOperation *operation,
373 const gfloat *in,
374 const gfloat *layer,
375 gfloat *comp,
376 gint samples)
377 {
378 while (samples--)
379 {
380 if (in[ALPHA] != 0.0f && layer[ALPHA] != 0.0f)
381 {
382 gfloat dest_min, dest_max, dest_l;
383 gfloat src_min, src_max, src_l;
384
385 dest_min = MIN (in[0], in[1]);
386 dest_min = MIN (dest_min, in[2]);
387 dest_max = MAX (in[0], in[1]);
388 dest_max = MAX (dest_max, in[2]);
389 dest_l = (dest_min + dest_max) / 2.0f;
390
391 src_min = MIN (layer[0], layer[1]);
392 src_min = MIN (src_min, layer[2]);
393 src_max = MAX (layer[0], layer[1]);
394 src_max = MAX (src_max, layer[2]);
395 src_l = (src_min + src_max) / 2.0f;
396
397 if (fabs (src_l) > EPSILON && fabs (1.0 - src_l) > EPSILON)
398 {
399 gboolean dest_high;
400 gboolean src_high;
401 gfloat ratio;
402 gfloat offset;
403 gint c;
404
405 dest_high = dest_l > 0.5f;
406 src_high = src_l > 0.5f;
407
408 dest_l = MIN (dest_l, 1.0f - dest_l);
409 src_l = MIN (src_l, 1.0f - src_l);
410
411 ratio = dest_l / src_l;
412
413 offset = 0.0f;
414 if (dest_high) offset += 1.0f - 2.0f * dest_l;
415 if (src_high) offset += 2.0f * dest_l - ratio;
416
417 for (c = 0; c < 3; c++)
418 comp[c] = layer[c] * ratio + offset;
419 }
420 else
421 {
422 comp[RED] = dest_l;
423 comp[GREEN] = dest_l;
424 comp[BLUE] = dest_l;
425 }
426 }
427
428 comp[ALPHA] = layer[ALPHA];
429
430 comp += 4;
431 layer += 4;
432 in += 4;
433 }
434 }
435
436 void
gimp_operation_layer_mode_blend_hsv_hue(GeglOperation * operation,const gfloat * in,const gfloat * layer,gfloat * comp,gint samples)437 gimp_operation_layer_mode_blend_hsv_hue (GeglOperation *operation,
438 const gfloat *in,
439 const gfloat *layer,
440 gfloat *comp,
441 gint samples)
442 {
443 while (samples--)
444 {
445 if (in[ALPHA] != 0.0f && layer[ALPHA] != 0.0f)
446 {
447 gfloat src_min, src_max, src_delta;
448 gfloat dest_min, dest_max, dest_delta, dest_s;
449
450 src_min = MIN (layer[0], layer[1]);
451 src_min = MIN (src_min, layer[2]);
452 src_max = MAX (layer[0], layer[1]);
453 src_max = MAX (src_max, layer[2]);
454 src_delta = src_max - src_min;
455
456 if (src_delta > EPSILON)
457 {
458 gfloat ratio;
459 gfloat offset;
460 gint c;
461
462 dest_min = MIN (in[0], in[1]);
463 dest_min = MIN (dest_min, in[2]);
464 dest_max = MAX (in[0], in[1]);
465 dest_max = MAX (dest_max, in[2]);
466 dest_delta = dest_max - dest_min;
467 dest_s = dest_max ? dest_delta / dest_max : 0.0f;
468
469 ratio = dest_s * dest_max / src_delta;
470 offset = dest_max - src_max * ratio;
471
472 for (c = 0; c < 3; c++)
473 comp[c] = layer[c] * ratio + offset;
474 }
475 else
476 {
477 gint c;
478
479 for (c = 0; c < 3; c++)
480 comp[c] = in[c];
481 }
482 }
483
484 comp[ALPHA] = layer[ALPHA];
485
486 comp += 4;
487 layer += 4;
488 in += 4;
489 }
490 }
491
492 void
gimp_operation_layer_mode_blend_hsv_saturation(GeglOperation * operation,const gfloat * in,const gfloat * layer,gfloat * comp,gint samples)493 gimp_operation_layer_mode_blend_hsv_saturation (GeglOperation *operation,
494 const gfloat *in,
495 const gfloat *layer,
496 gfloat *comp,
497 gint samples)
498 {
499 while (samples--)
500 {
501 if (in[ALPHA] != 0.0f && layer[ALPHA] != 0.0f)
502 {
503 gfloat src_min, src_max, src_delta, src_s;
504 gfloat dest_min, dest_max, dest_delta;
505
506 dest_min = MIN (in[0], in[1]);
507 dest_min = MIN (dest_min, in[2]);
508 dest_max = MAX (in[0], in[1]);
509 dest_max = MAX (dest_max, in[2]);
510 dest_delta = dest_max - dest_min;
511
512 if (dest_delta > EPSILON)
513 {
514 gfloat ratio;
515 gfloat offset;
516 gint c;
517
518 src_min = MIN (layer[0], layer[1]);
519 src_min = MIN (src_min, layer[2]);
520 src_max = MAX (layer[0], layer[1]);
521 src_max = MAX (src_max, layer[2]);
522 src_delta = src_max - src_min;
523 src_s = src_max ? src_delta / src_max : 0.0f;
524
525 ratio = src_s * dest_max / dest_delta;
526 offset = (1.0f - ratio) * dest_max;
527
528 for (c = 0; c < 3; c++)
529 comp[c] = in[c] * ratio + offset;
530 }
531 else
532 {
533 comp[RED] = dest_max;
534 comp[GREEN] = dest_max;
535 comp[BLUE] = dest_max;
536 }
537 }
538
539 comp[ALPHA] = layer[ALPHA];
540
541 comp += 4;
542 layer += 4;
543 in += 4;
544 }
545 }
546
547 void
gimp_operation_layer_mode_blend_hsv_value(GeglOperation * operation,const gfloat * in,const gfloat * layer,gfloat * comp,gint samples)548 gimp_operation_layer_mode_blend_hsv_value (GeglOperation *operation,
549 const gfloat *in,
550 const gfloat *layer,
551 gfloat *comp,
552 gint samples)
553 {
554 while (samples--)
555 {
556 if (in[ALPHA] != 0.0f && layer[ALPHA] != 0.0f)
557 {
558 gfloat dest_v;
559 gfloat src_v;
560
561 dest_v = MAX (in[0], in[1]);
562 dest_v = MAX (dest_v, in[2]);
563
564 src_v = MAX (layer[0], layer[1]);
565 src_v = MAX (src_v, layer[2]);
566
567 if (fabs (dest_v) > EPSILON)
568 {
569 gfloat ratio = src_v / dest_v;
570 gint c;
571
572 for (c = 0; c < 3; c++)
573 comp[c] = in[c] * ratio;
574 }
575 else
576 {
577 comp[RED] = src_v;
578 comp[GREEN] = src_v;
579 comp[BLUE] = src_v;
580 }
581 }
582
583 comp[ALPHA] = layer[ALPHA];
584
585 comp += 4;
586 layer += 4;
587 in += 4;
588 }
589 }
590
591 void
gimp_operation_layer_mode_blend_lch_chroma(GeglOperation * operation,const gfloat * in,const gfloat * layer,gfloat * comp,gint samples)592 gimp_operation_layer_mode_blend_lch_chroma (GeglOperation *operation,
593 const gfloat *in,
594 const gfloat *layer,
595 gfloat *comp,
596 gint samples)
597 {
598 while (samples--)
599 {
600 if (in[ALPHA] != 0.0f && layer[ALPHA] != 0.0f)
601 {
602 gfloat A1 = in[1];
603 gfloat B1 = in[2];
604 gfloat c1 = hypotf (A1, B1);
605
606 if (c1 > EPSILON)
607 {
608 gfloat A2 = layer[1];
609 gfloat B2 = layer[2];
610 gfloat c2 = hypotf (A2, B2);
611 gfloat A = c2 * A1 / c1;
612 gfloat B = c2 * B1 / c1;
613
614 comp[0] = in[0];
615 comp[1] = A;
616 comp[2] = B;
617 }
618 else
619 {
620 comp[0] = in[0];
621 comp[1] = in[1];
622 comp[2] = in[2];
623 }
624 }
625
626 comp[ALPHA] = layer[ALPHA];
627
628 comp += 4;
629 layer += 4;
630 in += 4;
631 }
632 }
633
634 void
gimp_operation_layer_mode_blend_lch_color(GeglOperation * operation,const gfloat * in,const gfloat * layer,gfloat * comp,gint samples)635 gimp_operation_layer_mode_blend_lch_color (GeglOperation *operation,
636 const gfloat *in,
637 const gfloat *layer,
638 gfloat *comp,
639 gint samples)
640 {
641 while (samples--)
642 {
643 if (in[ALPHA] != 0.0f && layer[ALPHA] != 0.0f)
644 {
645 comp[0] = in[0];
646 comp[1] = layer[1];
647 comp[2] = layer[2];
648 }
649
650 comp[ALPHA] = layer[ALPHA];
651
652 comp += 4;
653 layer += 4;
654 in += 4;
655 }
656 }
657
658 void
gimp_operation_layer_mode_blend_lch_hue(GeglOperation * operation,const gfloat * in,const gfloat * layer,gfloat * comp,gint samples)659 gimp_operation_layer_mode_blend_lch_hue (GeglOperation *operation,
660 const gfloat *in,
661 const gfloat *layer,
662 gfloat *comp,
663 gint samples)
664 {
665 while (samples--)
666 {
667 if (in[ALPHA] != 0.0f && layer[ALPHA] != 0.0f)
668 {
669 gfloat A2 = layer[1];
670 gfloat B2 = layer[2];
671 gfloat c2 = hypotf (A2, B2);
672
673 if (c2 > EPSILON)
674 {
675 gfloat A1 = in[1];
676 gfloat B1 = in[2];
677 gfloat c1 = hypotf (A1, B1);
678 gfloat A = c1 * A2 / c2;
679 gfloat B = c1 * B2 / c2;
680
681 comp[0] = in[0];
682 comp[1] = A;
683 comp[2] = B;
684 }
685 else
686 {
687 comp[0] = in[0];
688 comp[1] = in[1];
689 comp[2] = in[2];
690 }
691 }
692
693 comp[ALPHA] = layer[ALPHA];
694
695 comp += 4;
696 layer += 4;
697 in += 4;
698 }
699 }
700
701 void
gimp_operation_layer_mode_blend_lch_lightness(GeglOperation * operation,const gfloat * in,const gfloat * layer,gfloat * comp,gint samples)702 gimp_operation_layer_mode_blend_lch_lightness (GeglOperation *operation,
703 const gfloat *in,
704 const gfloat *layer,
705 gfloat *comp,
706 gint samples)
707 {
708 while (samples--)
709 {
710 if (in[ALPHA] != 0.0f && layer[ALPHA] != 0.0f)
711 {
712 comp[0] = layer[0];
713 comp[1] = in[1];
714 comp[2] = in[2];
715 }
716
717 comp[ALPHA] = layer[ALPHA];
718
719 comp += 4;
720 layer += 4;
721 in += 4;
722 }
723 }
724
725 void
gimp_operation_layer_mode_blend_lighten_only(GeglOperation * operation,const gfloat * in,const gfloat * layer,gfloat * comp,gint samples)726 gimp_operation_layer_mode_blend_lighten_only (GeglOperation *operation,
727 const gfloat *in,
728 const gfloat *layer,
729 gfloat *comp,
730 gint samples)
731 {
732 while (samples--)
733 {
734 if (in[ALPHA] != 0.0f && layer[ALPHA] != 0.0f)
735 {
736 gint c;
737
738 for (c = 0; c < 3; c++)
739 comp[c] = MAX (in[c], layer[c]);
740 }
741
742 comp[ALPHA] = layer[ALPHA];
743
744 comp += 4;
745 layer += 4;
746 in += 4;
747 }
748 }
749
750 void
gimp_operation_layer_mode_blend_linear_burn(GeglOperation * operation,const gfloat * in,const gfloat * layer,gfloat * comp,gint samples)751 gimp_operation_layer_mode_blend_linear_burn (GeglOperation *operation,
752 const gfloat *in,
753 const gfloat *layer,
754 gfloat *comp,
755 gint samples)
756 {
757 while (samples--)
758 {
759 if (in[ALPHA] != 0.0f && layer[ALPHA] != 0.0f)
760 {
761 gint c;
762
763 for (c = 0; c < 3; c++)
764 comp[c] = in[c] + layer[c] - 1.0f;
765 }
766
767 comp[ALPHA] = layer[ALPHA];
768
769 comp += 4;
770 layer += 4;
771 in += 4;
772 }
773 }
774
775 /* added according to:
776 http://www.deepskycolors.com/archivo/2010/04/21/formulas-for-Photoshop-blending-modes.html */
777 void
gimp_operation_layer_mode_blend_linear_light(GeglOperation * operation,const gfloat * in,const gfloat * layer,gfloat * comp,gint samples)778 gimp_operation_layer_mode_blend_linear_light (GeglOperation *operation,
779 const gfloat *in,
780 const gfloat *layer,
781 gfloat *comp,
782 gint samples)
783 {
784 while (samples--)
785 {
786 if (in[ALPHA] != 0.0f && layer[ALPHA] != 0.0f)
787 {
788 gint c;
789
790 for (c = 0; c < 3; c++)
791 {
792 gfloat val;
793
794 if (layer[c] <= 0.5f)
795 val = in[c] + 2.0f * layer[c] - 1.0f;
796 else
797 val = in[c] + 2.0f * (layer[c] - 0.5f);
798
799 comp[c] = val;
800 }
801 }
802
803 comp[ALPHA] = layer[ALPHA];
804
805 comp += 4;
806 layer += 4;
807 in += 4;
808 }
809 }
810
811 void
gimp_operation_layer_mode_blend_luma_darken_only(GeglOperation * operation,const gfloat * in,const gfloat * layer,gfloat * comp,gint samples)812 gimp_operation_layer_mode_blend_luma_darken_only (GeglOperation *operation,
813 const gfloat *in,
814 const gfloat *layer,
815 gfloat *comp,
816 gint samples)
817 {
818 while (samples--)
819 {
820 if (in[ALPHA] != 0.0f && layer[ALPHA] != 0.0f)
821 {
822 gfloat dest_luminance;
823 gfloat src_luminance;
824 gint c;
825
826 dest_luminance = GIMP_RGB_LUMINANCE (in[0], in[1], in[2]);
827 src_luminance = GIMP_RGB_LUMINANCE (layer[0], layer[1], layer[2]);
828
829 if (dest_luminance <= src_luminance)
830 {
831 for (c = 0; c < 3; c++)
832 comp[c] = in[c];
833 }
834 else
835 {
836 for (c = 0; c < 3; c++)
837 comp[c] = layer[c];
838 }
839 }
840
841 comp[ALPHA] = layer[ALPHA];
842
843 comp += 4;
844 layer += 4;
845 in += 4;
846 }
847 }
848
849 void
gimp_operation_layer_mode_blend_luma_lighten_only(GeglOperation * operation,const gfloat * in,const gfloat * layer,gfloat * comp,gint samples)850 gimp_operation_layer_mode_blend_luma_lighten_only (GeglOperation *operation,
851 const gfloat *in,
852 const gfloat *layer,
853 gfloat *comp,
854 gint samples)
855 {
856 while (samples--)
857 {
858 if (in[ALPHA] != 0.0f && layer[ALPHA] != 0.0f)
859 {
860 gfloat dest_luminance;
861 gfloat src_luminance;
862 gint c;
863
864 dest_luminance = GIMP_RGB_LUMINANCE (in[0], in[1], in[2]);
865 src_luminance = GIMP_RGB_LUMINANCE (layer[0], layer[1], layer[2]);
866
867 if (dest_luminance >= src_luminance)
868 {
869 for (c = 0; c < 3; c++)
870 comp[c] = in[c];
871 }
872 else
873 {
874 for (c = 0; c < 3; c++)
875 comp[c] = layer[c];
876 }
877 }
878
879 comp[ALPHA] = layer[ALPHA];
880
881 comp += 4;
882 layer += 4;
883 in += 4;
884 }
885 }
886
887 void
gimp_operation_layer_mode_blend_luminance(GeglOperation * operation,const gfloat * in,const gfloat * layer,gfloat * comp,gint samples)888 gimp_operation_layer_mode_blend_luminance (GeglOperation *operation,
889 const gfloat *in,
890 const gfloat *layer,
891 gfloat *comp,
892 gint samples)
893 {
894 static const Babl *fish;
895 gfloat *scratch;
896 gfloat *in_Y;
897 gfloat *layer_Y;
898
899 if (! fish)
900 fish = babl_fish ("RGBA float", "Y float");
901
902 scratch = gegl_scratch_new (gfloat, 2 * samples);
903
904 in_Y = scratch;
905 layer_Y = scratch + samples;
906
907 babl_process (fish, in, in_Y, samples);
908 babl_process (fish, layer, layer_Y, samples);
909
910 while (samples--)
911 {
912 if (layer[ALPHA] != 0.0f && in[ALPHA] != 0.0f)
913 {
914 gfloat ratio = safe_div (layer_Y[0], in_Y[0]);
915 gint c;
916
917 for (c = 0; c < 3; c ++)
918 comp[c] = in[c] * ratio;
919 }
920
921 comp[ALPHA] = layer[ALPHA];
922
923 comp += 4;
924 in += 4;
925 layer += 4;
926 in_Y ++;
927 layer_Y ++;
928 }
929
930 gegl_scratch_free (scratch);
931 }
932
933 void
gimp_operation_layer_mode_blend_multiply(GeglOperation * operation,const gfloat * in,const gfloat * layer,gfloat * comp,gint samples)934 gimp_operation_layer_mode_blend_multiply (GeglOperation *operation,
935 const gfloat *in,
936 const gfloat *layer,
937 gfloat *comp,
938 gint samples)
939 {
940 while (samples--)
941 {
942 if (in[ALPHA] != 0.0f && layer[ALPHA] != 0.0f)
943 {
944 gint c;
945
946 for (c = 0; c < 3; c++)
947 comp[c] = in[c] * layer[c];
948 }
949
950 comp[ALPHA] = layer[ALPHA];
951
952 comp += 4;
953 layer += 4;
954 in += 4;
955 }
956 }
957
958 void
gimp_operation_layer_mode_blend_overlay(GeglOperation * operation,const gfloat * in,const gfloat * layer,gfloat * comp,gint samples)959 gimp_operation_layer_mode_blend_overlay (GeglOperation *operation,
960 const gfloat *in,
961 const gfloat *layer,
962 gfloat *comp,
963 gint samples)
964 {
965 while (samples--)
966 {
967 if (in[ALPHA] != 0.0f && layer[ALPHA] != 0.0f)
968 {
969 gint c;
970
971 for (c = 0; c < 3; c++)
972 {
973 gfloat val;
974
975 if (in[c] < 0.5f)
976 val = 2.0f * in[c] * layer[c];
977 else
978 val = 1.0f - 2.0f * (1.0f - layer[c]) * (1.0f - in[c]);
979
980 comp[c] = val;
981 }
982 }
983 comp[ALPHA] = layer[ALPHA];
984
985 comp += 4;
986 layer += 4;
987 in += 4;
988 }
989 }
990
991 /* added according to:
992 http://www.deepskycolors.com/archivo/2010/04/21/formulas-for-Photoshop-blending-modes.html */
993 void
gimp_operation_layer_mode_blend_pin_light(GeglOperation * operation,const gfloat * in,const gfloat * layer,gfloat * comp,gint samples)994 gimp_operation_layer_mode_blend_pin_light (GeglOperation *operation,
995 const gfloat *in,
996 const gfloat *layer,
997 gfloat *comp,
998 gint samples)
999 {
1000 while (samples--)
1001 {
1002 if (in[ALPHA] != 0.0f && layer[ALPHA] != 0.0f)
1003 {
1004 gint c;
1005
1006 for (c = 0; c < 3; c++)
1007 {
1008 gfloat val;
1009
1010 if (layer[c] > 0.5f)
1011 val = MAX(in[c], 2.0f * (layer[c] - 0.5f));
1012 else
1013 val = MIN(in[c], 2.0f * layer[c]);
1014
1015 comp[c] = val;
1016 }
1017 }
1018
1019 comp[ALPHA] = layer[ALPHA];
1020
1021 comp += 4;
1022 layer += 4;
1023 in += 4;
1024 }
1025 }
1026
1027 void
gimp_operation_layer_mode_blend_screen(GeglOperation * operation,const gfloat * in,const gfloat * layer,gfloat * comp,gint samples)1028 gimp_operation_layer_mode_blend_screen (GeglOperation *operation,
1029 const gfloat *in,
1030 const gfloat *layer,
1031 gfloat *comp,
1032 gint samples)
1033 {
1034 while (samples--)
1035 {
1036 if (in[ALPHA] != 0.0f && layer[ALPHA] != 0.0f)
1037 {
1038 gint c;
1039
1040 for (c = 0; c < 3; c++)
1041 comp[c] = 1.0f - (1.0f - in[c]) * (1.0f - layer[c]);
1042 }
1043
1044 comp[ALPHA] = layer[ALPHA];
1045
1046 comp += 4;
1047 layer += 4;
1048 in += 4;
1049 }
1050 }
1051
1052 void
gimp_operation_layer_mode_blend_softlight(GeglOperation * operation,const gfloat * in,const gfloat * layer,gfloat * comp,gint samples)1053 gimp_operation_layer_mode_blend_softlight (GeglOperation *operation,
1054 const gfloat *in,
1055 const gfloat *layer,
1056 gfloat *comp,
1057 gint samples)
1058 {
1059 while (samples--)
1060 {
1061 if (in[ALPHA] != 0.0f && layer[ALPHA] != 0.0f)
1062 {
1063 gint c;
1064
1065 for (c = 0; c < 3; c++)
1066 {
1067 gfloat multiply = in[c] * layer[c];
1068 gfloat screen = 1.0f - (1.0f - in[c]) * (1.0f - layer[c]);
1069 gfloat val = (1.0f - in[c]) * multiply + in[c] * screen;
1070
1071 comp[c] = val;
1072 }
1073 }
1074 comp[ALPHA] = layer[ALPHA];
1075
1076 comp += 4;
1077 layer += 4;
1078 in += 4;
1079 }
1080 }
1081
1082 void
gimp_operation_layer_mode_blend_subtract(GeglOperation * operation,const gfloat * in,const gfloat * layer,gfloat * comp,gint samples)1083 gimp_operation_layer_mode_blend_subtract (GeglOperation *operation,
1084 const gfloat *in,
1085 const gfloat *layer,
1086 gfloat *comp,
1087 gint samples)
1088 {
1089 while (samples--)
1090 {
1091 if (in[ALPHA] != 0.0f && layer[ALPHA] != 0.0f)
1092 {
1093 gint c;
1094
1095 for (c = 0; c < 3; c++)
1096 comp[c] = in[c] - layer[c];
1097 }
1098
1099 comp[ALPHA] = layer[ALPHA];
1100
1101 comp += 4;
1102 layer += 4;
1103 in += 4;
1104 }
1105 }
1106
1107 /* added according to:
1108 http://www.simplefilter.de/en/basics/mixmods.html */
1109 void
gimp_operation_layer_mode_blend_vivid_light(GeglOperation * operation,const gfloat * in,const gfloat * layer,gfloat * comp,gint samples)1110 gimp_operation_layer_mode_blend_vivid_light (GeglOperation *operation,
1111 const gfloat *in,
1112 const gfloat *layer,
1113 gfloat *comp,
1114 gint samples)
1115 {
1116 while (samples--)
1117 {
1118 if (in[ALPHA] != 0.0f && layer[ALPHA] != 0.0f)
1119 {
1120 gint c;
1121
1122 for (c = 0; c < 3; c++)
1123 {
1124 gfloat val;
1125
1126 if (layer[c] <= 0.5f)
1127 {
1128 val = 1.0f - safe_div (1.0f - in[c], 2.0f * layer[c]);
1129 val = MAX (val, 0.0f);
1130 }
1131 else
1132 {
1133 val = safe_div (in[c], 2.0f * (1.0f - layer[c]));
1134 val = MIN (val, 1.0f);
1135 }
1136
1137 comp[c] = val;
1138 }
1139 }
1140
1141 comp[ALPHA] = layer[ALPHA];
1142
1143 comp += 4;
1144 layer += 4;
1145 in += 4;
1146 }
1147 }
1148
1149
1150 /* subtractive blending functions. these functions must set comp[ALPHA] to
1151 * the modified alpha of the overlapping content, as a fraction of the
1152 * original overlapping content (i.e., an alpha of 1.0 specifies that no
1153 * content is subtracted.) when in[ALPHA] or layer[ALPHA] are zero, the value
1154 * of comp[RED..BLUE] is unconstrained (in particular, it may be NaN).
1155 */
1156
1157
1158 void
gimp_operation_layer_mode_blend_color_erase(GeglOperation * operation,const gfloat * in,const gfloat * layer,gfloat * comp,gint samples)1159 gimp_operation_layer_mode_blend_color_erase (GeglOperation *operation,
1160 const gfloat *in,
1161 const gfloat *layer,
1162 gfloat *comp,
1163 gint samples)
1164 {
1165 while (samples--)
1166 {
1167 if (in[ALPHA] != 0.0f && layer[ALPHA] != 0.0f)
1168 {
1169 const gfloat *color = in;
1170 const gfloat *bgcolor = layer;
1171 gfloat alpha;
1172 gint c;
1173
1174 alpha = 0.0f;
1175
1176 for (c = 0; c < 3; c++)
1177 {
1178 gfloat col = CLAMP (color[c], 0.0f, 1.0f);
1179 gfloat bgcol = CLAMP (bgcolor[c], 0.0f, 1.0f);
1180
1181 if (fabs (col - bgcol) > EPSILON)
1182 {
1183 gfloat a;
1184
1185 if (col > bgcol)
1186 a = (col - bgcol) / (1.0f - bgcol);
1187 else
1188 a = (bgcol - col) / bgcol;
1189
1190 alpha = MAX (alpha, a);
1191 }
1192 }
1193
1194 if (alpha > EPSILON)
1195 {
1196 gfloat alpha_inv = 1.0f / alpha;
1197
1198 for (c = 0; c < 3; c++)
1199 comp[c] = (color[c] - bgcolor[c]) * alpha_inv + bgcolor[c];
1200 }
1201 else
1202 {
1203 comp[RED] = comp[GREEN] = comp[BLUE] = 0.0f;
1204 }
1205
1206 comp[ALPHA] = alpha;
1207 }
1208 else
1209 comp[ALPHA] = 0.0f;
1210
1211 comp += 4;
1212 layer += 4;
1213 in += 4;
1214 }
1215 }
1216