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 /* FIXME: endianess? */
46 static void makePalette(void)
50 for(i=0; i<MaxColor; i++) {
51 HSItoRGB(4.6-1.5*i/MaxColor, (double)i/MaxColor, (double)i/MaxColor, &r, &g, &b);
52 palette[i] = ((r<<16)|(g<<8)|b) & 0xfefeff;
54 for(i=MaxColor; i<256; i++) {
55 if(r<255)r++;if(r<255)r++;if(r<255)r++;
60 palette[i] = ((r<<16)|(g<<8)|b) & 0xfefeff;
64 static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
68 unsigned char *buffer;
71 mlt_filter filter = mlt_frame_pop_service( this );
74 *format = mlt_image_rgb24a;
75 int error = mlt_frame_get_image( this, image, format, width, height, 1 );
77 // Only process if we have no error and a valid colour space
80 // Get the "Burn the foreground" value
81 int burn_foreground = mlt_properties_get_int( MLT_FILTER_PROPERTIES( filter ), "foreground" );
82 int y_threshold = image_set_threshold_y(
83 mlt_properties_get_int( MLT_FILTER_PROPERTIES( filter ), "threshold" ));
85 // We'll process pixel by pixel
90 int video_width = *width;
91 int video_height = *height;
92 int video_area = video_width * video_height;
93 // We need to create a new frame as this effect modifies the input
94 RGB32 *dest = (RGB32*)*image;
95 RGB32 *src = (RGB32*)*image;
100 diff = mlt_properties_get_data( MLT_FILTER_PROPERTIES( filter ),
104 diff = mlt_pool_alloc(video_area*sizeof(unsigned char));
105 mlt_properties_set_data( MLT_FILTER_PROPERTIES( filter ), "_diff",
106 diff, video_area*sizeof(unsigned char), mlt_pool_release, NULL );
109 buffer = mlt_properties_get_data( MLT_FILTER_PROPERTIES( filter ),
113 buffer = mlt_pool_alloc(video_area*sizeof(unsigned char));
114 memset(buffer, 0, video_area*sizeof(unsigned char));
115 mlt_properties_set_data( MLT_FILTER_PROPERTIES( filter ), "_buffer",
116 buffer, video_area*sizeof(unsigned char), mlt_pool_release, NULL );
120 if (burn_foreground == 1) {
121 /* to burn the foreground, we need a background */
122 background = mlt_properties_get_data( MLT_FILTER_PROPERTIES( filter ),
123 "_background", NULL );
124 if (background == NULL)
126 background = mlt_pool_alloc(video_area*sizeof(RGB32));
127 image_bgset_y(background, src, video_area, y_threshold);
128 mlt_properties_set_data( MLT_FILTER_PROPERTIES( filter ), "_background",
129 background, video_area*sizeof(RGB32), mlt_pool_release, NULL );
133 if (burn_foreground == 1) {
134 image_bgsubtract_y(diff, background, src, video_area, y_threshold);
137 image_y_over(diff, src, video_area, y_threshold);
140 for(x=1; x<video_width-1; x++) {
142 for(y=0; y<video_height-1; y++) {
143 w = diff[y*video_width+x];
144 buffer[y*video_width+x] |= v ^ w;
148 for(x=1; x<video_width-1; x++) {
150 for(y=1; y<video_height; y++) {
153 buffer[i-video_width] = 0;
155 buffer[i-video_width+fastrand()%3-1] = v - (fastrand()&Decay);
161 for(y=0; y<video_height; y++) {
162 for(x=1; x<video_width-1; x++) {
163 /* FIXME: endianess? */
164 a = (src[i] & 0xfefeff) + palette[buffer[i]];
166 dest[i] = a | (b - (b >> 8));
176 /** Filter processing.
179 static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
181 // Push the frame filter
182 mlt_frame_push_service( frame, this );
183 mlt_frame_push_get_image( frame, filter_get_image );
188 /** Constructor for the filter.
191 mlt_filter filter_burn_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
193 mlt_filter this = mlt_filter_new( );
196 this->process = filter_process;
197 mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "foreground", "0" );
198 mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "threshold", MAGIC_THRESHOLD );