]> git.sesse.net Git - mlt/blob - src/modules/core/filter_mirror.c
Merge ../mlt++
[mlt] / src / modules / core / filter_mirror.c
1 /*
2  * filter_mirror.c -- mirror filter
3  * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
4  * Author: Charles Yates <charles.yates@pandora.be>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library 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 GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include <framework/mlt_filter.h>
22 #include <framework/mlt_frame.h>
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27
28 /** Do it :-).
29 */
30
31 static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
32 {
33         // Pop the mirror filter from the stack
34         mlt_filter this = mlt_frame_pop_service( frame );
35
36         // Get the mirror type
37         mlt_properties properties = MLT_FILTER_PROPERTIES( this );
38
39         // Get the properties
40         char *mirror = mlt_properties_get( properties, "mirror" );
41
42         // Determine if reverse is required
43         int reverse = mlt_properties_get_int( properties, "reverse" );
44
45         // Get the image
46         int error = mlt_frame_get_image( frame, image, format, width, height, 1 );
47
48         // Get the alpha
49         uint8_t *alpha = mlt_frame_get_alpha_mask( frame );
50
51         // If we have an image of the right colour space
52         if ( error == 0 && *format == mlt_image_yuv422 )
53         {
54                 // We'll KISS here
55                 int hh = *height / 2;
56
57                 if ( !strcmp( mirror, "horizontal" ) )
58                 {
59                         uint8_t *p = NULL;
60                         uint8_t *q = NULL;
61                         uint8_t *a = NULL;
62                         uint8_t *b = NULL;
63                         int i;
64                         int uneven_w = ( *width % 2 ) * 2;
65                         for ( i = 0; i < *height; i ++ )
66                         {
67                                 p = ( uint8_t * )*image + i * *width * 2;
68                                 q = p + *width * 2;
69                                 a = alpha + i * *width;
70                                 b = a + *width - 1;
71                                 if ( !reverse )
72                                 {
73                                         while ( p < q )
74                                         {
75                                                 *p ++ = *( q - 2 );
76                                                 *p ++ = *( q - 3 - uneven_w );
77                                                 *p ++ = *( q - 4 );
78                                                 *p ++ = *( q - 1 - uneven_w );
79                                                 q -= 4;
80                                                 *a ++ = *b --;
81                                                 *a ++ = *b --;
82                                         }
83                                 }
84                                 else
85                                 {
86                                         while ( p < q )
87                                         {
88                                                 *( q - 2 ) = *p ++;
89                                                 *( q - 3 - uneven_w ) = *p ++;
90                                                 *( q - 4 ) = *p ++;
91                                                 *( q - 1 - uneven_w ) = *p ++;
92                                                 q -= 4;
93                                                 *b -- = *a ++;
94                                                 *b -- = *a ++;
95                                         }
96                                 }
97                         }
98                 }
99                 else if ( !strcmp( mirror, "vertical" ) )
100                 {
101                         uint16_t *end = ( uint16_t *)*image + *width * *height;
102                         uint16_t *p = NULL;
103                         uint16_t *q = NULL;
104                         uint8_t *a = NULL;
105                         uint8_t *b = NULL;
106                         int i;
107                         int j;
108                         for ( i = 0; i < hh; i ++ )
109                         {
110                                 p = ( uint16_t * )*image + i * *width;
111                                 q = end - ( i + 1 ) * *width;
112                                 j = *width;
113                                 a = alpha + i * *width;
114                                 b = alpha + ( *height - i - 1 ) * *width;
115                                 if ( !reverse )
116                                 {
117                                         while ( j -- )
118                                         {
119                                                 *p ++ = *q ++;
120                                                 *a ++ = *b ++;
121                                         }
122                                 }
123                                 else
124                                 {
125                                         while ( j -- )
126                                         {
127                                                 *q ++ = *p ++;
128                                                 *b ++ = *a ++;
129                                         }
130                                 }
131                         }
132                 }
133                 else if ( !strcmp( mirror, "diagonal" ) )
134                 {
135                         uint8_t *end = ( uint8_t *)*image + *width * *height * 2;
136                         uint8_t *p = NULL;
137                         uint8_t *q = NULL;
138                         uint8_t *a = NULL;
139                         uint8_t *b = NULL;
140                         int i;
141                         int j;
142                         int uneven_w = ( *width % 2 ) * 2;
143                         for ( i = 0; i < *height; i ++ )
144                         {
145                                 p = ( uint8_t * )*image + i * *width * 2;
146                                 q = end - i * *width * 2;
147                                 j = ( ( *width * ( *height - i ) ) / *height ) / 2;
148                                 a = alpha + i * *width;
149                                 b = alpha + ( *height - i - 1 ) * *width;
150                                 if ( !reverse )
151                                 {
152                                         while ( j -- )
153                                         {
154                                                 *p ++ = *( q - 2 );
155                                                 *p ++ = *( q - 3 - uneven_w );
156                                                 *p ++ = *( q - 4 );
157                                                 *p ++ = *( q - 1 - uneven_w );
158                                                 q -= 4;
159                                                 *a ++ = *b --;
160                                                 *a ++ = *b --;
161                                         }
162                                 }
163                                 else
164                                 {
165                                         while ( j -- )
166                                         {
167                                                 *( q - 2 ) = *p ++;
168                                                 *( q - 3 - uneven_w ) = *p ++;
169                                                 *( q - 4 ) = *p ++;
170                                                 *( q - 1 - uneven_w ) = *p ++;
171                                                 q -= 4;
172                                                 *b -- = *a ++;
173                                                 *b -- = *a ++;
174                                         }
175                                 }
176                         }
177                 }
178                 else if ( !strcmp( mirror, "xdiagonal" ) )
179                 {
180                         uint8_t *end = ( uint8_t *)*image + *width * *height * 2;
181                         uint8_t *p = NULL;
182                         uint8_t *q = NULL;
183                         int i;
184                         int j;
185                         uint8_t *a = NULL;
186                         uint8_t *b = NULL;
187                         int uneven_w = ( *width % 2 ) * 2;
188                         for ( i = 0; i < *height; i ++ )
189                         {
190                                 p = ( uint8_t * )*image + ( i + 1 ) * *width * 2;
191                                 q = end - ( i + 1 ) * *width * 2;
192                                 j = ( ( *width * ( *height - i ) ) / *height ) / 2;
193                                 a = alpha + ( i + 1 ) * *width - 1;
194                                 b = alpha + ( *height - i - 1 ) * *width;
195                                 if ( !reverse )
196                                 {
197                                         while ( j -- )
198                                         {
199                                                 *q ++ = *( p - 2 );
200                                                 *q ++ = *( p - 3 - uneven_w );
201                                                 *q ++ = *( p - 4 );
202                                                 *q ++ = *( p - 1 - uneven_w );
203                                                 p -= 4;
204                                                 *b ++ = *a --;
205                                                 *b ++ = *a --;
206                                         }
207                                 }
208                                 else
209                                 {
210                                         while ( j -- )
211                                         {
212                                                 *( p - 2 ) = *q ++;
213                                                 *( p - 3 - uneven_w ) = *q ++;
214                                                 *( p - 4 ) = *q ++;
215                                                 *( p - 1 - uneven_w ) = *q ++;
216                                                 p -= 4;
217                                                 *a -- = *b ++;
218                                                 *a -- = *b ++;
219                                         }
220                                 }
221                         }
222                 }
223                 else if ( !strcmp( mirror, "flip" ) )
224                 {
225                         uint8_t t[ 4 ];
226                         uint8_t *p = NULL;
227                         uint8_t *q = NULL;
228                         int i;
229                         uint8_t *a = NULL;
230                         uint8_t *b = NULL;
231                         uint8_t c;
232                         int uneven_w = ( *width % 2 ) * 2;
233                         for ( i = 0; i < *height; i ++ )
234                         {
235                                 p = ( uint8_t * )*image + i * *width * 2;
236                                 q = p + *width * 2;
237                                 a = alpha + i * *width;
238                                 b = a + *width - 1;
239                                 while ( p < q )
240                                 {
241                                         t[ 0 ] = p[ 0 ];
242                                         t[ 1 ] = p[ 1 + uneven_w ];
243                                         t[ 2 ] = p[ 2 ];
244                                         t[ 3 ] = p[ 3 + uneven_w ];
245                                         *p ++ = *( q - 2 );
246                                         *p ++ = *( q - 3 - uneven_w );
247                                         *p ++ = *( q - 4 );
248                                         *p ++ = *( q - 1 - uneven_w );
249                                         *( -- q ) = t[ 3 ];
250                                         *( -- q ) = t[ 0 ];
251                                         *( -- q ) = t[ 1 ];
252                                         *( -- q ) = t[ 2 ];
253                                         c = *a;
254                                         *a ++ = *b;
255                                         *b -- = c;
256                                         c = *a;
257                                         *a ++ = *b;
258                                         *b -- = c;
259                                 }
260                         }
261                 }
262                 else if ( !strcmp( mirror, "flop" ) )
263                 {
264                         uint16_t *end = ( uint16_t *)*image + *width * *height;
265                         uint16_t *p = NULL;
266                         uint16_t *q = NULL;
267                         uint16_t t;
268                         uint8_t *a = NULL;
269                         uint8_t *b = NULL;
270                         uint8_t c;
271                         int i;
272                         int j;
273                         for ( i = 0; i < hh; i ++ )
274                         {
275                                 p = ( uint16_t * )*image + i * *width;
276                                 q = end - ( i + 1 ) * *width;
277                                 a = alpha + i * *width;
278                                 b = alpha + ( *height - i - 1 ) * *width;
279                                 j = *width;
280                                 while ( j -- )
281                                 {
282                                         t = *p;
283                                         *p ++ = *q;
284                                         *q ++ = t;
285                                         c = *a;
286                                         *a ++ = *b;
287                                         *b ++ = c;
288                                 }
289                         }
290                 }
291         }
292
293         // Return the error
294         return error;
295 }
296
297 /** Filter processing.
298 */
299
300 static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
301 {
302         // Push the service on to the stack
303         mlt_frame_push_service( frame, this );
304
305         // Push the filter method on to the stack
306         mlt_frame_push_service( frame, filter_get_image );
307
308         return frame;
309 }
310
311 /** Constructor for the filter.
312 */
313
314 mlt_filter filter_mirror_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
315 {
316         // Construct a new filter
317         mlt_filter this = mlt_filter_new( );
318
319         // If we have a filter, initialise it
320         if ( this != NULL )
321         {
322                 // Get the properties
323                 mlt_properties properties = MLT_FILTER_PROPERTIES( this );
324
325                 // Set the default mirror type
326                 mlt_properties_set_or_default( properties, "mirror", arg, "horizontal" );
327
328                 // Assign the process method
329                 this->process = filter_process;
330         }
331
332         // Return the filter
333         return this;
334 }
335