From: Janne Liljeblad Date: Mon, 10 Feb 2014 10:57:02 +0000 (+0200) Subject: Add rgblut filter X-Git-Url: https://git.sesse.net/?p=mlt;a=commitdiff_plain;h=f80af938c8dba920f0782aa89be473590bbe7255 Add rgblut filter --- diff --git a/src/modules/plus/Makefile b/src/modules/plus/Makefile index 8102a1b7..c96f4b99 100644 --- a/src/modules/plus/Makefile +++ b/src/modules/plus/Makefile @@ -13,6 +13,7 @@ OBJS = consumer_blipflash.o \ filter_dynamictext.o \ filter_invert.o \ filter_loudness.o \ + filter_rgblut.o \ filter_sepia.o \ producer_blipflash.o \ producer_count.o \ diff --git a/src/modules/plus/factory.c b/src/modules/plus/factory.c index a7399571..92989e34 100644 --- a/src/modules/plus/factory.c +++ b/src/modules/plus/factory.c @@ -28,6 +28,7 @@ extern mlt_filter filter_charcoal_init( mlt_profile profile, mlt_service_type ty extern mlt_filter filter_dynamictext_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg ); extern mlt_filter filter_loudness_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg ); extern mlt_filter filter_invert_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg ); +extern mlt_filter filter_rgblut_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg ); extern mlt_filter filter_sepia_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg ); extern mlt_producer producer_blipflash_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg ); extern mlt_producer producer_count_init( const char *arg ); @@ -48,6 +49,7 @@ MLT_REPOSITORY MLT_REGISTER( filter_type, "dynamictext", filter_dynamictext_init ); MLT_REGISTER( filter_type, "invert", filter_invert_init ); MLT_REGISTER( filter_type, "loudness", filter_loudness_init ); + MLT_REGISTER( filter_type, "rgblut", filter_rgblut_init ); MLT_REGISTER( filter_type, "sepia", filter_sepia_init ); MLT_REGISTER( producer_type, "blipflash", producer_blipflash_init ); MLT_REGISTER( producer_type, "count", producer_count_init ); @@ -59,6 +61,7 @@ MLT_REPOSITORY MLT_REGISTER_METADATA( filter_type, "dynamictext", metadata, "filter_dynamictext.yml" ); MLT_REGISTER_METADATA( filter_type, "invert", metadata, "filter_invert.yml" ); MLT_REGISTER_METADATA( filter_type, "loudness", metadata, "filter_loudness.yml" ); + MLT_REGISTER_METADATA( filter_type, "rgblut", metadata, "filter_rgblut.yml" ); MLT_REGISTER_METADATA( filter_type, "sepia", metadata, "filter_sepia.yml" ); MLT_REGISTER_METADATA( producer_type, "blipflash", metadata, "producer_blipflash.yml" ); MLT_REGISTER_METADATA( producer_type, "count", metadata, "producer_count.yml" ); diff --git a/src/modules/plus/filter_rgblut.c b/src/modules/plus/filter_rgblut.c new file mode 100644 index 00000000..6d2e936a --- /dev/null +++ b/src/modules/plus/filter_rgblut.c @@ -0,0 +1,136 @@ +/* + * filter_rgblut.c -- generic RGB look-up table filter with string interface + * Copyright (C) 2014 Janne Liljeblad + * Author: Janne Liljeblad + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include +#include +#include +#include + +/** Fill channel lut with integers parsed from property string. +*/ +static void fill_channel_lut(int lut[], char* channel_table_str) +{ + mlt_tokeniser tokeniser = mlt_tokeniser_init(); + mlt_tokeniser_parse_new( tokeniser, channel_table_str, ";" ); + + // Only create lut from string if tokens count exactly right + if ( tokeniser->count == 256 ) + { + // Fill lut with token values + int i; + int val; + for( i = 0; i < 256; i++ ) + { + val = atoi(tokeniser->tokens[i]); + lut[i] = val; + } + } + else + { + // Fill lut with linear no-op table + int i; + for( i = 0; i < 256; i++ ) + { + lut[i] = i; + } + } + mlt_tokeniser_close( tokeniser ); +} + +/** Do it :-). +*/ +static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ) +{ + // Get the image + mlt_filter filter = mlt_frame_pop_service( this ); + + *format = mlt_image_rgb24; + int error = mlt_frame_get_image( this, image, format, width, height, 0 ); + + // Only process if we have no error and a valid colour space + if ( error == 0 ) + { + // Create lut tables from properties for each RGB channel + char* r_str = mlt_properties_get( MLT_FRAME_PROPERTIES( this ), "R_table" ); + int r_lut[256]; + fill_channel_lut( r_lut, r_str ); + + char* g_str = mlt_properties_get( MLT_FRAME_PROPERTIES( this ), "G_table" ); + int g_lut[256]; + fill_channel_lut( g_lut, g_str ); + + char* b_str = mlt_properties_get( MLT_FRAME_PROPERTIES( this ), "B_table" ); + int b_lut[256]; + fill_channel_lut( b_lut, b_str ); + + // Apply look-up tables into image + int i = *width * *height + 1; + uint8_t *p = *image; + uint8_t *r = *image; + while ( --i ) + { + *p ++ = r_lut[ *r ++ ]; + *p ++ = g_lut[ *r ++ ]; + *p ++ = b_lut[ *r ++ ]; + } + } + + return error; +} + +/** Filter processing. +*/ + +static mlt_frame filter_process( mlt_filter this, mlt_frame frame ) +{ + char* r_table = mlt_properties_get( MLT_FILTER_PROPERTIES( this ), "R_table" ); + char* g_table = mlt_properties_get( MLT_FILTER_PROPERTIES( this ), "G_table" ); + char* b_table = mlt_properties_get( MLT_FILTER_PROPERTIES( this ), "B_table" ); + + mlt_properties_set( MLT_FRAME_PROPERTIES( frame ), "R_table", r_table ); + mlt_properties_set( MLT_FRAME_PROPERTIES( frame ), "G_table", g_table ); + mlt_properties_set( MLT_FRAME_PROPERTIES( frame ), "B_table", b_table ); + + // Push the frame filter + mlt_frame_push_service( frame, this ); + mlt_frame_push_get_image( frame, filter_get_image ); + return frame; +} + +/** Constructor for the filter. +*/ + +mlt_filter filter_rgblut_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg ) +{ + mlt_filter this = mlt_filter_new( ); + if ( this != NULL ) + { + this->process = filter_process; + mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "R_table", "unset" ); + mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "G_table", "unset" ); + mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "B_table", "unset" ); + } + return this; +} + diff --git a/src/modules/plus/filter_rgblut.yml b/src/modules/plus/filter_rgblut.yml new file mode 100644 index 00000000..93e8849b --- /dev/null +++ b/src/modules/plus/filter_rgblut.yml @@ -0,0 +1,47 @@ +schema_version: 0.1 +type: filter +identifier: rgblut +title: RGBLUT +version: 1 +copyright: Janne Liljeblad +creator: Janne Liljeblad +license: LGPLv2.1 +language: en +tags: + - Video +description: + Converts input strings with exactly 256 half-comma separated integer values in + range 0 - 255 to look-up tables that then used to modify R, G, B values. + + This creates a generic string interface for color correction. + +parameters: + - identifier: R_table + title: Red channel look-up table + type: string + default: unset + description: > + Value is tokenised using half-comma separator into exactly 256 integer + values in range 0 - 255 and a loop-up table for red channel values is + created and applied to image. If tokenising of value fails a linear table + that returns input values unchanged is used instead. + + - identifier: G_table + title: Green channel look-up table + type: string + default: unset + description: > + Value is tokenised using half-comma separator into exactly 256 integer + values in range 0 - 255 and a loop-up table for green channel values is + created and applied to image. If tokenising of value fails a linear table + that returns input values unchanged is used instead. + + - identifier: B_table + title: Blue channel look-up table + type: string + default: unset + description: > + Value is tokenised using half-comma separator into exactly 256 integer + values in range 0 - 255 and a loop-up table for green channel values is + created and applied to image. If tokenising of value fails a linear table + that returns input values unchanged is used instead.