blob: d77abbd4fb9e8f87a65ce0e8022c4d65a1f26cce [file] [log] [blame]
Thiago Santos2f9a6302010-06-02 00:34:36 -03001/*
2 * GStreamer
3 * Copyright (C) 2010 Thiago Santos <thiago.sousa.santos@collabora.co.uk>
Thiago Santos44d33ee2010-06-04 15:53:20 -03004 *
Thiago Santos2f9a6302010-06-02 00:34:36 -03005 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 *
23 * Alternatively, the contents of this file may be used under the
24 * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
25 * which case the following provisions apply instead of the ones
26 * mentioned above:
27 *
28 * This library is free software; you can redistribute it and/or
29 * modify it under the terms of the GNU Library General Public
30 * License as published by the Free Software Foundation; either
31 * version 2 of the License, or (at your option) any later version.
32 *
33 * This library is distributed in the hope that it will be useful,
34 * but WITHOUT ANY WARRANTY; without even the implied warranty of
35 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
36 * Library General Public License for more details.
37 *
38 * You should have received a copy of the GNU Library General Public
39 * License along with this library; if not, write to the
Tim-Philipp Müller9e1b75f2012-11-03 20:38:00 +000040 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
41 * Boston, MA 02110-1301, USA.
Thiago Santos2f9a6302010-06-02 00:34:36 -030042 */
43
44/*
45 * Thanks to Jerry Huxtable <http://www.jhlabs.com> work on its java
46 * image editor and filters. The algorithms here were extracted from
47 * his code.
48 */
49
50
51#ifdef HAVE_CONFIG_H
52# include <config.h>
53#endif
54
55#include <gst/gst.h>
56#include <math.h>
57
58#include "gstcirclegeometrictransform.h"
59
60GST_DEBUG_CATEGORY_STATIC (gst_circle_geometric_transform_debug);
61#define GST_CAT_DEFAULT gst_circle_geometric_transform_debug
62
63GstGeometricTransformClass *parent_class;
64
65enum
66{
67 PROP_0,
68 PROP_X_CENTER,
69 PROP_Y_CENTER,
70 PROP_RADIUS
71};
72
73#define DEFAULT_X_CENTER 0.5
74#define DEFAULT_Y_CENTER 0.5
Filippo Argiolasc9210672010-08-03 10:08:34 +020075#define DEFAULT_RADIUS 0.35
Thiago Santos2f9a6302010-06-02 00:34:36 -030076
77static void
78gst_circle_geometric_transform_set_property (GObject * object, guint prop_id,
79 const GValue * value, GParamSpec * pspec)
80{
Thiago Santos1c33b792010-06-07 22:21:10 -030081 GstCircleGeometricTransform *cgt;
82 GstGeometricTransform *gt;
83 gdouble v;
Thiago Santos2f9a6302010-06-02 00:34:36 -030084
Thiago Santos1c33b792010-06-07 22:21:10 -030085 gt = GST_GEOMETRIC_TRANSFORM_CAST (object);
86 cgt = GST_CIRCLE_GEOMETRIC_TRANSFORM_CAST (object);
Thiago Santos2f9a6302010-06-02 00:34:36 -030087
Thiago Santos1c33b792010-06-07 22:21:10 -030088 GST_OBJECT_LOCK (cgt);
Thiago Santos2f9a6302010-06-02 00:34:36 -030089 switch (prop_id) {
90 case PROP_X_CENTER:
Thiago Santos1c33b792010-06-07 22:21:10 -030091 v = g_value_get_double (value);
92 if (v != cgt->x_center) {
93 cgt->x_center = v;
94 gst_geometric_transform_set_need_remap (gt);
95 }
Thiago Santos2f9a6302010-06-02 00:34:36 -030096 break;
97 case PROP_Y_CENTER:
Thiago Santos1c33b792010-06-07 22:21:10 -030098 v = g_value_get_double (value);
99 if (v != cgt->y_center) {
100 cgt->y_center = v;
101 gst_geometric_transform_set_need_remap (gt);
102 }
Thiago Santos2f9a6302010-06-02 00:34:36 -0300103 break;
104 case PROP_RADIUS:
Thiago Santos1c33b792010-06-07 22:21:10 -0300105 v = g_value_get_double (value);
106 if (v != cgt->radius) {
107 cgt->radius = v;
108 gst_geometric_transform_set_need_remap (gt);
109 }
Thiago Santos2f9a6302010-06-02 00:34:36 -0300110 break;
111 default:
112 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
113 break;
114 }
Thiago Santos1c33b792010-06-07 22:21:10 -0300115 GST_OBJECT_UNLOCK (cgt);
Thiago Santos2f9a6302010-06-02 00:34:36 -0300116}
117
118static void
119gst_circle_geometric_transform_get_property (GObject * object, guint prop_id,
120 GValue * value, GParamSpec * pspec)
121{
Thiago Santos1c33b792010-06-07 22:21:10 -0300122 GstCircleGeometricTransform *cgt;
Thiago Santos2f9a6302010-06-02 00:34:36 -0300123
Thiago Santos1c33b792010-06-07 22:21:10 -0300124 cgt = GST_CIRCLE_GEOMETRIC_TRANSFORM_CAST (object);
Thiago Santos2f9a6302010-06-02 00:34:36 -0300125
126 switch (prop_id) {
127 case PROP_X_CENTER:
Thiago Santos1c33b792010-06-07 22:21:10 -0300128 g_value_set_double (value, cgt->x_center);
Thiago Santos2f9a6302010-06-02 00:34:36 -0300129 break;
130 case PROP_Y_CENTER:
Thiago Santos1c33b792010-06-07 22:21:10 -0300131 g_value_set_double (value, cgt->y_center);
Thiago Santos2f9a6302010-06-02 00:34:36 -0300132 break;
133 case PROP_RADIUS:
Thiago Santos1c33b792010-06-07 22:21:10 -0300134 g_value_set_double (value, cgt->radius);
Thiago Santos2f9a6302010-06-02 00:34:36 -0300135 break;
136 default:
137 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
138 break;
139 }
140}
141
Thiago Santos2f9a6302010-06-02 00:34:36 -0300142/* GObject vmethod implementations */
143
144static gboolean
145circle_geometric_transform_precalc (GstGeometricTransform * gt)
146{
147 GstCircleGeometricTransform *cgt = GST_CIRCLE_GEOMETRIC_TRANSFORM_CAST (gt);
148
149 cgt->precalc_x_center = cgt->x_center * gt->width;
150 cgt->precalc_y_center = cgt->y_center * gt->height;
Filippo Argiolasc9210672010-08-03 10:08:34 +0200151 cgt->precalc_radius =
152 cgt->radius * 0.5 * sqrt (gt->width * gt->width +
153 gt->height * gt->height);
154 cgt->precalc_radius2 = cgt->precalc_radius * cgt->precalc_radius;
Thiago Santos2f9a6302010-06-02 00:34:36 -0300155
156 return TRUE;
157}
158
159static void
160gst_circle_geometric_transform_class_init (GstCircleGeometricTransformClass *
161 klass)
162{
163 GObjectClass *gobject_class;
164 GstGeometricTransformClass *gstgt_class;
165
166 gobject_class = (GObjectClass *) klass;
167 gstgt_class = (GstGeometricTransformClass *) klass;
168
169 parent_class = g_type_class_peek_parent (klass);
170
Sebastian Dröge426c26f2013-12-02 10:25:57 +0100171 gobject_class->set_property = gst_circle_geometric_transform_set_property;
172 gobject_class->get_property = gst_circle_geometric_transform_get_property;
Thiago Santos2f9a6302010-06-02 00:34:36 -0300173
174 /* FIXME I don't like the idea of x-center and y-center being in % and
175 * radius and intensity in absolute values, I think no one likes it, but
176 * I can't see a way to have nice default values without % */
177 g_object_class_install_property (gobject_class, PROP_X_CENTER,
178 g_param_spec_double ("x-center", "x center",
179 "X axis center of the circle_geometric_transform effect",
180 0.0, 1.0, DEFAULT_X_CENTER,
Thiago Santos1c33b792010-06-07 22:21:10 -0300181 GST_PARAM_CONTROLLABLE | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
Thiago Santos2f9a6302010-06-02 00:34:36 -0300182 g_object_class_install_property (gobject_class, PROP_Y_CENTER,
183 g_param_spec_double ("y-center", "y center",
184 "Y axis center of the circle_geometric_transform effect",
185 0.0, 1.0, DEFAULT_Y_CENTER,
Thiago Santos1c33b792010-06-07 22:21:10 -0300186 GST_PARAM_CONTROLLABLE | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
Thiago Santos2f9a6302010-06-02 00:34:36 -0300187 g_object_class_install_property (gobject_class, PROP_RADIUS,
188 g_param_spec_double ("radius", "radius",
Filippo Argiolasc9210672010-08-03 10:08:34 +0200189 "radius of the circle_geometric_transform effect", 0.0, 1.0,
Thiago Santos1c33b792010-06-07 22:21:10 -0300190 DEFAULT_RADIUS,
191 GST_PARAM_CONTROLLABLE | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
Thiago Santos2f9a6302010-06-02 00:34:36 -0300192
193 gstgt_class->prepare_func = circle_geometric_transform_precalc;
194}
195
196static void
197gst_circle_geometric_transform_init (GstCircleGeometricTransform * filter,
198 GstCircleGeometricTransformClass * gclass)
199{
200 filter->x_center = DEFAULT_X_CENTER;
201 filter->y_center = DEFAULT_Y_CENTER;
202 filter->radius = DEFAULT_RADIUS;
203}
204
205GType
206gst_circle_geometric_transform_get_type (void)
207{
208 static GType circle_geometric_transform_type = 0;
209
210 if (!circle_geometric_transform_type) {
211 static const GTypeInfo circle_geometric_transform_info = {
212 sizeof (GstCircleGeometricTransformClass),
213 NULL,
214 NULL,
215 (GClassInitFunc) gst_circle_geometric_transform_class_init,
216 NULL,
217 NULL,
218 sizeof (GstCircleGeometricTransform),
219 0,
220 (GInstanceInitFunc) gst_circle_geometric_transform_init,
221 };
222
223 circle_geometric_transform_type =
224 g_type_register_static (GST_TYPE_GEOMETRIC_TRANSFORM,
225 "GstCircleGeometricTransform", &circle_geometric_transform_info,
226 G_TYPE_FLAG_ABSTRACT);
227
228 GST_DEBUG_CATEGORY_INIT (gst_circle_geometric_transform_debug,
229 "circlegeometrictransform", 0,
230 "Base class for geometric transform elements that operate "
231 "on a circular area");
232 }
233 return circle_geometric_transform_type;
234}