2 * filter_imageconvert.c -- colorspace and pixel format converter
3 * Copyright (C) 2009 Ushodaya Enterprises Limited
4 * Author: Dan Dennedy <dan@dennedy.org>
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.
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.
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
21 #include <framework/mlt_filter.h>
22 #include <framework/mlt_frame.h>
23 #include <framework/mlt_log.h>
24 #include <framework/mlt_pool.h>
28 /** This macro converts a YUV value to the RGB color space. */
29 #define RGB2YUV_601_UNSCALED(r, g, b, y, u, v)\
30 y = (299*r + 587*g + 114*b) >> 10;\
31 u = ((-169*r - 331*g + 500*b) >> 10) + 128;\
32 v = ((500*r - 419*g - 81*b) >> 10) + 128;\
36 y = y > 235 ? 235 : y;\
37 u = u > 240 ? 240 : u;\
40 /** This macro scales YUV up into the full gamut of the RGB color space. */
41 #define YUV2RGB_601_SCALED( y, u, v, r, g, b ) \
42 r = ((1192 * ( y - 16 ) + 1634 * ( v - 128 ) ) >> 10 ); \
43 g = ((1192 * ( y - 16 ) - 832 * ( v - 128 ) - 401 * ( u - 128 ) ) >> 10 ); \
44 b = ((1192 * ( y - 16 ) + 2066 * ( u - 128 ) ) >> 10 ); \
45 r = r < 0 ? 0 : r > 255 ? 255 : r; \
46 g = g < 0 ? 0 : g > 255 ? 255 : g; \
47 b = b < 0 ? 0 : b > 255 ? 255 : b;
49 /** This macro converts a YUV value to the RGB color space. */
50 #define YUV2RGB_601_UNSCALED( y, u, v, r, g, b ) \
51 r = ((1024 * y + 1404 * ( v - 128 ) ) >> 10 ); \
52 g = ((1024 * y - 715 * ( v - 128 ) - 345 * ( u - 128 ) ) >> 10 ); \
53 b = ((1024 * y + 1774 * ( u - 128 ) ) >> 10 ); \
54 r = r < 0 ? 0 : r > 255 ? 255 : r; \
55 g = g < 0 ? 0 : g > 255 ? 255 : g; \
56 b = b < 0 ? 0 : b > 255 ? 255 : b;
59 static int convert_yuv422_to_rgb24a( uint8_t *yuv, uint8_t *rgba, uint8_t *alpha, int width, int height )
64 int total = width * height / 2 + 1;
71 YUV2RGB_601_SCALED (yy, uu, vv, r, g, b);
77 YUV2RGB_601_SCALED (yy, uu, vv, r, g, b);
88 static int convert_yuv422_to_rgb24( uint8_t *yuv, uint8_t *rgb, uint8_t *alpha, int width, int height )
93 int total = width * height / 2 + 1;
100 YUV2RGB_601_SCALED (yy, uu, vv, r, g, b);
105 YUV2RGB_601_SCALED (yy, uu, vv, r, g, b);
115 static int convert_rgb24a_to_yuv422( uint8_t *rgba, uint8_t *yuv, uint8_t *alpha, int width, int height )
118 int stride = width * 4;
119 int y0, y1, u0, u1, v0, v1;
121 uint8_t *s, *d = yuv;
122 int i, j, n = width / 2 + 1;
125 for ( i = 0; i < height; i++ )
127 s = rgba + ( stride * i );
135 RGB2YUV_601_SCALED (r, g, b, y0, u0 , v0);
140 RGB2YUV_601_SCALED (r, g, b, y1, u1 , v1);
152 RGB2YUV_601_SCALED (r, g, b, y0, u0 , v0);
158 for ( i = 0; i < height; i++ )
160 s = rgba + ( stride * i );
168 RGB2YUV_601_SCALED (r, g, b, y0, u0 , v0);
173 RGB2YUV_601_SCALED (r, g, b, y1, u1 , v1);
185 RGB2YUV_601_SCALED (r, g, b, y0, u0 , v0);
194 static int convert_rgb24_to_yuv422( uint8_t *rgb, uint8_t *yuv, uint8_t *alpha, int width, int height )
197 int stride = width * 3;
198 int y0, y1, u0, u1, v0, v1;
200 uint8_t *s, *d = yuv;
201 int i, j, n = width / 2 + 1;
203 for ( i = 0; i < height; i++ )
205 s = rgb + ( stride * i );
212 RGB2YUV_601_SCALED (r, g, b, y0, u0 , v0);
216 RGB2YUV_601_SCALED (r, g, b, y1, u1 , v1);
227 RGB2YUV_601_SCALED (r, g, b, y0, u0 , v0);
235 static int convert_yuv420p_to_yuv422( uint8_t *yuv420p, uint8_t *yuv, uint8_t *alpha, int width, int height )
239 int half = width >> 1;
240 uint8_t *Y = yuv420p;
241 uint8_t *U = Y + width * height;
242 uint8_t *V = U + width * height / 4;
245 for ( i = 0; i < height; i++ )
247 uint8_t *u = U + ( i / 2 ) * ( half );
248 uint8_t *v = V + ( i / 2 ) * ( half );
262 static int convert_rgb24_to_rgb24a( uint8_t *rgb, uint8_t *rgba, uint8_t *alpha, int width, int height )
266 int total = width * height + 1;
279 static int convert_rgb24a_to_rgb24( uint8_t *rgba, uint8_t *rgb, uint8_t *alpha, int width, int height )
283 int total = width * height + 1;
296 typedef int ( *conversion_function )( uint8_t *yuv, uint8_t *rgba, uint8_t *alpha, int width, int height );
298 static conversion_function conversion_matrix[5][5] = {
299 { NULL, convert_rgb24_to_rgb24a, convert_rgb24_to_yuv422, NULL, convert_rgb24_to_rgb24a },
300 { convert_rgb24a_to_rgb24, NULL, convert_rgb24a_to_yuv422, NULL, NULL },
301 { convert_yuv422_to_rgb24, convert_yuv422_to_rgb24a, NULL, NULL, convert_yuv422_to_rgb24a },
302 { NULL, NULL, convert_yuv420p_to_yuv422, NULL, NULL },
303 { convert_rgb24a_to_rgb24, NULL, convert_rgb24a_to_yuv422, NULL, NULL },
306 static uint8_t bpp_table[4] = { 3, 4, 2, 0 };
308 static int convert_image( mlt_frame frame, uint8_t **buffer, mlt_image_format *format, mlt_image_format requested_format )
311 mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
312 int width = mlt_properties_get_int( properties, "width" );
313 int height = mlt_properties_get_int( properties, "height" );
315 if ( *format != requested_format )
317 conversion_function converter = conversion_matrix[ *format - 1 ][ requested_format - 1 ];
319 mlt_log_debug( NULL, "[filter imageconvert] %s -> %s\n",
320 mlt_image_format_name( *format ), mlt_image_format_name( requested_format ) );
323 int size = width * height * bpp_table[ requested_format - 1 ];
324 uint8_t *image = mlt_pool_alloc( size );
325 uint8_t *alpha = ( *format == mlt_image_rgb24a ||
326 *format == mlt_image_opengl )
327 ? mlt_pool_alloc( width * height ) : NULL;
329 if ( !( error = converter( *buffer, image, alpha, width, height ) ) )
331 mlt_properties_set_data( properties, "image", image, size, mlt_pool_release, NULL );
333 mlt_properties_set_data( properties, "alpha", alpha, width * height, mlt_pool_release, NULL );
335 *format = requested_format;
339 mlt_pool_release( image );
341 mlt_pool_release( alpha );
350 mlt_properties_set_int( properties, "format", *format );
355 /** Filter processing.
358 static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
360 frame->convert_image = convert_image;
364 /** Constructor for the filter.
367 mlt_filter filter_imageconvert_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
369 mlt_filter this = calloc( sizeof( struct mlt_filter_s ), 1 );
370 if ( mlt_filter_init( this, this ) == 0 )
372 this->process = filter_process;