2 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
5 * Copyright (C) 2001 FUKUCHI Kentarou
7 * Inspired by Adrian Likin's script for the GIMP.
8 * EffecTV is free software. This library is free software;
9 * you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
19 * You should have received a copy of the GNU Library General Public
20 * License along with this library; if not, write to the
21 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 * Boston, MA 02111-1307, USA.
31 #include <gstvideofilter.h>
33 #define GST_TYPE_SHAGADELICTV \
34 (gst_shagadelictv_get_type())
35 #define GST_SHAGADELICTV(obj) \
36 (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SHAGADELICTV,GstShagadelicTV))
37 #define GST_SHAGADELICTV_CLASS(klass) \
38 (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SHAGADELICTV,GstShagadelicTVClass))
39 #define GST_IS_SHAGADELICTV(obj) \
40 (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SHAGADELICTV))
41 #define GST_IS_SHAGADELICTV_CLASS(obj) \
42 (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SHAGADELICTV))
44 typedef struct _GstShagadelicTV GstShagadelicTV;
45 typedef struct _GstShagadelicTVClass GstShagadelicTVClass;
47 struct _GstShagadelicTV
49 GstVideofilter videofilter;
62 struct _GstShagadelicTVClass
64 GstVideofilterClass parent_class;
67 /* Filter signals and args */
79 static void gst_shagadelictv_base_init (gpointer g_class);
80 static void gst_shagadelictv_class_init (gpointer g_class, gpointer class_data);
81 static void gst_shagadelictv_init (GTypeInstance *instance, gpointer g_class);
83 static void gst_shagadelic_initialize (GstShagadelicTV *filter);
85 static void gst_shagadelictv_set_property (GObject * object, guint prop_id,
86 const GValue * value, GParamSpec * pspec);
87 static void gst_shagadelictv_get_property (GObject * object, guint prop_id,
88 GValue * value, GParamSpec * pspec);
89 static void gst_shagadelictv_setup (GstVideofilter *videofilter);
90 static void gst_shagadelictv_rgb32 (GstVideofilter *videofilter, void *d, void *s);
92 /*static guint gst_shagadelictv_signals[LAST_SIGNAL] = { 0 }; */
94 GType gst_shagadelictv_get_type (void)
96 static GType shagadelictv_type = 0;
98 if (!shagadelictv_type) {
99 static const GTypeInfo shagadelictv_info = {
100 sizeof (GstShagadelicTVClass),
101 gst_shagadelictv_base_init,
103 (GClassInitFunc) gst_shagadelictv_class_init,
106 sizeof (GstShagadelicTV),
108 (GInstanceInitFunc) gst_shagadelictv_init,
111 shagadelictv_type = g_type_register_static (GST_TYPE_VIDEOFILTER, "GstShagadelicTV", &shagadelictv_info, 0);
113 return shagadelictv_type;
116 static GstVideofilterFormat gst_shagadelictv_formats[] = {
117 { "RGB ", 32, gst_shagadelictv_rgb32, 24, G_BIG_ENDIAN, 0x0000ff00, 0x00ff0000, 0xff000000 }
121 gst_shagadelictv_base_init (gpointer g_class)
123 /* elementfactory information */
124 static GstElementDetails gst_shagadelictv_details = GST_ELEMENT_DETAILS (
126 "Filter/Effect/Video",
127 "Oh behave, ShagedelicTV makes images shagadelic!",
128 "Wim Taymans <wim.taymans@chello.be>"
131 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
132 GstVideofilterClass *videofilter_class = GST_VIDEOFILTER_CLASS (g_class);
135 gst_element_class_set_details (element_class, &gst_shagadelictv_details);
137 for(i=0;i<G_N_ELEMENTS(gst_shagadelictv_formats);i++){
138 gst_videofilter_class_add_format(videofilter_class,
139 gst_shagadelictv_formats + i);
142 gst_videofilter_class_add_pad_templates (GST_VIDEOFILTER_CLASS (g_class));
146 gst_shagadelictv_class_init (gpointer g_class, gpointer class_data)
148 GObjectClass *gobject_class;
149 GstVideofilterClass *videofilter_class;
151 gobject_class = G_OBJECT_CLASS (g_class);
152 videofilter_class = GST_VIDEOFILTER_CLASS (g_class);
154 gobject_class->set_property = gst_shagadelictv_set_property;
155 gobject_class->get_property = gst_shagadelictv_get_property;
157 videofilter_class->setup = gst_shagadelictv_setup;
161 gst_shagadelictv_init (GTypeInstance *instance, gpointer g_class)
163 GstShagadelicTV *filter = GST_SHAGADELICTV (instance);
165 filter->ripple = NULL;
166 filter->spiral = NULL;
170 gst_shagadelictv_setup(GstVideofilter *videofilter)
172 GstShagadelicTV *filter;
173 int width = gst_videofilter_get_input_width(videofilter);
174 int height = gst_videofilter_get_input_height(videofilter);
177 g_return_if_fail (GST_IS_SHAGADELICTV (videofilter));
178 filter = GST_SHAGADELICTV (videofilter);
180 filter->width = width;
181 filter->height = height;
183 area = filter->width * filter->height;
185 g_free (filter->ripple);
186 g_free (filter->spiral);
188 filter->ripple = (gchar *) g_malloc (area * 4);
189 filter->spiral = (gchar *) g_malloc (area);
191 gst_shagadelic_initialize (filter);
197 static unsigned int fastrand_val;
199 return (fastrand_val = fastrand_val * 1103515245 + 12345);
203 gst_shagadelic_initialize (GstShagadelicTV *filter)
213 for(y = 0; y < filter->height * 2; y++) {
214 yy = y - filter->height;
217 for (x = 0; x < filter->width * 2; x++) {
218 xx = x - filter->width;
220 filter->ripple[i++] = ((unsigned int)(sqrtf(xx*xx+yy)*8))&255;
222 filter->ripple[i++] = ((unsigned int)(sqrt(xx*xx+yy)*8))&255;
228 for (y = 0; y < filter->height; y++) {
229 yy = y - filter->height/2;
231 for (x = 0; x < filter->width; x++) {
232 xx = x - filter->width/2;
234 filter->spiral[i++] = ((unsigned int)
235 ((atan2f(xx, yy)/((float)M_PI)*256*9) + (sqrtf(xx*xx+yy*yy)*5)))&255;
237 filter->spiral[i++] = ((unsigned int)
238 ((atan2(xx, yy)/M_PI*256*9) + (sqrt(xx*xx+yy*yy)*5)))&255;
240 /* Here is another Swinger!
241 * ((atan2(xx, yy)/M_PI*256) + (sqrt(xx*xx+yy*yy)*10))&255;
245 filter->rx = fastrand () % filter->width;
246 filter->ry = fastrand () % filter->height;
247 filter->bx = fastrand () % filter->width;
248 filter->by = fastrand () % filter->height;
257 gst_shagadelictv_rgb32 (GstVideofilter *videofilter, void *d, void *s)
259 GstShagadelicTV *filter;
266 filter = GST_SHAGADELICTV (videofilter);
269 dest = (guint32 *) d;
271 width = filter->width;
272 height = filter->height;
274 for (y = 0; y < height; y++) {
275 for (x = 0; x < width; x++) {
276 v = *src++ | 0x1010100;
277 v = (v - 0x707060) & 0x1010100;
281 * *dest++ = v & ((r<<16)|(g<<8)|b);
283 r = (gchar) (filter->ripple[(filter->ry + y) * width * 2 + filter->rx + x] + filter->phase * 2) >> 7;
284 g = (gchar) (filter->spiral[y * width + x] + filter->phase * 3) >> 7;
285 b = (gchar) (filter->ripple[(filter->by + y) * width * 2 + filter->bx + x] - filter->phase) >> 7;
286 *dest++ = v & ((r << 16) | (g << 8) | b);
291 if ((filter->rx + filter->rvx) < 0 || (filter->rx + filter->rvx) >= width) filter->rvx =- filter->rvx;
292 if ((filter->ry + filter->rvy) < 0 || (filter->ry + filter->rvy) >= height) filter->rvy =- filter->rvy;
293 if ((filter->bx + filter->bvx) < 0 || (filter->bx + filter->bvx) >= width) filter->bvx =- filter->bvx;
294 if ((filter->by + filter->bvy) < 0 || (filter->by + filter->bvy) >= height) filter->bvy =- filter->bvy;
295 filter->rx += filter->rvx;
296 filter->ry += filter->rvy;
297 filter->bx += filter->bvx;
298 filter->by += filter->bvy;
302 gst_shagadelictv_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec)
304 GstShagadelicTV *filter;
306 /* it's not null if we got it, but it might not be ours */
307 g_return_if_fail (GST_IS_SHAGADELICTV (object));
309 filter = GST_SHAGADELICTV (object);
318 gst_shagadelictv_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec)
320 GstShagadelicTV *filter;
322 /* it's not null if we got it, but it might not be ours */
323 g_return_if_fail (GST_IS_SHAGADELICTV (object));
325 filter = GST_SHAGADELICTV (object);
329 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);