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 2006 Øyvind Kolås <pippin@gimp.org>
17 * Copyright 2013 Daniel Sabo
21 #include <glib/gi18n-lib.h>
23 #ifdef GEGL_PROPERTIES
25 property_double (value
, _("Opacity"), 1.0)
26 description (_("Global opacity value that is always used on top of the optional auxiliary input buffer."))
27 value_range (-10.0, 10.0)
32 #define GEGL_OP_POINT_COMPOSER
33 #define GEGL_OP_NAME opacity
34 #define GEGL_OP_C_SOURCE opacity.c
43 prepare (GeglOperation
*self
)
45 const Babl
*space
= gegl_operation_get_source_space (self
, "input");
46 const Babl
*fmt
= gegl_operation_get_source_format (self
, "input");
48 fmt
= gegl_babl_variant (fmt
, GEGL_BABL_VARIANT_ALPHA
);
50 gegl_operation_set_format (self
, "input", fmt
);
51 gegl_operation_set_format (self
, "output", fmt
);
52 gegl_operation_set_format (self
, "aux", babl_format_with_space ("Y float", space
));
57 static inline gfloat
int_fabsf (const gfloat x
)
59 union {gfloat f
; guint32 i
;} u
= {x
};
65 process_premultiplied_float (GeglOperation
*op
,
70 const GeglRectangle
*roi
,
75 gfloat
*out
= out_buf
;
76 gfloat
*aux
= aux_buf
;
77 gfloat value
= GEGL_PROPERTIES (op
)->value
;
84 for (j
=0; j
<components
; j
++)
85 out
[j
] = in
[j
] * value
;
90 else if (int_fabsf (value
- 1.0f
) <= EPSILON
)
94 for (j
=0; j
<components
; j
++)
95 out
[j
] = in
[j
] * (*aux
);
103 gfloat v
= (*aux
) * value
;
105 for (j
=0; j
<components
; j
++)
114 process_with_alpha_float (GeglOperation
*op
,
119 const GeglRectangle
*roi
,
124 gfloat
*out
= out_buf
;
125 gfloat
*aux
= aux_buf
;
126 gint ccomponents
= components
- 1;
127 gfloat value
= GEGL_PROPERTIES (op
)->value
;
134 for (j
=0; j
<ccomponents
; j
++)
136 out
[ccomponents
] = in
[ccomponents
] * value
;
141 else if (int_fabsf (value
- 1.0f
) <= EPSILON
)
145 for (j
=0; j
<ccomponents
; j
++)
147 out
[ccomponents
] = in
[ccomponents
] * (*aux
);
155 gfloat v
= (*aux
) * value
;
157 for (j
=0; j
<ccomponents
; j
++)
159 out
[ccomponents
] = in
[ccomponents
] * v
;
167 process (GeglOperation
*op
,
172 const GeglRectangle
*roi
,
175 const Babl
*format
= gegl_operation_get_format (op
, "output");
176 int components
= babl_format_get_n_components (format
);
178 if (babl_get_model_flags (format
) & BABL_MODEL_FLAG_ASSOCIATED
)
179 process_premultiplied_float (op
, in_buf
, aux_buf
, out_buf
, samples
, roi
, level
, components
);
181 process_with_alpha_float (op
, in_buf
, aux_buf
, out_buf
, samples
, roi
, level
, components
);
186 #include "opencl/gegl-cl.h"
188 #include "opencl/opacity.cl.h"
190 static GeglClRunData
*cl_data
= NULL
;
193 cl_process (GeglOperation
*op
,
197 size_t global_worksize
,
198 const GeglRectangle
*roi
,
208 const char *kernel_name
[] = {"gegl_opacity_RaGaBaA_float", "gegl_opacity_RGBA_float", NULL
};
209 cl_data
= gegl_cl_compile_and_build (opacity_cl_source
, kernel_name
);
211 if (!cl_data
) return TRUE
;
213 fmt
= gegl_operation_get_format(op
, "input");
214 value
= GEGL_PROPERTIES (op
)->value
;
216 kernel
= ((babl_get_model_flags(fmt
) & BABL_MODEL_FLAG_ASSOCIATED
) == 0)? 1 : 0;
218 cl_err
= gegl_clSetKernelArg(cl_data
->kernel
[kernel
], 0, sizeof(cl_mem
), (void*)&in_tex
);
220 cl_err
= gegl_clSetKernelArg(cl_data
->kernel
[kernel
], 1, sizeof(cl_mem
), (aux_tex
)? (void*)&aux_tex
: NULL
);
222 cl_err
= gegl_clSetKernelArg(cl_data
->kernel
[kernel
], 2, sizeof(cl_mem
), (void*)&out_tex
);
224 cl_err
= gegl_clSetKernelArg(cl_data
->kernel
[kernel
], 3, sizeof(cl_float
), (void*)&value
);
227 cl_err
= gegl_clEnqueueNDRangeKernel(gegl_cl_get_command_queue (),
228 cl_data
->kernel
[kernel
], 1,
229 NULL
, &global_worksize
, NULL
,
239 /* Fast path when opacity is a no-op
241 static gboolean
operation_process (GeglOperation
*operation
,
242 GeglOperationContext
*context
,
243 const gchar
*output_prop
,
244 const GeglRectangle
*result
,
247 GeglOperationClass
*operation_class
;
249 gfloat value
= GEGL_PROPERTIES (operation
)->value
;
250 operation_class
= GEGL_OPERATION_CLASS (gegl_op_parent_class
);
252 /* get the raw values this does not increase the reference count */
253 in
= gegl_operation_context_get_object (context
, "input");
254 aux
= gegl_operation_context_get_object (context
, "aux");
256 if (in
&& !aux
&& int_fabsf (value
- 1.0f
) <= EPSILON
)
258 gegl_operation_context_take_object (context
, "output",
259 g_object_ref (G_OBJECT (in
)));
262 /* chain up, which will create the needed buffers for our actual
265 return operation_class
->process (operation
, context
, output_prop
, result
,
266 gegl_operation_context_get_level (context
));
271 gegl_op_class_init (GeglOpClass
*klass
)
273 GeglOperationClass
*operation_class
;
274 GeglOperationPointComposerClass
*point_composer_class
;
276 operation_class
= GEGL_OPERATION_CLASS (klass
);
277 point_composer_class
= GEGL_OPERATION_POINT_COMPOSER_CLASS (klass
);
279 operation_class
->prepare
= prepare
;
280 operation_class
->process
= operation_process
;
281 point_composer_class
->process
= process
;
282 point_composer_class
->cl_process
= cl_process
;
284 operation_class
->opencl_support
= TRUE
;
286 gegl_operation_class_set_keys (operation_class
,
287 "name" , "gegl:opacity",
288 "categories" , "transparency",
289 "title", _("Opacity"),
290 "reference-hash", "b20e8c1d7bb20af95f724191feb10103",
292 _("Weights the opacity of the input both the value of the aux"
293 " input and the global value property."),