]> git.sesse.net Git - mlt/blob - src/modules/core/filter_mirror.c
a9678914f33858b8c6717e120f91422abbe87562
[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 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  * along 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_mirror.h"
22
23 #include <framework/mlt_frame.h>
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28
29 /** Do it :-).
30 */
31
32 static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
33 {
34         // Pop the mirror filter from the stack
35         mlt_filter this = mlt_frame_pop_service( frame );
36
37         // Get the mirror type
38         mlt_properties properties = MLT_FILTER_PROPERTIES( this );
39
40         // Get the properties
41         char *mirror = mlt_properties_get( properties, "mirror" );
42
43         // Determine if reverse is required
44         int reverse = mlt_properties_get_int( properties, "reverse" );
45
46         // Get the image
47         int error = mlt_frame_get_image( frame, image, format, width, height, 1 );
48
49         // Get the alpha
50         uint8_t *alpha = mlt_frame_get_alpha_mask( frame );
51
52         // If we have an image of the right colour space
53         if ( error == 0 && *format == mlt_image_yuv422 )
54         {
55                 // We'll KISS here
56                 int hh = *height / 2;
57
58                 if ( !strcmp( mirror, "horizontal" ) )
59                 {
60                         uint8_t *p = NULL;
61                         uint8_t *q = NULL;
62                         uint8_t *a = NULL;
63                         uint8_t *b = NULL;
64                         int i;
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 );
77                                                 *p ++ = *( q - 4 );
78                                                 *p ++ = *( q - 1 );
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 ) = *p ++;
90                                                 *( q - 4 ) = *p ++;
91                                                 *( q - 1 ) = *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                         for ( i = 0; i < *height; i ++ )
143                         {
144                                 p = ( uint8_t * )*image + i * *width * 2;
145                                 q = end - i * *width * 2;
146                                 j = ( ( *width * ( *height - i ) ) / *height ) / 2;
147                                 a = alpha + i * *width;
148                                 b = alpha + ( *height - i - 1 ) * *width;
149                                 if ( !reverse )
150                                 {
151                                         while ( j -- )
152                                         {
153                                                 *p ++ = *( q - 2 );
154                                                 *p ++ = *( q - 3 );
155                                                 *p ++ = *( q - 4 );
156                                                 *p ++ = *( q - 1 );
157                                                 q -= 4;
158                                                 *a ++ = *b --;
159                                                 *a ++ = *b --;
160                                         }
161                                 }
162                                 else
163                                 {
164                                         while ( j -- )
165                                         {
166                                                 *( q - 2 ) = *p ++;
167                                                 *( q - 3 ) = *p ++;
168                                                 *( q - 4 ) = *p ++;
169                                                 *( q - 1 ) = *p ++;
170                                                 q -= 4;
171                                                 *b -- = *a ++;
172                                                 *b -- = *a ++;
173                                         }
174                                 }
175                         }
176                 }
177                 else if ( !strcmp( mirror, "xdiagonal" ) )
178                 {
179                         uint8_t *end = ( uint8_t *)*image + *width * *height * 2;
180                         uint8_t *p = NULL;
181                         uint8_t *q = NULL;
182                         int i;
183                         int j;
184                         uint8_t *a = NULL;
185                         uint8_t *b = NULL;
186                         for ( i = 0; i < *height; i ++ )
187                         {
188                                 p = ( uint8_t * )*image + ( i + 1 ) * *width * 2;
189                                 q = end - ( i + 1 ) * *width * 2;
190                                 j = ( ( *width * ( *height - i ) ) / *height ) / 2;
191                                 a = alpha + ( i + 1 ) * *width - 1;
192                                 b = alpha + ( *height - i - 1 ) * *width;
193                                 if ( !reverse )
194                                 {
195                                         while ( j -- )
196                                         {
197                                                 *q ++ = *( p - 2 );
198                                                 *q ++ = *( p - 3 );
199                                                 *q ++ = *( p - 4 );
200                                                 *q ++ = *( p - 1 );
201                                                 p -= 4;
202                                                 *b ++ = *a --;
203                                                 *b ++ = *a --;
204                                         }
205                                 }
206                                 else
207                                 {
208                                         while ( j -- )
209                                         {
210                                                 *( p - 2 ) = *q ++;
211                                                 *( p - 3 ) = *q ++;
212                                                 *( p - 4 ) = *q ++;
213                                                 *( p - 1 ) = *q ++;
214                                                 p -= 4;
215                                                 *a -- = *b ++;
216                                                 *a -- = *b ++;
217                                         }
218                                 }
219                         }
220                 }
221                 else if ( !strcmp( mirror, "flip" ) )
222                 {
223                         uint8_t t[ 4 ];
224                         uint8_t *p = NULL;
225                         uint8_t *q = NULL;
226                         int i;
227                         uint8_t *a = NULL;
228                         uint8_t *b = NULL;
229                         uint8_t c;
230                         for ( i = 0; i < *height; i ++ )
231                         {
232                                 p = ( uint8_t * )*image + i * *width * 2;
233                                 q = p + *width * 2;
234                                 a = alpha + i * *width;
235                                 b = a + *width - 1;
236                                 while ( p < q )
237                                 {
238                                         t[ 0 ] = p[ 0 ];
239                                         t[ 1 ] = p[ 1 ];
240                                         t[ 2 ] = p[ 2 ];
241                                         t[ 3 ] = p[ 3 ];
242                                         *p ++ = *( q - 2 );
243                                         *p ++ = *( q - 3 );
244                                         *p ++ = *( q - 4 );
245                                         *p ++ = *( q - 1 );
246                                         *( -- q ) = t[ 3 ];
247                                         *( -- q ) = t[ 0 ];
248                                         *( -- q ) = t[ 1 ];
249                                         *( -- q ) = t[ 2 ];
250                                         c = *a;
251                                         *a ++ = *b;
252                                         *b -- = c;
253                                         c = *a;
254                                         *a ++ = *b;
255                                         *b -- = c;
256                                 }
257                         }
258                 }
259                 else if ( !strcmp( mirror, "flop" ) )
260                 {
261                         uint16_t *end = ( uint16_t *)*image + *width * *height;
262                         uint16_t *p = NULL;
263                         uint16_t *q = NULL;
264                         uint16_t t;
265                         uint8_t *a = NULL;
266                         uint8_t *b = NULL;
267                         uint8_t c;
268                         int i;
269                         int j;
270                         for ( i = 0; i < hh; i ++ )
271                         {
272                                 p = ( uint16_t * )*image + i * *width;
273                                 q = end - ( i + 1 ) * *width;
274                                 a = alpha + i * *width;
275                                 b = alpha + ( *height - i - 1 ) * *width;
276                                 j = *width;
277                                 while ( j -- )
278                                 {
279                                         t = *p;
280                                         *p ++ = *q;
281                                         *q ++ = t;
282                                         c = *a;
283                                         *a ++ = *b;
284                                         *b ++ = c;
285                                 }
286                         }
287                 }
288         }
289
290         // Return the error
291         return error;
292 }
293
294 /** Filter processing.
295 */
296
297 static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
298 {
299         // Push the service on to the stack
300         mlt_frame_push_service( frame, this );
301
302         // Push the filter method on to the stack
303         mlt_frame_push_service( frame, filter_get_image );
304
305         return frame;
306 }
307
308 /** Constructor for the filter.
309 */
310
311 mlt_filter filter_mirror_init( void *arg )
312 {
313         // Construct a new filter
314         mlt_filter this = mlt_filter_new( );
315
316         // If we have a filter, initialise it
317         if ( this != NULL )
318         {
319                 // Get the properties
320                 mlt_properties properties = MLT_FILTER_PROPERTIES( this );
321
322                 // Set the default mirror type
323                 mlt_properties_set_or_default( properties, "mirror", arg, "horizontal" );
324
325                 // Assign the process method
326                 this->process = filter_process;
327         }
328
329         // Return the filter
330         return this;
331 }
332