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