e3c50d2353e0d2c5fa9dfd53f9defe11f78a1869
[platform/upstream/gstreamer.git] / gst / effectv / gstshagadelic.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  *
4  * EffecTV:
5  * Copyright (C) 2001 FUKUCHI Kentarou
6  *
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.
13  *
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.
18  *
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.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28 #include <math.h>
29 #include <string.h>
30 #include <gst/gst.h>
31 #include <gstvideofilter.h>
32
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))
43
44 typedef struct _GstShagadelicTV GstShagadelicTV;
45 typedef struct _GstShagadelicTVClass GstShagadelicTVClass;
46
47 struct _GstShagadelicTV
48 {
49   GstVideofilter videofilter;
50
51   gint width, height;
52   gint stat;
53   gchar *ripple;
54   gchar *spiral;
55   guchar phase;
56   gint rx, ry;
57   gint bx, by;
58   gint rvx, rvy;
59   gint bvx, bvy;
60 };
61
62 struct _GstShagadelicTVClass
63 {
64   GstVideofilterClass parent_class;
65 };
66
67 /* Filter signals and args */
68 enum
69 {
70   /* FILL ME */
71   LAST_SIGNAL
72 };
73
74 enum
75 {
76   ARG_0
77 };
78
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);
82
83 static void gst_shagadelic_initialize (GstShagadelicTV * filter);
84
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,
91     void *s);
92
93 /*static guint gst_shagadelictv_signals[LAST_SIGNAL] = { 0 }; */
94
95 GType
96 gst_shagadelictv_get_type (void)
97 {
98   static GType shagadelictv_type = 0;
99
100   if (!shagadelictv_type) {
101     static const GTypeInfo shagadelictv_info = {
102       sizeof (GstShagadelicTVClass),
103       gst_shagadelictv_base_init,
104       NULL,
105       (GClassInitFunc) gst_shagadelictv_class_init,
106       NULL,
107       NULL,
108       sizeof (GstShagadelicTV),
109       0,
110       (GInstanceInitFunc) gst_shagadelictv_init,
111     };
112
113     shagadelictv_type =
114         g_type_register_static (GST_TYPE_VIDEOFILTER, "GstShagadelicTV",
115         &shagadelictv_info, 0);
116   }
117   return shagadelictv_type;
118 }
119
120 static GstVideofilterFormat gst_shagadelictv_formats[] = {
121   {"RGB ", 32, gst_shagadelictv_rgb32, 24, G_BIG_ENDIAN, 0x0000ff00, 0x00ff0000,
122       0xff000000}
123 };
124
125 static void
126 gst_shagadelictv_base_init (gpointer g_class)
127 {
128   /* elementfactory information */
129   static GstElementDetails gst_shagadelictv_details =
130       GST_ELEMENT_DETAILS ("ShagadelicTV",
131       "Filter/Effect/Video",
132       "Oh behave, ShagedelicTV makes images shagadelic!",
133       "Wim Taymans <wim.taymans@chello.be>");
134
135   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
136   GstVideofilterClass *videofilter_class = GST_VIDEOFILTER_CLASS (g_class);
137   int i;
138
139   gst_element_class_set_details (element_class, &gst_shagadelictv_details);
140
141   for (i = 0; i < G_N_ELEMENTS (gst_shagadelictv_formats); i++) {
142     gst_videofilter_class_add_format (videofilter_class,
143         gst_shagadelictv_formats + i);
144   }
145
146   gst_videofilter_class_add_pad_templates (GST_VIDEOFILTER_CLASS (g_class));
147 }
148
149 static void
150 gst_shagadelictv_class_init (gpointer g_class, gpointer class_data)
151 {
152   GObjectClass *gobject_class;
153   GstVideofilterClass *videofilter_class;
154
155   gobject_class = G_OBJECT_CLASS (g_class);
156   videofilter_class = GST_VIDEOFILTER_CLASS (g_class);
157
158   gobject_class->set_property = gst_shagadelictv_set_property;
159   gobject_class->get_property = gst_shagadelictv_get_property;
160
161   videofilter_class->setup = gst_shagadelictv_setup;
162 }
163
164 static void
165 gst_shagadelictv_init (GTypeInstance * instance, gpointer g_class)
166 {
167   GstShagadelicTV *filter = GST_SHAGADELICTV (instance);
168
169   filter->ripple = NULL;
170   filter->spiral = NULL;
171 }
172
173 static void
174 gst_shagadelictv_setup (GstVideofilter * videofilter)
175 {
176   GstShagadelicTV *filter;
177   int width = gst_videofilter_get_input_width (videofilter);
178   int height = gst_videofilter_get_input_height (videofilter);
179   int area;
180
181   g_return_if_fail (GST_IS_SHAGADELICTV (videofilter));
182   filter = GST_SHAGADELICTV (videofilter);
183
184   filter->width = width;
185   filter->height = height;
186
187   area = filter->width * filter->height;
188
189   g_free (filter->ripple);
190   g_free (filter->spiral);
191
192   filter->ripple = (gchar *) g_malloc (area * 4);
193   filter->spiral = (gchar *) g_malloc (area);
194
195   gst_shagadelic_initialize (filter);
196 }
197
198 static unsigned int
199 fastrand (void)
200 {
201   static unsigned int fastrand_val;
202
203   return (fastrand_val = fastrand_val * 1103515245 + 12345);
204 }
205
206 static void
207 gst_shagadelic_initialize (GstShagadelicTV * filter)
208 {
209   int i, x, y;
210
211 #ifdef PS2
212   float xx, yy;
213 #else
214   double xx, yy;
215 #endif
216
217   i = 0;
218   for (y = 0; y < filter->height * 2; y++) {
219     yy = y - filter->height;
220     yy *= yy;
221
222     for (x = 0; x < filter->width * 2; x++) {
223       xx = x - filter->width;
224 #ifdef PS2
225       filter->ripple[i++] = ((unsigned int) (sqrtf (xx * xx + yy) * 8)) & 255;
226 #else
227       filter->ripple[i++] = ((unsigned int) (sqrt (xx * xx + yy) * 8)) & 255;
228 #endif
229     }
230   }
231
232   i = 0;
233   for (y = 0; y < filter->height; y++) {
234     yy = y - filter->height / 2;
235
236     for (x = 0; x < filter->width; x++) {
237       xx = x - filter->width / 2;
238 #ifdef PS2
239       filter->spiral[i++] = ((unsigned int)
240           ((atan2f (xx,
241                       yy) / ((float) M_PI) * 256 * 9) + (sqrtf (xx * xx +
242                       yy * yy) * 5))) & 255;
243 #else
244       filter->spiral[i++] = ((unsigned int)
245           ((atan2 (xx, yy) / M_PI * 256 * 9) + (sqrt (xx * xx +
246                       yy * yy) * 5))) & 255;
247 #endif
248 /* Here is another Swinger!
249  * ((atan2(xx, yy)/M_PI*256) + (sqrt(xx*xx+yy*yy)*10))&255;
250  */
251     }
252   }
253   filter->rx = fastrand () % filter->width;
254   filter->ry = fastrand () % filter->height;
255   filter->bx = fastrand () % filter->width;
256   filter->by = fastrand () % filter->height;
257   filter->rvx = -2;
258   filter->rvy = -2;
259   filter->bvx = 2;
260   filter->bvy = 2;
261   filter->phase = 0;
262 }
263
264 static void
265 gst_shagadelictv_rgb32 (GstVideofilter * videofilter, void *d, void *s)
266 {
267   GstShagadelicTV *filter;
268   guint32 *src, *dest;
269   gint x, y;
270   guint32 v;
271   guchar r, g, b;
272   gint width, height;
273
274   filter = GST_SHAGADELICTV (videofilter);
275
276   src = (guint32 *) s;
277   dest = (guint32 *) d;
278
279   width = filter->width;
280   height = filter->height;
281
282   for (y = 0; y < height; y++) {
283     for (x = 0; x < width; x++) {
284       v = *src++ | 0x1010100;
285       v = (v - 0x707060) & 0x1010100;
286       v -= v >> 8;
287 /* Try another Babe! 
288  * v = *src++;
289  * *dest++ = v & ((r<<16)|(g<<8)|b);
290  */
291       r = (gchar) (filter->ripple[(filter->ry + y) * width * 2 + filter->rx +
292               x] + filter->phase * 2) >> 7;
293       g = (gchar) (filter->spiral[y * width + x] + filter->phase * 3) >> 7;
294       b = (gchar) (filter->ripple[(filter->by + y) * width * 2 + filter->bx +
295               x] - filter->phase) >> 7;
296       *dest++ = v & ((r << 16) | (g << 8) | b);
297     }
298   }
299
300   filter->phase -= 8;
301   if ((filter->rx + filter->rvx) < 0 || (filter->rx + filter->rvx) >= width)
302     filter->rvx = -filter->rvx;
303   if ((filter->ry + filter->rvy) < 0 || (filter->ry + filter->rvy) >= height)
304     filter->rvy = -filter->rvy;
305   if ((filter->bx + filter->bvx) < 0 || (filter->bx + filter->bvx) >= width)
306     filter->bvx = -filter->bvx;
307   if ((filter->by + filter->bvy) < 0 || (filter->by + filter->bvy) >= height)
308     filter->bvy = -filter->bvy;
309   filter->rx += filter->rvx;
310   filter->ry += filter->rvy;
311   filter->bx += filter->bvx;
312   filter->by += filter->bvy;
313 }
314
315 static void
316 gst_shagadelictv_set_property (GObject * object, guint prop_id,
317     const GValue * value, GParamSpec * pspec)
318 {
319   GstShagadelicTV *filter;
320
321   g_return_if_fail (GST_IS_SHAGADELICTV (object));
322
323   filter = GST_SHAGADELICTV (object);
324
325   switch (prop_id) {
326     default:
327       break;
328   }
329 }
330
331 static void
332 gst_shagadelictv_get_property (GObject * object, guint prop_id, GValue * value,
333     GParamSpec * pspec)
334 {
335   GstShagadelicTV *filter;
336
337   g_return_if_fail (GST_IS_SHAGADELICTV (object));
338
339   filter = GST_SHAGADELICTV (object);
340
341   switch (prop_id) {
342     default:
343       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
344       break;
345   }
346 }