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 "filter_burn.h"
31 #include <framework/mlt_frame.h>
42 #define MAGIC_THRESHOLD "50"
44 static RGB32 palette
[256];
46 /* FIXME: endianess? */
47 static void makePalette(void)
51 for(i
=0; i
<MaxColor
; i
++) {
52 HSItoRGB(4.6-1.5*i
/MaxColor
, (double)i
/MaxColor
, (double)i
/MaxColor
, &r
, &g
, &b
);
53 palette
[i
] = ((r
<<16)|(g
<<8)|b
) & 0xfefeff;
55 for(i
=MaxColor
; i
<256; i
++) {
56 if(r
<255)r
++;if(r
<255)r
++;if(r
<255)r
++;
61 palette
[i
] = ((r
<<16)|(g
<<8)|b
) & 0xfefeff;
65 static int filter_get_image( mlt_frame
this, uint8_t **image
, mlt_image_format
*format
, int *width
, int *height
, int writable
)
69 unsigned char *buffer
;
72 mlt_filter filter
= mlt_frame_pop_service( this );
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
78 if ( error
== 0 && *format
== mlt_image_yuv422
)
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
= mlt_pool_alloc( video_area
* sizeof(RGB32
) );
95 RGB32
*src
= (RGB32
*)dest
;
100 mlt_convert_yuv422_to_rgb24a(*image
, (uint8_t *)dest
, video_area
);
103 diff
= mlt_properties_get_data( MLT_FILTER_PROPERTIES( filter
),
107 diff
= mlt_pool_alloc(video_area
*sizeof(unsigned char));
108 mlt_properties_set_data( MLT_FILTER_PROPERTIES( filter
), "_diff",
109 diff
, video_area
*sizeof(unsigned char), mlt_pool_release
, NULL
);
112 buffer
= mlt_properties_get_data( MLT_FILTER_PROPERTIES( filter
),
116 buffer
= mlt_pool_alloc(video_area
*sizeof(unsigned char));
117 memset(buffer
, 0, video_area
*sizeof(unsigned char));
118 mlt_properties_set_data( MLT_FILTER_PROPERTIES( filter
), "_buffer",
119 buffer
, video_area
*sizeof(unsigned char), mlt_pool_release
, NULL
);
123 if (burn_foreground
== 1) {
124 /* to burn the foreground, we need a background */
125 background
= mlt_properties_get_data( MLT_FILTER_PROPERTIES( filter
),
126 "_background", NULL
);
127 if (background
== NULL
)
129 background
= mlt_pool_alloc(video_area
*sizeof(RGB32
));
130 image_bgset_y(background
, src
, video_area
, y_threshold
);
131 mlt_properties_set_data( MLT_FILTER_PROPERTIES( filter
), "_background",
132 background
, video_area
*sizeof(RGB32
), mlt_pool_release
, NULL
);
136 if (burn_foreground
== 1) {
137 image_bgsubtract_y(diff
, background
, src
, video_area
, y_threshold
);
140 image_y_over(diff
, src
, video_area
, y_threshold
);
143 for(x
=1; x
<video_width
-1; x
++) {
145 for(y
=0; y
<video_height
-1; y
++) {
146 w
= diff
[y
*video_width
+x
];
147 buffer
[y
*video_width
+x
] |= v ^ w
;
151 for(x
=1; x
<video_width
-1; x
++) {
153 for(y
=1; y
<video_height
; y
++) {
156 buffer
[i
-video_width
] = 0;
158 buffer
[i
-video_width
+fastrand()%3-1] = v
- (fastrand()&Decay
);
164 for(y
=0; y
<video_height
; y
++) {
165 for(x
=1; x
<video_width
-1; x
++) {
166 /* FIXME: endianess? */
167 a
= (src
[i
] & 0xfefeff) + palette
[buffer
[i
]];
169 dest
[i
] = a
| (b
- (b
>> 8));
175 mlt_convert_rgb24a_to_yuv422((uint8_t *)dest
, *width
, *height
, *width
* sizeof(RGB32
),
178 mlt_pool_release(dest
);
184 /** Filter processing.
187 static mlt_frame
filter_process( mlt_filter
this, mlt_frame frame
)
189 // Push the frame filter
190 mlt_frame_push_service( frame
, this );
191 mlt_frame_push_get_image( frame
, filter_get_image
);
196 /** Constructor for the filter.
199 mlt_filter
filter_burn_init( char *arg
)
201 mlt_filter
this = mlt_filter_new( );
204 this->process
= filter_process
;
205 mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "foreground", "0" );
206 mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "threshold", MAGIC_THRESHOLD
);