2 * filter_burn.c -- burning filter
3 * Copyright (C) 2007 Stephane Fillod
5 * Filter taken from EffecTV - Realtime Digital Video Effector
6 * Copyright (C) 2001-2006 FUKUCHI Kentaro
8 * BurningTV - burns incoming objects.
9 * Copyright (C) 2001-2002 FUKUCHI Kentaro
11 * Fire routine is taken from Frank Jan Sorensen's demo program.
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software Foundation,
26 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 #include <framework/mlt_filter.h>
30 #include <framework/mlt_frame.h>
41 #define MAGIC_THRESHOLD "50"
43 static RGB32 palette[256];
45 static void makePalette(void)
48 uint8_t *p = (uint8_t*) palette;
50 for(i=0; i<MaxColor; i++) {
51 HSItoRGB(4.6-1.5*i/MaxColor, (double)i/MaxColor, (double)i/MaxColor, &r, &g, &b);
57 for(i=MaxColor; i<256; i++) {
58 if(r<255)r++;if(r<255)r++;if(r<255)r++;
70 static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
74 unsigned char *buffer;
77 mlt_filter filter = mlt_frame_pop_service( this );
80 *format = mlt_image_rgb24a;
81 int error = mlt_frame_get_image( this, image, format, width, height, 1 );
83 // Only process if we have no error and a valid colour space
86 // Get the "Burn the foreground" value
87 int burn_foreground = mlt_properties_get_int( MLT_FILTER_PROPERTIES( filter ), "foreground" );
88 int y_threshold = image_set_threshold_y(
89 mlt_properties_get_int( MLT_FILTER_PROPERTIES( filter ), "threshold" ));
91 // We'll process pixel by pixel
96 int video_width = *width;
97 int video_height = *height;
98 int video_area = video_width * video_height;
99 // We need to create a new frame as this effect modifies the input
100 RGB32 *dest = (RGB32*)*image;
101 RGB32 *src = (RGB32*)*image;
106 mlt_service_lock( MLT_FILTER_SERVICE( filter ) );
108 diff = mlt_properties_get_data( MLT_FILTER_PROPERTIES( filter ), "_diff", NULL );
111 diff = mlt_pool_alloc(video_area*sizeof(unsigned char));
112 mlt_properties_set_data( MLT_FILTER_PROPERTIES( filter ), "_diff",
113 diff, video_area*sizeof(unsigned char), mlt_pool_release, NULL );
116 buffer = mlt_properties_get_data( MLT_FILTER_PROPERTIES( filter ), "_buffer", NULL );
119 buffer = mlt_pool_alloc(video_area*sizeof(unsigned char));
120 memset(buffer, 0, video_area*sizeof(unsigned char));
121 mlt_properties_set_data( MLT_FILTER_PROPERTIES( filter ), "_buffer",
122 buffer, video_area*sizeof(unsigned char), mlt_pool_release, NULL );
125 if (burn_foreground == 1) {
126 /* to burn the foreground, we need a background */
127 background = mlt_properties_get_data( MLT_FILTER_PROPERTIES( filter ),
128 "_background", NULL );
129 if (background == NULL)
131 background = mlt_pool_alloc(video_area*sizeof(RGB32));
132 image_bgset_y(background, src, video_area, y_threshold);
133 mlt_properties_set_data( MLT_FILTER_PROPERTIES( filter ), "_background",
134 background, video_area*sizeof(RGB32), mlt_pool_release, NULL );
138 mlt_service_unlock( MLT_FILTER_SERVICE( filter ) );
140 if (burn_foreground == 1) {
141 image_bgsubtract_y(diff, background, src, video_area, y_threshold);
144 image_y_over(diff, src, video_area, y_threshold);
147 for(x=1; x<video_width-1; x++) {
149 for(y=0; y<video_height-1; y++) {
150 w = diff[y*video_width+x];
151 buffer[y*video_width+x] |= v ^ w;
155 for(x=1; x<video_width-1; x++) {
157 for(y=1; y<video_height; y++) {
160 buffer[i-video_width] = 0;
162 buffer[i-video_width+fastrand()%3-1] = v - (fastrand()&Decay);
168 for(y=0; y<video_height; y++) {
169 for(x=1; x<video_width-1; x++) {
170 /* FIXME: endianess? */
171 a = (src[i] & 0xfefeff) + palette[buffer[i]];
173 dest[i] = a | (b - (b >> 8));
183 /** Filter processing.
186 static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
188 // Push the frame filter
189 mlt_frame_push_service( frame, this );
190 mlt_frame_push_get_image( frame, filter_get_image );
195 /** Constructor for the filter.
198 mlt_filter filter_burn_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
200 mlt_filter this = mlt_filter_new( );
203 this->process = filter_process;
204 mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "foreground", "0" );
205 mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "threshold", MAGIC_THRESHOLD );