0cb8664426fdf5f7d7ab999d0c61d3403ad44437
[melted] / src / modules / core / filter_wave.c
1 /*
2 * wave.c -- wave filter
3 * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
4 * Author: Leny Grisel <leny.grisel@laposte.net>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * aint32_t with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21 #include "filter_wave.h"
22
23 #include <framework/mlt_frame.h>
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <math.h>
28
29 // this is a utility function used by DoWave below
30 static uint8_t getPoint(uint8_t *src, int w, int h, int x, int y, int z)
31 {
32 if (x<0) x+=-((-x)%w)+w; else if (x>=w) x=x%w;
33 if (y<0) y+=-((-y)%h)+h; else if (y>=h) y=y%h;
34 return src[(x+y*w)*4+z];
35 }
36
37 // the main meat of the algorithm lies here
38 static void DoWave(uint8_t *src, int src_w, int src_h, uint8_t *dst, mlt_position position, int speed, int factor, int deformX, int deformY)
39 {
40 register int x, y;
41 int decalY, decalX, z;
42 float amplitude, phase, pulsation;
43 register int uneven = src_w % 2;
44 int w = (src_w - uneven ) / 2;
45 amplitude = factor;
46 pulsation = 0.5 / factor; // smaller means bigger period
47 phase = position * pulsation * speed / 10; // smaller means longer
48 for (y=0;y<src_h;y++) {
49 decalX = deformX ? sin(pulsation * y + phase) * amplitude : 0;
50 for (x=0;x<w;x++) {
51 decalY = deformY ? sin(pulsation * x * 2 + phase) * amplitude : 0;
52 for (z=0; z<4; z++)
53 *dst++ = getPoint(src, w, src_h, (x+decalX), (y+decalY), z);
54 }
55 if (uneven) {
56 decalY = sin(pulsation * x * 2 + phase) * amplitude;
57 for (z=0; z<2; z++)
58 *dst++ = getPoint(src, w, src_h, (x+decalX), (y+decalY), z);
59 }
60 }
61 }
62
63 static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
64 {
65 // Get the image
66 int error = mlt_frame_get_image( this, image, format, width, height, 1 );
67 mlt_position position = mlt_frame_get_position( this );
68
69 // Only process if we have no error and a valid colour space
70 if ( error == 0 && *format == mlt_image_yuv422 )
71 {
72 double factor = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "wave" );
73 int speed = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "speed" );
74 int deformX = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "deformX" );
75 int deformY = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "deformY" );
76 if (factor != 0) {
77 int image_size = *width * (*height + 1) * 2;
78 int8_t *dest = mlt_pool_alloc (image_size);
79 DoWave(*image, *width, (*height + 1), dest, position, speed, factor, deformX, deformY);
80 memcpy(*image, dest, image_size);
81 mlt_pool_release(dest);
82 }
83 }
84
85 return error;
86 }
87
88 /** Filter processing.
89 */
90
91 static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
92 {
93 // Get the starting wave level
94 double wave = mlt_properties_get_double( MLT_FILTER_PROPERTIES( this ), "start" );
95 int speed = mlt_properties_get_int( MLT_FILTER_PROPERTIES( this ), "speed" );
96 int deformX = mlt_properties_get_int( MLT_FILTER_PROPERTIES( this ), "deformX" );
97 int deformY = mlt_properties_get_int( MLT_FILTER_PROPERTIES( this ), "deformY" );
98
99 // If there is an end adjust gain to the range
100 if ( mlt_properties_get( MLT_FILTER_PROPERTIES( this ), "end" ) != NULL )
101 {
102 // Determine the time position of this frame in the transition duration
103 mlt_position in = mlt_filter_get_in( this );
104 mlt_position out = mlt_filter_get_out( this );
105 mlt_position time = mlt_frame_get_position( frame );
106 double position = ( double )( time - in ) / ( double )( out - in + 1 );
107 double end = fabs( mlt_properties_get_double( MLT_FILTER_PROPERTIES( this ), "end" ) );
108 wave += ( end - wave ) * position;
109 }
110
111 // Push the frame filter
112 mlt_properties_set_double( MLT_FRAME_PROPERTIES( frame ), "wave", wave );
113 mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "speed", speed );
114 mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "deformX", deformX );
115 mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "deformY", deformY );
116 mlt_frame_push_get_image( frame, filter_get_image );
117
118 return frame;
119 }
120
121 /** Constructor for the filter.
122 */
123
124 mlt_filter filter_wave_init( char *arg )
125 {
126 mlt_filter this = mlt_filter_new( );
127 if ( this != NULL )
128 {
129 this->process = filter_process;
130 mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "start", arg == NULL ? "10" : arg);
131 mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "speed", arg == NULL ? "5" : arg);
132 mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "deformX", arg == NULL ? "1" : arg);
133 mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "deformY", arg == NULL ? "1" : arg);
134 }
135 return this;
136 }
137
138
139