2 * transition_affine.c -- affine transformations
3 * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
4 * Author: Charles Yates <charles.yates@pandora.be>
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.
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.
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.
21 #include "transition_affine.h"
22 #include <framework/mlt.h>
36 static void affine_init( float this[3][3] )
49 // Multiply two this affine transform with that
50 static void affine_multiply( float this[3][3], float that
[3][3] )
56 for ( i
= 0; i
< 3; i
++ )
57 for ( j
= 0; j
< 3; j
++ )
58 output
[i
][j
] = this[i
][0] * that
[j
][0] + this[i
][1] * that
[j
][1] + this[i
][2] * that
[j
][2];
60 this[0][0] = output
[0][0];
61 this[0][1] = output
[0][1];
62 this[0][2] = output
[0][2];
63 this[1][0] = output
[1][0];
64 this[1][1] = output
[1][1];
65 this[1][2] = output
[1][2];
66 this[2][0] = output
[2][0];
67 this[2][1] = output
[2][1];
68 this[2][2] = output
[2][2];
71 // Rotate by a given angle
72 static void affine_rotate( float this[3][3], float angle
)
75 affine
[0][0] = cos( angle
* M_PI
/ 180 );
76 affine
[0][1] = 0 - sin( angle
* M_PI
/ 180 );
78 affine
[1][0] = sin( angle
* M_PI
/ 180 );
79 affine
[1][1] = cos( angle
* M_PI
/ 180 );
84 affine_multiply( this, affine
);
87 static void affine_scale( float this[3][3], float sx
, float sy
)
99 affine_multiply( this, affine
);
102 // Shear by a given value
103 static void affine_shear( float this[3][3], float shear
)
107 affine
[0][1] = shear
;
115 affine_multiply( this, affine
);
118 // Shear by a given value
119 static void affine_invert( float this[3][3] )
131 affine_multiply( this, affine
);
134 static void affine_offset( float this[3][3], int x
, int y
)
140 // Obtain the mapped x coordinate of the input
141 static inline float MapX( float this[3][3], int x
, int y
)
143 return this[0][0] * x
+ this[0][1] * y
+ this[0][2] + 0.5;
146 // Obtain the mapped y coordinate of the input
147 static inline float MapY( float this[3][3], int x
, int y
)
149 return this[1][0] * x
+ this[1][1] * y
+ this[1][2] + 0.5;
155 static int transition_get_image( mlt_frame a_frame
, uint8_t **image
, mlt_image_format
*format
, int *width
, int *height
, int writable
)
157 // Get the b frame from the stack
158 mlt_frame b_frame
= mlt_frame_pop_frame( a_frame
);
160 // Get the transition object
161 mlt_transition transition
= mlt_frame_pop_service( a_frame
);
163 // Get the properties of the transition
164 mlt_properties properties
= mlt_transition_properties( transition
);
166 // Get the properties of the a frame
167 //mlt_properties a_props = mlt_frame_properties( a_frame );
169 // Get the properties of the b frame
170 //mlt_properties b_props = mlt_frame_properties( b_frame );
172 // Image, format, width, height and image for the b frame
173 uint8_t *b_image
= NULL
;
174 mlt_image_format b_format
= mlt_image_yuv422
;
178 // Fetch the a frame image
179 mlt_frame_get_image( a_frame
, image
, format
, width
, height
, 1 );
181 // Fetch the b frame image
184 mlt_properties_set( mlt_frame_properties( b_frame
), "rescale.interp", "nearest" );
185 mlt_properties_set( mlt_frame_properties( b_frame
), "distort", "true" );
186 mlt_frame_get_image( b_frame
, &b_image
, &b_format
, &b_width
, &b_height
, 0 );
188 // Check that both images are of the correct format and process
189 if ( *format
== mlt_image_yuv422
&& b_format
== mlt_image_yuv422
)
194 // This is the matrix we're creating
195 affine_t
*affine
= mlt_properties_get_data( properties
, "affine", NULL
);
197 // Get values from the transition
198 char *geometry
= mlt_properties_get( properties
, "geometry" );
199 float rotate
= mlt_properties_get_double( properties
, "rotate" );
200 float shear
= mlt_properties_get_double( properties
, "shear" );
201 int invert
= mlt_properties_get_int( properties
, "invert" );
202 float sx
= mlt_properties_get_double( properties
, "sx" );
203 float sy
= mlt_properties_get_double( properties
, "sy" );
204 float ox
= mlt_properties_get_double( properties
, "ox" );
205 float oy
= mlt_properties_get_double( properties
, "oy" );
214 //uint8_t *luma = mlt_properties_get_data( b_props, "luma", NULL );
216 // Constructuct the matrix
218 affine_rotate( affine
->matrix
, rotate
);
220 affine_shear( affine
->matrix
, shear
);
222 affine_scale( affine
->matrix
, sx
, sy
);
223 affine_offset( affine
->matrix
, ox
, oy
);
225 affine_invert( affine
->matrix
);
227 if ( geometry
!= NULL
)
229 sscanf( geometry
, "%f,%f:%fx%f", &gx
, &gy
, &gw
, &gh
);
230 gx
= gx
/ 100 * *width
;
231 gy
= gy
/ 100 * *height
;
232 gw
= gw
/ 100 * *width
;
233 gh
= gh
/ 100 * *height
;
236 for ( y
= - *height
/ 2; y
< *height
/ 2; y
++ )
238 for ( x
= - *width
/ 2; x
< *width
/ 2; x
++ )
240 dx
= MapX( affine
->matrix
, x
, y
) + b_width
/ 2;
241 dy
= MapY( affine
->matrix
, x
, y
) + b_height
/ 2;
243 if ( dx
>= 0 && dx
< b_width
&& dy
>=0 && dy
< b_height
)
245 *p
++ = *( b_image
+ dy
* b_width
* 2 + dx
* 2 );
247 *p
++ = *( b_image
+ dy
* b_width
* 2 + ( dx
/ 2 ) * 4 + 1 );
249 *p
++ = *( b_image
+ dy
* b_width
* 2 + ( dx
/ 2 ) * 4 + 3 );
262 /** Affine transition processing.
265 static mlt_frame
transition_process( mlt_transition transition
, mlt_frame a_frame
, mlt_frame b_frame
)
267 // Get a unique name to store the frame position
268 char *name
= mlt_properties_get( mlt_transition_properties( transition
), "_unique_id" );
270 // Assign the current position to the name
271 mlt_properties_set_position( mlt_frame_properties( a_frame
), name
, mlt_frame_get_position( a_frame
) );
273 // Push the transition on to the frame
274 mlt_frame_push_service( a_frame
, transition
);
276 // Push the b_frame on to the stack
277 mlt_frame_push_frame( a_frame
, b_frame
);
279 // Push the transition method
280 mlt_frame_push_get_image( a_frame
, transition_get_image
);
285 /** Constructor for the filter.
288 mlt_transition
transition_affine_init( char *arg
)
290 mlt_transition transition
= mlt_transition_new( );
291 if ( transition
!= NULL
)
293 affine_t
*affine
= malloc( sizeof( affine_t
) );
294 affine_init( affine
->matrix
);
295 mlt_properties_set_data( mlt_transition_properties( transition
), "affine", affine
, 0, free
, NULL
);
296 mlt_properties_set_int( mlt_transition_properties( transition
), "sx", 1 );
297 mlt_properties_set_int( mlt_transition_properties( transition
), "sy", 1 );
298 mlt_properties_set( mlt_transition_properties( transition
), "geometry", "0,0:100%x100%" );
299 transition
->process
= transition_process
;