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