]> git.sesse.net Git - mlt/blob - src/modules/kdenlive/filter_boxblur.c
c48fc3dee99fcbe563ace166a84f92aa16c1690e
[mlt] / src / modules / kdenlive / filter_boxblur.c
1 /*
2  * filter_boxblur.c -- blur filter
3  * Copyright (C) ?-2007 Leny Grisel <leny.grisel@laposte.net>
4  * Copyright (C) 2007 Jean-Baptiste Mardelle <jb@ader.ch>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include <framework/mlt_filter.h>
22 #include <framework/mlt_frame.h>
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <math.h>
27
28
29 static void PreCompute(uint8_t *image, int32_t *rgb, int width, int height)
30 {
31         register int x, y, z;
32         int32_t pts[3];
33         
34         for (y = 0; y < height; y++)
35         {
36                 for (x = 0; x < width; x++)
37                 {
38                         pts[0] = image[0];
39                         pts[1] = image[1];
40                         pts[2] = image[2];
41                         for (z = 0; z < 3; z++) 
42                         {
43                                 if (x > 0) pts[z] += rgb[-3];
44                                 if (y > 0) pts[z] += rgb[width * -3];
45                                 if (x>0 && y>0) pts[z] -= rgb[(width + 1) * -3];
46                                 *rgb++ = pts[z];
47             }
48                         image += 3;
49                 }
50         }
51 }
52
53 static int32_t GetRGB(int32_t *rgb, unsigned int w, unsigned int h, unsigned int x, int offsetx, unsigned int y, int offsety, unsigned int z)
54 {
55         int xtheo = x * 1 + offsetx;
56         int ytheo = y + offsety;
57         if (xtheo < 0) xtheo = 0; else if (xtheo >= w) xtheo = w - 1;
58         if (ytheo < 0) ytheo = 0; else if (ytheo >= h) ytheo = h - 1;
59         return rgb[3*(xtheo+ytheo*w)+z];
60 }
61
62 static void DoBoxBlur(uint8_t *image, int32_t *rgb, unsigned int width, unsigned int height, unsigned int boxw, unsigned int boxh)
63 {
64         register int x, y;
65         float mul = 1.f / ((boxw*2) * (boxh*2));
66
67         for (y = 0; y < height; y++)
68         {
69                 for (x = 0; x < width; x++)
70                 {
71                         *image++ = (GetRGB(rgb, width, height, x, +boxw, y, +boxh, 0)
72                                   + GetRGB(rgb, width, height, x, -boxw, y, -boxh, 0)
73                                   - GetRGB(rgb, width, height, x, -boxw, y, +boxh, 0)
74                                   - GetRGB(rgb, width, height, x, +boxw, y, -boxh, 0)) * mul;
75                         *image++ = (GetRGB(rgb, width, height, x, +boxw, y, +boxh, 1)
76                                   + GetRGB(rgb, width, height, x, -boxw, y, -boxh, 1)
77                                   - GetRGB(rgb, width, height, x, -boxw, y, +boxh, 1)
78                                   - GetRGB(rgb, width, height, x, +boxw, y, -boxh, 1)) * mul;
79                         *image++ = (GetRGB(rgb, width, height, x, +boxw, y, +boxh, 2)
80                                   + GetRGB(rgb, width, height, x, -boxw, y, -boxh, 2)
81                                   - GetRGB(rgb, width, height, x, -boxw, y, +boxh, 2)
82                                   - GetRGB(rgb, width, height, x, +boxw, y, -boxh, 2)) * mul;
83                 }
84         }
85 }
86
87 static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
88 {
89         // Get the image
90         *format = mlt_image_rgb24;
91         int error = mlt_frame_get_image( this, image, format, width, height, 1 );
92         short hori = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "hori" );
93         short vert = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "vert" );
94
95         // Only process if we have no error and a valid colour space
96         if ( error == 0 )
97         {
98                 double factor = mlt_properties_get_double( MLT_FRAME_PROPERTIES( this ), "boxblur" );
99                 if ( factor != 0)
100                 {
101                         int h = *height + 1;
102                         int32_t *rgb = mlt_pool_alloc( 3 * *width * h * sizeof(int32_t) );
103                         PreCompute( *image, rgb, *width, h );
104                         DoBoxBlur( *image, rgb, *width, h, (int) factor * hori, (int) factor * vert );
105                         mlt_pool_release( rgb );
106                 }
107         }
108         return error;
109 }
110
111 /** Filter processing.
112 */
113
114 static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
115 {
116         // Get the starting blur level
117         double blur = (double) mlt_properties_get_int( MLT_FILTER_PROPERTIES( this ), "start" );
118         short hori = mlt_properties_get_int(MLT_FILTER_PROPERTIES( this ), "hori" );
119         short vert = mlt_properties_get_int(MLT_FILTER_PROPERTIES( this ), "vert" );
120
121         // If there is an end adjust gain to the range
122         if ( mlt_properties_get( MLT_FILTER_PROPERTIES( this ), "end" ) != NULL )
123         {
124                 // Determine the time position of this frame in the transition duration
125                 mlt_position in = mlt_filter_get_in( this );
126                 mlt_position out = mlt_filter_get_out( this );
127                 mlt_position time = mlt_frame_get_position( frame );
128                 double position = (double) ( time - in ) / ( out - in + 1.0 );
129                 double end = (double) mlt_properties_get_int( MLT_FILTER_PROPERTIES( this ), "end" );
130                 blur += ( end - blur ) * position;
131         }
132
133         // Push the frame filter
134         mlt_properties_set_double( MLT_FRAME_PROPERTIES( frame ), "boxblur", blur );
135         mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "hori", hori );
136         mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "vert", vert );
137         mlt_frame_push_get_image( frame, filter_get_image );
138
139         return frame;
140 }
141
142 /** Constructor for the filter.
143 */
144
145 mlt_filter filter_boxblur_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
146 {
147         mlt_filter this = mlt_filter_new( );
148         if ( this != NULL )
149         {
150                 this->process = filter_process;
151                 mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "start", arg == NULL ? "2" : arg);
152                 mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "hori", arg == NULL ? "1" : arg);
153                 mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "vert", arg == NULL ? "1" : arg);
154         }
155         return this;
156 }
157
158
159