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.0f / 2.2f );
65 r += rlift * ( 1 - r );
66 g += glift * ( 1 - g );
67 b += blift * ( 1 - b );
70 r = pow( r, 2.2f / rgamma );
71 g = pow( g, 2.2f / ggamma );
72 b = pow( b, 2.2f / bgamma );
75 r *= pow( rgain, 1.0f / rgamma );
76 g *= pow( ggain, 1.0f / ggamma );
77 b *= pow( bgain, 1.0f / bgamma );
80 private->rlut[ i ] = (int)(r * 255.0);
81 private->glut[ i ] = (int)(g * 255.0);
82 private->blut[ i ] = (int)(b * 255.0);
85 // Store the values that created the LUT so that
86 // changes can be detected.
87 private->rlift = rlift;
88 private->glift = glift;
89 private->blift = blift;
90 private->rgamma = rgamma;
91 private->ggamma = ggamma;
92 private->bgamma = bgamma;
93 private->rgain = rgain;
94 private->ggain = ggain;
95 private->bgain = bgain;
99 static void apply_lut( mlt_filter filter, uint8_t* image, mlt_image_format format, int width, int height )
101 private_data* private = (private_data*)filter->child;
102 int total = width * height + 1;
103 uint8_t* sample = image;
107 case mlt_image_rgb24:
110 *sample = private->rlut[ *sample ];
112 *sample = private->glut[ *sample ];
114 *sample = private->blut[ *sample ];
118 case mlt_image_rgb24a:
121 *sample = private->rlut[ *sample ];
123 *sample = private->glut[ *sample ];
125 *sample = private->blut[ *sample ];
127 sample++; // Skip alpha
131 mlt_log_error( MLT_FILTER_SERVICE( filter ), "Invalid image format: %s\n", mlt_image_format_name( format ) );
136 static int filter_get_image( mlt_frame frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
138 mlt_filter filter = (mlt_filter) mlt_frame_pop_service( frame );
141 mlt_service_lock( MLT_FILTER_SERVICE( filter ) );
143 // Regenerate the LUT if necessary
144 refresh_lut( filter, frame );
146 // Make sure the format is acceptable
147 if( *format != mlt_image_rgb24 && *format != mlt_image_rgb24a )
149 *format = mlt_image_rgb24;
154 error = mlt_frame_get_image( frame, image, format, width, height, writable );
159 apply_lut( filter, *image, *format, *width, *height );
162 mlt_service_unlock( MLT_FILTER_SERVICE( filter ) );
167 static mlt_frame filter_process( mlt_filter filter, mlt_frame frame )
169 mlt_frame_push_service( frame, filter );
170 mlt_frame_push_get_image( frame, filter_get_image );
174 static void filter_close( mlt_filter filter )
176 private_data* private = (private_data*)filter->child;
182 filter->child = NULL;
183 filter->close = NULL;
184 filter->parent.close = NULL;
185 mlt_service_close( &filter->parent );
188 mlt_filter filter_lift_gamma_gain_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
190 mlt_filter filter = mlt_filter_new();
191 private_data* private = (private_data*)calloc( 1, sizeof(private_data) );
194 if ( filter && private )
196 mlt_properties properties = MLT_FILTER_PROPERTIES( filter );
198 // Initialize private data
199 for( i = 0; i < 256; i++ )
201 private->rlut[i] = i;
202 private->glut[i] = i;
203 private->blut[i] = i;
205 private->rlift = private->glift = private->blift = 0.0;
206 private->rgamma = private->ggamma = private->bgamma = 1.0;
207 private->rgain = private->ggain = private->bgain = 1.0;
209 // Initialize filter properties
210 mlt_properties_set_double( properties, "lift_r", private->rlift );
211 mlt_properties_set_double( properties, "lift_g", private->glift );
212 mlt_properties_set_double( properties, "lift_b", private->blift );
213 mlt_properties_set_double( properties, "gamma_r", private->rgamma );
214 mlt_properties_set_double( properties, "gamma_g", private->ggamma );
215 mlt_properties_set_double( properties, "gamma_b", private->bgamma );
216 mlt_properties_set_double( properties, "gain_r", private->rgain );
217 mlt_properties_set_double( properties, "gain_g", private->ggain );
218 mlt_properties_set_double( properties, "gain_b", private->bgain );
220 filter->close = filter_close;
221 filter->process = filter_process;
222 filter->child = private;
226 mlt_log_error( MLT_FILTER_SERVICE(filter), "Filter lift_gamma_gain init failed\n" );
230 mlt_filter_close( filter );