From b2c090d6f4dec62f264e2d7c7299abb2a936c631 Mon Sep 17 00:00:00 2001 From: Janne Liljeblad Date: Mon, 24 Feb 2014 11:18:27 +0200 Subject: [PATCH] Add lumaliftgaingamma filter to plusgpl --- src/modules/plusgpl/Makefile | 1 + src/modules/plusgpl/factory.c | 3 + .../plusgpl/filter_lumaliftgaingamma.c | 169 ++++++++++++++++++ .../plusgpl/filter_lumaliftgaingamma.yml | 47 +++++ 4 files changed, 220 insertions(+) create mode 100644 src/modules/plusgpl/filter_lumaliftgaingamma.c create mode 100644 src/modules/plusgpl/filter_lumaliftgaingamma.yml diff --git a/src/modules/plusgpl/Makefile b/src/modules/plusgpl/Makefile index c204ad3d..71de1803 100644 --- a/src/modules/plusgpl/Makefile +++ b/src/modules/plusgpl/Makefile @@ -8,6 +8,7 @@ TARGET = ../libmltplusgpl$(LIBSUF) OBJS = factory.o \ filter_burn.o \ + filter_lumaliftgaingamma.o \ image.o \ utils.o \ filter_rotoscoping.o \ diff --git a/src/modules/plusgpl/factory.c b/src/modules/plusgpl/factory.c index dddc117c..a1874133 100644 --- a/src/modules/plusgpl/factory.c +++ b/src/modules/plusgpl/factory.c @@ -22,6 +22,7 @@ #include extern mlt_filter filter_burn_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg ); +extern mlt_filter filter_lumaliftgaingamma_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg ); extern mlt_filter filter_rotoscoping_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg ); extern mlt_filter filter_telecide_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg ); @@ -36,10 +37,12 @@ MLT_REPOSITORY { MLT_REGISTER( filter_type, "BurningTV", filter_burn_init ); MLT_REGISTER( filter_type, "burningtv", filter_burn_init ); + MLT_REGISTER( filter_type, "lumaliftgaingamma", filter_lumaliftgaingamma_init ); MLT_REGISTER( filter_type, "rotoscoping", filter_rotoscoping_init ); MLT_REGISTER( filter_type, "telecide", filter_telecide_init ); MLT_REGISTER_METADATA( filter_type, "BurningTV", metadata, "filter_burningtv.yml" ); MLT_REGISTER_METADATA( filter_type, "burningtv", metadata, "filter_burningtv.yml" ); + MLT_REGISTER_METADATA( filter_type, "lumaliftgaingamma", metadata, "filter_lumaliftgaingamma.yml" ); MLT_REGISTER_METADATA( filter_type, "rotoscoping", metadata, "filter_rotoscoping.yml" ); } diff --git a/src/modules/plusgpl/filter_lumaliftgaingamma.c b/src/modules/plusgpl/filter_lumaliftgaingamma.c new file mode 100644 index 00000000..11d5ecc9 --- /dev/null +++ b/src/modules/plusgpl/filter_lumaliftgaingamma.c @@ -0,0 +1,169 @@ +/* + * filter_lumaliftgaingamma.c -- Lift Gain Gamma filter for luma correction + * Copyright (C) 2014 Janne Liljeblad + * Author: Janne Liljeblad + * + * This filter is a port from Gimp and is distributed under a compatible license. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; 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 + +static double clamp( double value, double low, double high) +{ + if (value < low) + value = low; + if (value > high) + value = high; + return value; +} + +static double lut_value( double value, double lift, double gain, double gamma ) +{ + double nvalue; + double power; + + value = clamp( value + lift, 0, 1 ); + + if( gain < 0.0) + value = value * (1.0 + gain); + else + value = value + ((1.0 - value) * gain); + + if(gamma < 0.0) + { + if (value > 0.5) + nvalue = 1.0 - value; + else + nvalue = value; + + if (nvalue < 0.0) + nvalue = 0.0; + + nvalue = 0.5 * pow (nvalue * 2.0 , (double) (1.0 + gamma)); + + if (value > 0.5) + value = 1.0 - nvalue; + else + value = nvalue; + } + else + { + if (value > 0.5) + nvalue = 1.0 - value; + else + nvalue = value; + + if (nvalue < 0.0) + nvalue = 0.0; + + power = (gamma == 1.0) ? 127 : 1.0 / (1.0 - gamma); + nvalue = 0.5 * pow (2.0 * nvalue, power); + + if (value > 0.5) + value = 1.0 - nvalue; + else + value = nvalue; + } + + return value; +} + +static void fill_lgg_lut(int lgg_lut[], double lift, double gain, double gamma) +{ + int i; + double val; + for( i = 0; i < 256; i++ ) + { + val = (double) i / 255.0; + lgg_lut[ i ] = (int) (lut_value( val, lift, gain, gamma ) * 255.0); + } +} + +/** Do image filtering. +*/ +static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ) +{ + // Get the image + mlt_filter filter = (mlt_filter) mlt_frame_pop_service( frame ); + mlt_properties properties = MLT_FILTER_PROPERTIES( filter ); + mlt_position position = mlt_filter_get_position( filter, frame ); + mlt_position length = mlt_filter_get_length2( filter, frame ); + + *format = mlt_image_rgb24; + int error = mlt_frame_get_image( frame, image, format, width, height, 0 ); + + // Only process if we have no error and a valid colour space + if ( error == 0 ) + { + // Get values and force accepted ranges + double lift = mlt_properties_anim_get_double( properties, "lift", position, length ); + double gain = mlt_properties_anim_get_double( properties, "gain", position, length ); + double gamma = mlt_properties_anim_get_double( properties, "gamma", position, length ); + lift = clamp( lift, -0.5, 0.5 ); + gain = clamp( gain, -0.5, 0.5 ); + gamma = clamp( gamma, -1.0, 1.0 ); + + // Build lut + int lgg_lut[256]; + fill_lgg_lut( lgg_lut, lift, gain, gamma); + + // Filter + int i = *width * *height + 1; + uint8_t *p = *image; + uint8_t *r = *image; + while ( --i ) + { + *p ++ = lgg_lut[ *r ++ ]; + *p ++ = lgg_lut[ *r ++ ]; + *p ++ = lgg_lut[ *r ++ ]; + } + } + + return error; +} + +/** Filter processing. +*/ +static mlt_frame filter_process( mlt_filter filter, mlt_frame frame ) +{ + // Push the frame filter + mlt_frame_push_service( frame, filter ); + mlt_frame_push_get_image( frame, filter_get_image ); + return frame; +} + +/** Constructor for the filter. +*/ +mlt_filter filter_lumaliftgaingamma_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg ) +{ + mlt_filter filter = mlt_filter_new( ); + if ( filter != NULL ) + { + filter->process = filter_process; + mlt_properties_set( MLT_FILTER_PROPERTIES( filter ), "lift", "0" ); + mlt_properties_set( MLT_FILTER_PROPERTIES( filter ), "gain", "0" ); + mlt_properties_set( MLT_FILTER_PROPERTIES( filter ), "gamma", "0" ); + } + return filter; +} + diff --git a/src/modules/plusgpl/filter_lumaliftgaingamma.yml b/src/modules/plusgpl/filter_lumaliftgaingamma.yml new file mode 100644 index 00000000..83dde742 --- /dev/null +++ b/src/modules/plusgpl/filter_lumaliftgaingamma.yml @@ -0,0 +1,47 @@ +schema_version: 0.1 +type: filter +identifier: lumaliftgaingamma +title: LumaLiftGainGamma +version: 1 +copyright: Janne Liljeblad +creator: Janne Liljeblad +license: GPL +language: en +tags: + - Video +description: + Filter can be used to apply lift, gain and gamma correction to + luma values of image. + +parameters: + - identifier: lift + title: Lift + type: double + minimum: -0.5 + maximum: 0.5 + default: 0 + description: > + Adds a value computed using parameter value + to color channel values. + +parameters: + - identifier: gain + title: Gain + type: double + minimum: -0.5 + maximum: 0.5 + default: 0 + description: > + Multiplies color channel values by value + computed using paramter value. + +parameters: + - identifier: gamma + title: Gamma + type: double + minimum: -1.0 + maximum: 1.0 + default: 0 + description: > + Applies a gamma correction to all + color channel values. -- 2.39.2