9608d2b48fdc57573a15f15595114c472519ebaf
[melted] / 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 "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 int uneven_w = ( *width % 2 ) * 2;
66 for ( i = 0; i < *height; i ++ )
67 {
68 p = ( uint8_t * )*image + i * *width * 2;
69 q = p + *width * 2;
70 a = alpha + i * *width;
71 b = a + *width - 1;
72 if ( !reverse )
73 {
74 while ( p < q )
75 {
76 *p ++ = *( q - 2 );
77 *p ++ = *( q - 3 - uneven_w );
78 *p ++ = *( q - 4 );
79 *p ++ = *( q - 1 - uneven_w );
80 q -= 4;
81 *a ++ = *b --;
82 *a ++ = *b --;
83 }
84 }
85 else
86 {
87 while ( p < q )
88 {
89 *( q - 2 ) = *p ++;
90 *( q - 3 - uneven_w ) = *p ++;
91 *( q - 4 ) = *p ++;
92 *( q - 1 - uneven_w ) = *p ++;
93 q -= 4;
94 *b -- = *a ++;
95 *b -- = *a ++;
96 }
97 }
98 }
99 }
100 else if ( !strcmp( mirror, "vertical" ) )
101 {
102 uint16_t *end = ( uint16_t *)*image + *width * *height;
103 uint16_t *p = NULL;
104 uint16_t *q = NULL;
105 uint8_t *a = NULL;
106 uint8_t *b = NULL;
107 int i;
108 int j;
109 for ( i = 0; i < hh; i ++ )
110 {
111 p = ( uint16_t * )*image + i * *width;
112 q = end - ( i + 1 ) * *width;
113 j = *width;
114 a = alpha + i * *width;
115 b = alpha + ( *height - i - 1 ) * *width;
116 if ( !reverse )
117 {
118 while ( j -- )
119 {
120 *p ++ = *q ++;
121 *a ++ = *b ++;
122 }
123 }
124 else
125 {
126 while ( j -- )
127 {
128 *q ++ = *p ++;
129 *b ++ = *a ++;
130 }
131 }
132 }
133 }
134 else if ( !strcmp( mirror, "diagonal" ) )
135 {
136 uint8_t *end = ( uint8_t *)*image + *width * *height * 2;
137 uint8_t *p = NULL;
138 uint8_t *q = NULL;
139 uint8_t *a = NULL;
140 uint8_t *b = NULL;
141 int i;
142 int j;
143 int uneven_w = ( *width % 2 ) * 2;
144 for ( i = 0; i < *height; i ++ )
145 {
146 p = ( uint8_t * )*image + i * *width * 2;
147 q = end - i * *width * 2;
148 j = ( ( *width * ( *height - i ) ) / *height ) / 2;
149 a = alpha + i * *width;
150 b = alpha + ( *height - i - 1 ) * *width;
151 if ( !reverse )
152 {
153 while ( j -- )
154 {
155 *p ++ = *( q - 2 );
156 *p ++ = *( q - 3 - uneven_w );
157 *p ++ = *( q - 4 );
158 *p ++ = *( q - 1 - uneven_w );
159 q -= 4;
160 *a ++ = *b --;
161 *a ++ = *b --;
162 }
163 }
164 else
165 {
166 while ( j -- )
167 {
168 *( q - 2 ) = *p ++;
169 *( q - 3 - uneven_w ) = *p ++;
170 *( q - 4 ) = *p ++;
171 *( q - 1 - uneven_w ) = *p ++;
172 q -= 4;
173 *b -- = *a ++;
174 *b -- = *a ++;
175 }
176 }
177 }
178 }
179 else if ( !strcmp( mirror, "xdiagonal" ) )
180 {
181 uint8_t *end = ( uint8_t *)*image + *width * *height * 2;
182 uint8_t *p = NULL;
183 uint8_t *q = NULL;
184 int i;
185 int j;
186 uint8_t *a = NULL;
187 uint8_t *b = NULL;
188 int uneven_w = ( *width % 2 ) * 2;
189 for ( i = 0; i < *height; i ++ )
190 {
191 p = ( uint8_t * )*image + ( i + 1 ) * *width * 2;
192 q = end - ( i + 1 ) * *width * 2;
193 j = ( ( *width * ( *height - i ) ) / *height ) / 2;
194 a = alpha + ( i + 1 ) * *width - 1;
195 b = alpha + ( *height - i - 1 ) * *width;
196 if ( !reverse )
197 {
198 while ( j -- )
199 {
200 *q ++ = *( p - 2 );
201 *q ++ = *( p - 3 - uneven_w );
202 *q ++ = *( p - 4 );
203 *q ++ = *( p - 1 - uneven_w );
204 p -= 4;
205 *b ++ = *a --;
206 *b ++ = *a --;
207 }
208 }
209 else
210 {
211 while ( j -- )
212 {
213 *( p - 2 ) = *q ++;
214 *( p - 3 - uneven_w ) = *q ++;
215 *( p - 4 ) = *q ++;
216 *( p - 1 - uneven_w ) = *q ++;
217 p -= 4;
218 *a -- = *b ++;
219 *a -- = *b ++;
220 }
221 }
222 }
223 }
224 else if ( !strcmp( mirror, "flip" ) )
225 {
226 uint8_t t[ 4 ];
227 uint8_t *p = NULL;
228 uint8_t *q = NULL;
229 int i;
230 uint8_t *a = NULL;
231 uint8_t *b = NULL;
232 uint8_t c;
233 int uneven_w = ( *width % 2 ) * 2;
234 for ( i = 0; i < *height; i ++ )
235 {
236 p = ( uint8_t * )*image + i * *width * 2;
237 q = p + *width * 2;
238 a = alpha + i * *width;
239 b = a + *width - 1;
240 while ( p < q )
241 {
242 t[ 0 ] = p[ 0 ];
243 t[ 1 ] = p[ 1 + uneven_w ];
244 t[ 2 ] = p[ 2 ];
245 t[ 3 ] = p[ 3 + uneven_w ];
246 *p ++ = *( q - 2 );
247 *p ++ = *( q - 3 - uneven_w );
248 *p ++ = *( q - 4 );
249 *p ++ = *( q - 1 - uneven_w );
250 *( -- q ) = t[ 3 ];
251 *( -- q ) = t[ 0 ];
252 *( -- q ) = t[ 1 ];
253 *( -- q ) = t[ 2 ];
254 c = *a;
255 *a ++ = *b;
256 *b -- = c;
257 c = *a;
258 *a ++ = *b;
259 *b -- = c;
260 }
261 }
262 }
263 else if ( !strcmp( mirror, "flop" ) )
264 {
265 uint16_t *end = ( uint16_t *)*image + *width * *height;
266 uint16_t *p = NULL;
267 uint16_t *q = NULL;
268 uint16_t t;
269 uint8_t *a = NULL;
270 uint8_t *b = NULL;
271 uint8_t c;
272 int i;
273 int j;
274 for ( i = 0; i < hh; i ++ )
275 {
276 p = ( uint16_t * )*image + i * *width;
277 q = end - ( i + 1 ) * *width;
278 a = alpha + i * *width;
279 b = alpha + ( *height - i - 1 ) * *width;
280 j = *width;
281 while ( j -- )
282 {
283 t = *p;
284 *p ++ = *q;
285 *q ++ = t;
286 c = *a;
287 *a ++ = *b;
288 *b ++ = c;
289 }
290 }
291 }
292 }
293
294 // Return the error
295 return error;
296 }
297
298 /** Filter processing.
299 */
300
301 static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
302 {
303 // Push the service on to the stack
304 mlt_frame_push_service( frame, this );
305
306 // Push the filter method on to the stack
307 mlt_frame_push_service( frame, filter_get_image );
308
309 return frame;
310 }
311
312 /** Constructor for the filter.
313 */
314
315 mlt_filter filter_mirror_init( void *arg )
316 {
317 // Construct a new filter
318 mlt_filter this = mlt_filter_new( );
319
320 // If we have a filter, initialise it
321 if ( this != NULL )
322 {
323 // Get the properties
324 mlt_properties properties = MLT_FILTER_PROPERTIES( this );
325
326 // Set the default mirror type
327 mlt_properties_set_or_default( properties, "mirror", arg, "horizontal" );
328
329 // Assign the process method
330 this->process = filter_process;
331 }
332
333 // Return the filter
334 return this;
335 }
336