1 /* This file is an image processing operation for GEGL
3 * GEGL is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 3 of the License, or (at your option) any later version.
8 * GEGL is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with GEGL; if not, see <https://www.gnu.org/licenses/>.
16 * Copyright 2015 Thomas Manni <thomas.manni@free.fr>
17 * 2023 Øyvind Kolås <pippin@gimp.org>
22 #include <glib/gi18n-lib.h>
24 #ifdef GEGL_PROPERTIES
26 property_boolean (clip_low
, _("Clip low pixel values"), TRUE
)
27 description (_("Clip low pixel values"))
29 property_double (low_limit
, _("Low limit"), 0.0)
30 value_range (-G_MAXDOUBLE
, G_MAXDOUBLE
)
32 description (_("Pixels values lower than this limit will be set to it"))
33 ui_meta ("sensitive", "clip-low")
35 property_boolean (clip_high
, _("Clip high pixel values"), TRUE
)
36 description (_("Clip high pixel values"))
38 property_double (high_limit
, _("High limit"), 1.0)
39 value_range (-G_MAXDOUBLE
, G_MAXDOUBLE
)
41 description (_("Pixels values higher than this limit will be set to it"))
42 ui_meta ("sensitive", "clip-high")
46 #define GEGL_OP_POINT_FILTER
47 #define GEGL_OP_NAME alpha_clip
48 #define GEGL_OP_C_SOURCE alpha-clip.c
53 prepare (GeglOperation
*operation
)
55 const Babl
*space
= gegl_operation_get_source_space (operation
, "input");
56 const Babl
*src_format
= gegl_operation_get_source_format (operation
, "input");
57 const char *format
= "RGBA float";
61 const Babl
*model
= babl_format_get_model (src_format
);
63 if (babl_model_is (model
, "RGB"))
64 format
= "RGBA float";
65 else if (babl_model_is (model
, "RGBA"))
66 format
= "RGBA float";
67 else if (babl_model_is (model
, "R'G'B'"))
68 format
= "R'G'B'A float";
69 else if (babl_model_is (model
, "R'G'B'A"))
70 format
= "R'G'B'A float";
73 gegl_operation_set_format (operation
, "input", babl_format_with_space (format
, space
));
74 gegl_operation_set_format (operation
, "output", babl_format_with_space (format
, space
));
78 process (GeglOperation
*operation
,
82 const GeglRectangle
*roi
,
85 GeglProperties
*o
= GEGL_PROPERTIES (operation
);
86 gint n_components
= 4;
87 gfloat
*input
= in_buf
;
88 gfloat
*output
= out_buf
;
90 float low_limit
= o
->low_limit
;
91 float high_limit
= o
->high_limit
;
93 if (o
->clip_low
&& o
->clip_high
)
97 for (int i
= 0; i
< 3; i
++) output
[i
] = input
[i
];
98 output
[3] = CLAMP (input
[3], low_limit
, high_limit
);
100 input
+= n_components
;
101 output
+= n_components
;
105 else if (o
->clip_high
)
109 for (int i
= 0; i
< 3; i
++) output
[i
] = input
[i
];
110 output
[3] = input
[3] > high_limit
? high_limit
: input
[3];
112 input
+= n_components
;
113 output
+= n_components
;
117 else if (o
->clip_low
)
121 for (int i
= 0; i
< 3; i
++) output
[i
] = input
[i
];
122 output
[3] = input
[3] < low_limit
? low_limit
: input
[3];
124 input
+= n_components
;
125 output
+= n_components
;
133 operation_process (GeglOperation
*operation
,
134 GeglOperationContext
*context
,
135 const gchar
*output_prop
,
136 const GeglRectangle
*result
,
139 GeglOperationClass
*operation_class
;
140 GeglProperties
*o
= GEGL_PROPERTIES (operation
);
142 operation_class
= GEGL_OPERATION_CLASS (gegl_op_parent_class
);
144 if (!o
->clip_high
&& !o
->clip_low
)
146 gpointer in
= gegl_operation_context_get_object (context
, "input");
147 gegl_operation_context_take_object (context
, "output",
148 g_object_ref (G_OBJECT (in
)));
152 /* chain up, which will create the needed buffers for our actual
155 return operation_class
->process (operation
, context
, output_prop
, result
,
156 gegl_operation_context_get_level (context
));
160 gegl_op_class_init (GeglOpClass
*klass
)
162 GeglOperationClass
*operation_class
;
163 GeglOperationPointFilterClass
*filter_class
;
165 "<?xml version='1.0' encoding='UTF-8'?>"
167 " <node operation='gegl:crop' width='200' height='200'/>"
168 " <node operation='gegl:over'>"
169 " <node operation='gegl:alpha-clip'>"
171 " <param name='low_limit'>0.2</param>"
172 " <param name='high_limit'>0.8</param>"
175 " <node operation='gegl:load' path='standard-input.png'/>"
177 " <node operation='gegl:checkerboard'>"
179 " <param name='color1'>rgb(0.25,0.25,0.25)</param>"
180 " <param name='color2'>rgb(0.75,0.75,0.75)</param>"
185 operation_class
= GEGL_OPERATION_CLASS (klass
);
186 filter_class
= GEGL_OPERATION_POINT_FILTER_CLASS (klass
);
188 operation_class
->prepare
= prepare
;
189 operation_class
->process
= operation_process
;
190 operation_class
->opencl_support
= FALSE
;
192 filter_class
->process
= process
;
194 gegl_operation_class_set_keys (operation_class
,
195 "name", "gegl:alpha-clip",
196 "title", _("Clip Alpha"),
197 "categories", "color",
198 "reference-composition", composition
,
199 "description", _("Keep alpha values inside a specific range"),