2 * filter_boxblur.c -- blur filter
3 * Author: Leny Grisel <leny.grisel@laposte.net>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program 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
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * aint32_t with this program; if not, write to the Free Software Foundation,
17 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 #include "filter_boxblur.h"
22 #include <framework/mlt_frame.h>
29 static void PreCompute(uint8_t *yuv
, int32_t *rgb
, unsigned int width
, unsigned int height
)
32 register int uneven
= width
% 2;
33 int w
= (width
- uneven
) / 2;
37 for (y
=0; y
<height
; y
++)
44 YUV2RGB(yy
, uu
, vv
, r
, g
, b
);
48 for (z
= 0; z
< 3; z
++)
50 if (x
>0) pts
[z
]+=rgb
[-3];
51 if (y
>0) pts
[z
]+=rgb
[-(width
*3)];
52 if (x
>0 && y
>0) pts
[z
]-=rgb
[-((width
+1)*3)];
57 YUV2RGB(yy
, uu
, vv
, r
, g
, b
);
61 for (z
= 0; z
< 3; z
++)
66 pts
[z
]+=rgb
[-(width
*3)];
67 pts
[z
]-=rgb
[-((width
+1)*3)];
78 YUV2RGB(yy
, uu
, vv
, r
, g
, b
);
82 for (z
= 0; z
< 3; z
++)
87 pts
[z
]+=rgb
[-(width
*3)];
88 pts
[z
]-=rgb
[-((width
+1)*3)];
97 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
)
99 int xtheo
= x
* 2 + offsetx
;
100 int ytheo
= y
+ offsety
;
101 if (xtheo
< 0) xtheo
= 0; else if (xtheo
>= w
) xtheo
= w
- 1;
102 if (ytheo
< 0) ytheo
= 0; else if (ytheo
>= h
) ytheo
= h
- 1;
103 return rgb
[3*(xtheo
+ytheo
*w
)+z
];
106 static int32_t GetRGB2(int32_t *rgb
, unsigned int w
, unsigned int h
, unsigned int x
, int offsetx
, unsigned int y
, int offsety
, unsigned int z
)
108 int xtheo
= x
* 2 + 1 + offsetx
;
109 int ytheo
= y
+ offsety
;
110 if (xtheo
< 0) xtheo
= 0; else if (xtheo
>= w
) xtheo
= w
- 1;
111 if (ytheo
< 0) ytheo
= 0; else if (ytheo
>= h
) ytheo
= h
- 1;
112 return rgb
[3*(xtheo
+ytheo
*w
)+z
];
115 static void DoBoxBlur(uint8_t *yuv
, int32_t *rgb
, unsigned int width
, unsigned int height
, unsigned int boxw
, unsigned int boxh
)
119 register int uneven
= width
% 2;
120 register int y0
, y1
, u0
, u1
, v0
, v1
;
121 int w
= (width
- uneven
) / 2;
122 float mul
= 1.f
/ ((boxw
*2) * (boxh
*2));
124 for (y
= 0; y
< height
; y
++)
126 for (x
= 0; x
< w
; x
++)
128 r
= GetRGB(rgb
, width
, height
, x
, +boxw
, y
, +boxh
, 0) + GetRGB(rgb
, width
, height
, x
, -boxw
, y
, -boxh
, 0) - GetRGB(rgb
, width
, height
, x
, -boxw
, y
, + boxh
, 0) - GetRGB(rgb
, width
, height
, x
, +boxw
, y
, -boxh
, 0);
129 g
= GetRGB(rgb
, width
, height
, x
, +boxw
, y
, +boxh
, 1) + GetRGB(rgb
, width
, height
, x
, -boxw
, y
, -boxh
, 1) - GetRGB(rgb
, width
, height
, x
, -boxw
, y
, +boxh
, 1) - GetRGB(rgb
, width
, height
, x
, +boxw
, y
, -boxh
, 1);
130 b
= GetRGB(rgb
, width
, height
, x
, +boxw
, y
, +boxh
, 2) + GetRGB(rgb
, width
, height
, x
, -boxw
, y
, -boxh
, 2) - GetRGB(rgb
, width
, height
, x
, -boxw
, y
, +boxh
, 2) - GetRGB(rgb
, width
, height
, x
, +boxw
, y
, -boxh
, 2);
131 r
= (int32_t) (r
* mul
);
132 g
= (int32_t) (g
* mul
);
133 b
= (int32_t) (b
* mul
);
134 RGB2YUV (r
, g
, b
, y0
, u0
, v0
);
136 r
= GetRGB2(rgb
, width
, height
, x
, +boxw
, y
, +boxh
, 0) + GetRGB2(rgb
, width
, height
, x
, -boxw
, y
, -boxh
, 0) - GetRGB2(rgb
, width
, height
, x
, -boxw
, y
, +boxh
, 0) - GetRGB2(rgb
, width
, height
, x
, +boxw
, y
, -boxh
, 0);
137 g
= GetRGB2(rgb
, width
, height
, x
, +boxw
, y
, +boxh
, 1) + GetRGB2(rgb
, width
, height
, x
, -boxw
, y
, -boxh
, 1) - GetRGB2(rgb
, width
, height
, x
, -boxw
, y
, +boxh
, 1) - GetRGB2(rgb
, width
, height
, x
, +boxw
, y
, -boxh
, 1);
138 b
= GetRGB2(rgb
, width
, height
, x
, +boxw
, y
, +boxh
, 2) + GetRGB2(rgb
, width
, height
, x
, -boxw
, y
, -boxh
, 2) - GetRGB2(rgb
, width
, height
, x
, -boxw
, y
, +boxh
, 2) - GetRGB2(rgb
, width
, height
, x
, +boxw
, y
, -boxh
, 2);
139 r
= (int32_t) (r
* mul
);
140 g
= (int32_t) (g
* mul
);
141 b
= (int32_t) (b
* mul
);
142 RGB2YUV (r
, g
, b
, y1
, u1
, v1
);
144 *yuv
++ = (u0
+u1
) >> 1;
146 *yuv
++ = (v0
+v1
) >> 1;
150 r
= GetRGB(rgb
, width
, height
, x
, +boxw
, y
, +boxh
, 0) + GetRGB(rgb
, width
, height
, x
, -boxw
, y
, -boxh
, 0) - GetRGB(rgb
, width
, height
, x
, -boxw
, y
, +boxh
, 0) - GetRGB(rgb
, width
, height
, x
, +boxw
, y
, -boxh
, 0);
151 g
= GetRGB(rgb
, width
, height
, x
, +boxw
, y
, +boxh
, 1) + GetRGB(rgb
, width
, height
, x
, -boxw
, y
, -boxh
, 1) - GetRGB(rgb
, width
, height
, x
, -boxw
, y
, +boxh
, 1) - GetRGB(rgb
, width
, height
, x
, +boxw
, y
, -boxh
, 1);
152 b
= GetRGB(rgb
, width
, height
, x
, +boxw
, y
, +boxh
, 2) + GetRGB(rgb
, width
, height
, x
, -boxw
, y
, -boxh
, 2) - GetRGB(rgb
, width
, height
, x
, -boxw
, y
, +boxh
, 2) - GetRGB(rgb
, width
, height
, x
, +boxw
, y
, -boxh
, 2);
153 r
= (int32_t) (r
* mul
);
154 g
= (int32_t) (g
* mul
);
155 b
= (int32_t) (b
* mul
);
156 RGB2YUV (r
, g
, b
, y0
, u0
, v0
);
163 static int filter_get_image( mlt_frame
this, uint8_t **image
, mlt_image_format
*format
, int *width
, int *height
, int writable
)
166 int error
= mlt_frame_get_image( this, image
, format
, width
, height
, 1 );
167 short hori
= mlt_properties_get_int(MLT_FRAME_PROPERTIES( this ), "hori" );
168 short vert
= mlt_properties_get_int(MLT_FRAME_PROPERTIES( this ), "vert" );
170 // Only process if we have no error and a valid colour space
171 if ( error
== 0 && *format
== mlt_image_yuv422
)
173 double factor
= mlt_properties_get_double( MLT_FRAME_PROPERTIES( this ), "boxblur" );
176 int32_t *rgb
= mlt_pool_alloc (3 * *width
* h
* sizeof(int32_t));
177 PreCompute (*image
, rgb
, *width
, h
);
178 DoBoxBlur (*image
, rgb
, *width
, h
, (int) factor
*hori
, (int) factor
*vert
);
179 mlt_pool_release (rgb
);
185 /** Filter processing.
188 static mlt_frame
filter_process( mlt_filter
this, mlt_frame frame
)
190 // Get the starting blur level
191 double blur
= (double) mlt_properties_get_int( MLT_FILTER_PROPERTIES( this ), "start" );
192 short hori
= mlt_properties_get_int(MLT_FILTER_PROPERTIES( this ), "hori" );
193 short vert
= mlt_properties_get_int(MLT_FILTER_PROPERTIES( this ), "vert" );
195 // If there is an end adjust gain to the range
196 if ( mlt_properties_get( MLT_FILTER_PROPERTIES( this ), "end" ) != NULL
)
198 // Determine the time position of this frame in the transition duration
199 mlt_position in
= mlt_filter_get_in( this );
200 mlt_position out
= mlt_filter_get_out( this );
201 mlt_position time
= mlt_frame_get_position( frame
);
202 double position
= (double) ( time
- in
) / ( out
- in
+ 1.0 );
203 double end
= (double) mlt_properties_get_int( MLT_FILTER_PROPERTIES( this ), "end" );
204 blur
+= ( end
- blur
) * position
;
207 // Push the frame filter
208 mlt_properties_set_double( MLT_FRAME_PROPERTIES( frame
), "boxblur", blur
);
209 mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame
), "hori", hori
);
210 mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame
), "vert", vert
);
211 mlt_frame_push_get_image( frame
, filter_get_image
);
216 /** Constructor for the filter.
219 mlt_filter
filter_boxblur_init( char *arg
)
221 mlt_filter
this = mlt_filter_new( );
224 this->process
= filter_process
;
225 mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "start", arg
== NULL ?
"10" : arg
);
226 mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "hori", arg
== NULL ?
"1" : arg
);
227 mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "vert", arg
== NULL ?
"1" : arg
);