1 /* GIMP - The GNU Image Manipulation Program
2  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3  *
4  * gimpoperationgrainmergemode.c
5  * Copyright (C) 2008 Michael Natterer <mitch@gimp.org>
6  *               2012 Ville Sokk <ville.sokk@gmail.com>
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20  */
21 
22 #include "config.h"
23 
24 #include <gegl-plugin.h>
25 
26 #include "../operations-types.h"
27 
28 #include "gimpoperationgrainmergelegacy.h"
29 
30 
31 static gboolean   gimp_operation_grain_merge_legacy_process (GeglOperation       *op,
32                                                              void                *in,
33                                                              void                *layer,
34                                                              void                *mask,
35                                                              void                *out,
36                                                              glong                samples,
37                                                              const GeglRectangle *roi,
38                                                              gint                 level);
39 
40 
G_DEFINE_TYPE(GimpOperationGrainMergeLegacy,gimp_operation_grain_merge_legacy,GIMP_TYPE_OPERATION_LAYER_MODE)41 G_DEFINE_TYPE (GimpOperationGrainMergeLegacy, gimp_operation_grain_merge_legacy,
42                GIMP_TYPE_OPERATION_LAYER_MODE)
43 
44 
45 static void
46 gimp_operation_grain_merge_legacy_class_init (GimpOperationGrainMergeLegacyClass *klass)
47 {
48   GeglOperationClass          *operation_class  = GEGL_OPERATION_CLASS (klass);
49   GimpOperationLayerModeClass *layer_mode_class = GIMP_OPERATION_LAYER_MODE_CLASS (klass);
50 
51   gegl_operation_class_set_keys (operation_class,
52                                  "name",        "gimp:grain-merge-legacy",
53                                  "description", "GIMP grain merge mode operation",
54                                  NULL);
55 
56   layer_mode_class->process = gimp_operation_grain_merge_legacy_process;
57 }
58 
59 static void
gimp_operation_grain_merge_legacy_init(GimpOperationGrainMergeLegacy * self)60 gimp_operation_grain_merge_legacy_init (GimpOperationGrainMergeLegacy *self)
61 {
62 }
63 
64 static gboolean
gimp_operation_grain_merge_legacy_process(GeglOperation * op,void * in_p,void * layer_p,void * mask_p,void * out_p,glong samples,const GeglRectangle * roi,gint level)65 gimp_operation_grain_merge_legacy_process (GeglOperation       *op,
66                                            void                *in_p,
67                                            void                *layer_p,
68                                            void                *mask_p,
69                                            void                *out_p,
70                                            glong                samples,
71                                            const GeglRectangle *roi,
72                                            gint                 level)
73 {
74   GimpOperationLayerMode *layer_mode = (gpointer) op;
75   gfloat                 *in         = in_p;
76   gfloat                 *out        = out_p;
77   gfloat                 *layer      = layer_p;
78   gfloat                 *mask       = mask_p;
79   gfloat                  opacity    = layer_mode->opacity;
80 
81   while (samples--)
82     {
83       gfloat comp_alpha, new_alpha;
84 
85       comp_alpha = MIN (in[ALPHA], layer[ALPHA]) * opacity;
86       if (mask)
87         comp_alpha *= *mask;
88 
89       new_alpha = in[ALPHA] + (1.0f - in[ALPHA]) * comp_alpha;
90 
91       if (comp_alpha && new_alpha)
92         {
93           gfloat ratio = comp_alpha / new_alpha;
94           gint   b;
95 
96           for (b = RED; b < ALPHA; b++)
97             {
98               gfloat comp = in[b] + layer[b] - 128.0f / 255.0f;
99               comp = CLAMP (comp, 0.0f, 1.0f);
100 
101               out[b] = comp * ratio + in[b] * (1.0f - ratio);
102             }
103         }
104       else
105         {
106           gint b;
107 
108           for (b = RED; b < ALPHA; b++)
109             {
110               out[b] = in[b];
111             }
112         }
113 
114       out[ALPHA] = in[ALPHA];
115 
116       in    += 4;
117       layer += 4;
118       out   += 4;
119 
120       if (mask)
121         mask ++;
122     }
123 
124   return TRUE;
125 }
126