2 * filter_lift_gamma_gain.cpp
3 * Copyright (C) 2014 Brian Matherly <pez4brian@yahoo.com>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include <framework/mlt.h>
29 double rlift, glift, blift;
30 double rgamma, ggamma, bgamma;
31 double rgain, ggain, bgain;
34 static void refresh_lut( mlt_filter filter, mlt_frame frame )
36 private_data* private = (private_data*)filter->child;
37 mlt_properties properties = MLT_FILTER_PROPERTIES( filter );
38 mlt_position position = mlt_filter_get_position( filter, frame );
39 mlt_position length = mlt_filter_get_length2( filter, frame );
40 double rlift = mlt_properties_anim_get_double( properties, "lift_r", position, length );
41 double glift = mlt_properties_anim_get_double( properties, "lift_g", position, length );
42 double blift = mlt_properties_anim_get_double( properties, "lift_b", position, length );
43 double rgamma = mlt_properties_anim_get_double( properties, "gamma_r", position, length );
44 double ggamma = mlt_properties_anim_get_double( properties, "gamma_g", position, length );
45 double bgamma = mlt_properties_anim_get_double( properties, "gamma_b", position, length );
46 double rgain = mlt_properties_anim_get_double( properties, "gain_r", position, length );
47 double ggain = mlt_properties_anim_get_double( properties, "gain_g", position, length );
48 double bgain = mlt_properties_anim_get_double( properties, "gain_b", position, length );
50 // Only regenerate the LUT if something changed.
51 if( private->rlift != rlift || private->glift != glift || private->blift != blift ||
52 private->rgamma != rgamma || private->ggamma != ggamma || private->bgamma != bgamma ||
53 private->rgain != rgain || private->ggain != ggain || private->bgain != bgain )
56 for( i = 0; i < 256; i++ )
58 // Convert to gamma 2.2
59 double gamma22 = pow( (double)i / 255.0, 1.0 / 2.2 );
65 r += rlift * ( 1.0 - r );
66 g += glift * ( 1.0 - g );
67 b += blift * ( 1.0 - b );
70 r = pow( r, 2.2 / rgamma );
71 g = pow( g, 2.2 / ggamma );
72 b = pow( b, 2.2 / bgamma );
75 r *= pow( rgain, 1.0 / rgamma );
76 g *= pow( ggain, 1.0 / ggamma );
77 b *= pow( bgain, 1.0 / bgamma );
80 r = r < 0.0 ? 0.0 : r > 1.0 ? 1.0 : r;
81 g = g < 0.0 ? 0.0 : g > 1.0 ? 1.0 : g;
82 b = b < 0.0 ? 0.0 : b > 1.0 ? 1.0 : b;
85 private->rlut[ i ] = (int)(r * 255.0);
86 private->glut[ i ] = (int)(g * 255.0);
87 private->blut[ i ] = (int)(b * 255.0);
90 // Store the values that created the LUT so that
91 // changes can be detected.
92 private->rlift = rlift;
93 private->glift = glift;
94 private->blift = blift;
95 private->rgamma = rgamma;
96 private->ggamma = ggamma;
97 private->bgamma = bgamma;
98 private->rgain = rgain;
99 private->ggain = ggain;
100 private->bgain = bgain;
104 static void apply_lut( mlt_filter filter, uint8_t* image, mlt_image_format format, int width, int height )
106 private_data* private = (private_data*)filter->child;
107 int total = width * height + 1;
108 uint8_t* sample = image;
112 case mlt_image_rgb24:
115 *sample = private->rlut[ *sample ];
117 *sample = private->glut[ *sample ];
119 *sample = private->blut[ *sample ];
123 case mlt_image_rgb24a:
126 *sample = private->rlut[ *sample ];
128 *sample = private->glut[ *sample ];
130 *sample = private->blut[ *sample ];
132 sample++; // Skip alpha
136 mlt_log_error( MLT_FILTER_SERVICE( filter ), "Invalid image format: %s\n", mlt_image_format_name( format ) );
141 static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
143 mlt_filter filter = (mlt_filter) mlt_frame_pop_service( frame );
146 mlt_service_lock( MLT_FILTER_SERVICE( filter ) );
148 // Regenerate the LUT if necessary
149 refresh_lut( filter, frame );
151 // Make sure the format is acceptable
152 if( *format != mlt_image_rgb24 && *format != mlt_image_rgb24a )
154 *format = mlt_image_rgb24;
159 error = mlt_frame_get_image( frame, image, format, width, height, writable );
164 apply_lut( filter, *image, *format, *width, *height );
167 mlt_service_unlock( MLT_FILTER_SERVICE( filter ) );
172 static mlt_frame filter_process( mlt_filter filter, mlt_frame frame )
174 mlt_frame_push_service( frame, filter );
175 mlt_frame_push_get_image( frame, filter_get_image );
179 static void filter_close( mlt_filter filter )
181 private_data* private = (private_data*)filter->child;
187 filter->child = NULL;
188 filter->close = NULL;
189 filter->parent.close = NULL;
190 mlt_service_close( &filter->parent );
193 mlt_filter filter_lift_gamma_gain_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
195 mlt_filter filter = mlt_filter_new();
196 private_data* private = (private_data*)calloc( 1, sizeof(private_data) );
199 if ( filter && private )
201 mlt_properties properties = MLT_FILTER_PROPERTIES( filter );
203 // Initialize private data
204 for( i = 0; i < 256; i++ )
206 private->rlut[i] = i;
207 private->glut[i] = i;
208 private->blut[i] = i;
210 private->rlift = private->glift = private->blift = 0.0;
211 private->rgamma = private->ggamma = private->bgamma = 1.0;
212 private->rgain = private->ggain = private->bgain = 1.0;
214 // Initialize filter properties
215 mlt_properties_set_double( properties, "lift_r", private->rlift );
216 mlt_properties_set_double( properties, "lift_g", private->glift );
217 mlt_properties_set_double( properties, "lift_b", private->blift );
218 mlt_properties_set_double( properties, "gamma_r", private->rgamma );
219 mlt_properties_set_double( properties, "gamma_g", private->ggamma );
220 mlt_properties_set_double( properties, "gamma_b", private->bgamma );
221 mlt_properties_set_double( properties, "gain_r", private->rgain );
222 mlt_properties_set_double( properties, "gain_g", private->ggain );
223 mlt_properties_set_double( properties, "gain_b", private->bgain );
225 filter->close = filter_close;
226 filter->process = filter_process;
227 filter->child = private;
231 mlt_log_error( MLT_FILTER_SERVICE(filter), "Filter lift_gamma_gain init failed\n" );
235 mlt_filter_close( filter );