2 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
5 * Copyright (C) 2001 FUKUCHI Kentarou
7 * EffecTV is free software. * This library is free software;
8 * you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library 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 GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
29 #include <gstvideofilter.h>
31 #define GST_TYPE_EDGETV \
32 (gst_edgetv_get_type())
33 #define GST_EDGETV(obj) \
34 (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_EDGETV,GstEdgeTV))
35 #define GST_EDGETV_CLASS(klass) \
36 (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_EDGETV,GstEdgeTVClass))
37 #define GST_IS_EDGETV(obj) \
38 (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_EDGETV))
39 #define GST_IS_EDGETV_CLASS(obj) \
40 (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_EDGETV))
42 typedef struct _GstEdgeTV GstEdgeTV;
43 typedef struct _GstEdgeTVClass GstEdgeTVClass;
47 GstVideofilter videofilter;
50 gint map_width, map_height;
52 gint video_width_margin;
55 struct _GstEdgeTVClass
57 GstVideofilterClass parent_class;
60 /* Filter signals and args */
72 static void gst_edgetv_base_init (gpointer g_class);
73 static void gst_edgetv_class_init (gpointer g_class, gpointer class_data);
74 static void gst_edgetv_init (GTypeInstance * instance, gpointer g_class);
76 static void gst_edgetv_set_property (GObject * object, guint prop_id,
77 const GValue * value, GParamSpec * pspec);
78 static void gst_edgetv_get_property (GObject * object, guint prop_id,
79 GValue * value, GParamSpec * pspec);
81 static void gst_edgetv_setup (GstVideofilter * videofilter);
82 static void gst_edgetv_rgb32 (GstVideofilter * videofilter, void *d, void *s);
84 /*static guint gst_edgetv_signals[LAST_SIGNAL] = { 0 }; */
87 gst_edgetv_get_type (void)
89 static GType edgetv_type = 0;
92 static const GTypeInfo edgetv_info = {
93 sizeof (GstEdgeTVClass),
96 (GClassInitFunc) gst_edgetv_class_init,
101 (GInstanceInitFunc) gst_edgetv_init,
105 g_type_register_static (GST_TYPE_VIDEOFILTER, "GstEdgeTV", &edgetv_info,
111 static GstVideofilterFormat gst_edgetv_formats[] = {
112 {"RGB ", 32, gst_edgetv_rgb32, 24, G_BIG_ENDIAN, 0x0000ff00, 0x00ff0000,
117 gst_edgetv_base_init (gpointer g_class)
119 /* elementfactory information */
120 static GstElementDetails gst_edgetv_details = GST_ELEMENT_DETAILS ("EdgeTV",
121 "Filter/Effect/Video",
122 "Apply edge detect on video",
123 "Wim Taymans <wim.taymans@chello.be>");
125 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
126 GstVideofilterClass *videofilter_class = GST_VIDEOFILTER_CLASS (g_class);
129 gst_element_class_set_details (element_class, &gst_edgetv_details);
131 for (i = 0; i < G_N_ELEMENTS (gst_edgetv_formats); i++) {
132 gst_videofilter_class_add_format (videofilter_class,
133 gst_edgetv_formats + i);
136 gst_videofilter_class_add_pad_templates (GST_VIDEOFILTER_CLASS (g_class));
140 gst_edgetv_class_init (gpointer g_class, gpointer class_data)
142 GObjectClass *gobject_class;
143 GstVideofilterClass *videofilter_class;
145 gobject_class = G_OBJECT_CLASS (g_class);
146 videofilter_class = GST_VIDEOFILTER_CLASS (g_class);
148 gobject_class->set_property = gst_edgetv_set_property;
149 gobject_class->get_property = gst_edgetv_get_property;
151 videofilter_class->setup = gst_edgetv_setup;
155 gst_edgetv_init (GTypeInstance * instance, gpointer g_class)
157 GstEdgeTV *edgetv = GST_EDGETV (instance);
163 gst_edgetv_setup (GstVideofilter * videofilter)
166 int width = gst_videofilter_get_input_width (videofilter);
167 int height = gst_videofilter_get_input_height (videofilter);
169 g_return_if_fail (GST_IS_EDGETV (videofilter));
170 edgetv = GST_EDGETV (videofilter);
172 edgetv->width = width;
173 edgetv->height = height;
174 edgetv->map_width = width / 4;
175 edgetv->map_height = height / 4;
176 edgetv->video_width_margin = width % 4;
178 g_free (edgetv->map);
180 (guint32 *) g_malloc (edgetv->map_width * edgetv->map_height *
181 sizeof (guint32) * 2);
182 memset (edgetv->map, 0,
183 edgetv->map_width * edgetv->map_height * sizeof (guint32) * 2);
187 gst_edgetv_rgb32 (GstVideofilter * videofilter, void *d, void *s)
194 guint32 v0, v1, v2, v3;
196 filter = GST_EDGETV (videofilter);
199 dest = (guint32 *) d;
201 src += filter->width * 4 + 4;
202 dest += filter->width * 4 + 4;
204 for (y = 1; y < filter->map_height - 1; y++) {
205 for (x = 1; x < filter->map_width - 1; x++) {
210 /* difference between the current pixel and right neighbor. */
211 r = ((p & 0xff0000) - (q & 0xff0000)) >> 16;
212 g = ((p & 0xff00) - (q & 0xff00)) >> 8;
213 b = (p & 0xff) - (q & 0xff);
217 r = r >> 5; /* To lack the lower bit for saturated addition, */
218 g = g >> 5; /* devide the value with 32, instead of 16. It is */
219 b = b >> 4; /* same as `v2 &= 0xfefeff' */
226 v2 = (r << 17) | (g << 9) | b;
228 /* difference between the current pixel and upper neighbor. */
229 q = *(src - filter->width * 4);
230 r = ((p & 0xff0000) - (q & 0xff0000)) >> 16;
231 g = ((p & 0xff00) - (q & 0xff00)) >> 8;
232 b = (p & 0xff) - (q & 0xff);
245 v3 = (r << 17) | (g << 9) | b;
247 v0 = filter->map[(y - 1) * filter->map_width * 2 + x * 2];
248 v1 = filter->map[y * filter->map_width * 2 + (x - 1) * 2 + 1];
249 filter->map[y * filter->map_width * 2 + x * 2] = v2;
250 filter->map[y * filter->map_width * 2 + x * 2 + 1] = v3;
253 dest[0] = r | (g - (g >> 8));
256 dest[1] = r | (g - (g >> 8));
261 dest[filter->width] = r | (g - (g >> 8));
264 dest[filter->width + 1] = r | (g - (g >> 8));
265 dest[filter->width + 2] = v3;
266 dest[filter->width + 3] = v3;
267 dest[filter->width * 2] = v2;
268 dest[filter->width * 2 + 1] = v2;
269 dest[filter->width * 3] = v2;
270 dest[filter->width * 3 + 1] = v2;
275 src += filter->width * 3 + 8 + filter->video_width_margin;
276 dest += filter->width * 3 + 8 + filter->video_width_margin;
281 gst_edgetv_set_property (GObject * object, guint prop_id, const GValue * value,
286 /* it's not null if we got it, but it might not be ours */
287 g_return_if_fail (GST_IS_EDGETV (object));
289 filter = GST_EDGETV (object);
298 gst_edgetv_get_property (GObject * object, guint prop_id, GValue * value,
303 /* it's not null if we got it, but it might not be ours */
304 g_return_if_fail (GST_IS_EDGETV (object));
306 filter = GST_EDGETV (object);
310 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);