2 * filter_boxblur.c -- blur filter
3 * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
4 * Author: Leny Grisel <leny.grisel@laposte.net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program 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
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * aint32_t with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 #include "filter_boxblur.h"
23 #include <framework/mlt_frame.h>
30 static void PreCompute(uint8_t *yuv
, int32_t *rgb
, unsigned int width
, unsigned int height
)
33 register int uneven
= width
% 2;
34 int w
= (width
- uneven
) / 2;
38 for (y
=0; y
<height
; y
++)
45 YUV2RGB(yy
, uu
, vv
, r
, g
, b
);
49 for (z
= 0; z
< 3; z
++)
51 if (x
>0) pts
[z
]+=rgb
[-3];
52 if (y
>0) pts
[z
]+=rgb
[-(width
*3)];
53 if (x
>0 && y
>0) pts
[z
]-=rgb
[-((width
+1)*3)];
58 YUV2RGB(yy
, uu
, vv
, r
, g
, b
);
62 for (z
= 0; z
< 3; z
++)
67 pts
[z
]+=rgb
[-(width
*3)];
68 pts
[z
]-=rgb
[-((width
+1)*3)];
79 YUV2RGB(yy
, uu
, vv
, r
, g
, b
);
83 for (z
= 0; z
< 3; z
++)
88 pts
[z
]+=rgb
[-(width
*3)];
89 pts
[z
]-=rgb
[-((width
+1)*3)];
98 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
)
100 int xtheo
= x
* 2 + offsetx
;
101 int ytheo
= y
+ offsety
;
102 if (xtheo
< 0) xtheo
= 0; else if (xtheo
>= w
) xtheo
= w
- 1;
103 if (ytheo
< 0) ytheo
= 0; else if (ytheo
>= h
) ytheo
= h
- 1;
104 return rgb
[3*(xtheo
+ytheo
*w
)+z
];
107 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
)
109 int xtheo
= x
* 2 + 1 + offsetx
;
110 int ytheo
= y
+ offsety
;
111 if (xtheo
< 0) xtheo
= 0; else if (xtheo
>= w
) xtheo
= w
- 1;
112 if (ytheo
< 0) ytheo
= 0; else if (ytheo
>= h
) ytheo
= h
- 1;
113 return rgb
[3*(xtheo
+ytheo
*w
)+z
];
116 static void DoBoxBlur(uint8_t *yuv
, int32_t *rgb
, unsigned int width
, unsigned int height
, unsigned int boxw
, unsigned int boxh
)
120 register int uneven
= width
% 2;
121 register int y0
, y1
, u0
, u1
, v0
, v1
;
122 int w
= (width
- uneven
) / 2;
123 float mul
= 1.f
/ ((boxw
*2) * (boxh
*2));
125 for (y
= 0; y
< height
; y
++)
127 for (x
= 0; x
< w
; x
++)
129 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);
130 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);
131 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);
132 r
= (int32_t) (r
* mul
);
133 g
= (int32_t) (g
* mul
);
134 b
= (int32_t) (b
* mul
);
135 RGB2YUV (r
, g
, b
, y0
, u0
, v0
);
137 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);
138 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);
139 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);
140 r
= (int32_t) (r
* mul
);
141 g
= (int32_t) (g
* mul
);
142 b
= (int32_t) (b
* mul
);
143 RGB2YUV (r
, g
, b
, y1
, u1
, v1
);
145 *yuv
++ = (u0
+u1
) >> 1;
147 *yuv
++ = (v0
+v1
) >> 1;
151 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);
152 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);
153 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);
154 r
= (int32_t) (r
* mul
);
155 g
= (int32_t) (g
* mul
);
156 b
= (int32_t) (b
* mul
);
157 RGB2YUV (r
, g
, b
, y0
, u0
, v0
);
164 static int filter_get_image( mlt_frame
this, uint8_t **image
, mlt_image_format
*format
, int *width
, int *height
, int writable
)
167 int error
= mlt_frame_get_image( this, image
, format
, width
, height
, 1 );
168 short hori
= mlt_properties_get_int(MLT_FRAME_PROPERTIES( this ), "hori" );
169 short vert
= mlt_properties_get_int(MLT_FRAME_PROPERTIES( this ), "vert" );
171 // Only process if we have no error and a valid colour space
172 if ( error
== 0 && *format
== mlt_image_yuv422
)
174 double factor
= mlt_properties_get_double( MLT_FRAME_PROPERTIES( this ), "boxblur" );
177 int32_t *rgb
= mlt_pool_alloc (3 * *width
* h
* sizeof(int32_t));
178 PreCompute (*image
, rgb
, *width
, h
);
179 DoBoxBlur (*image
, rgb
, *width
, h
, (int) factor
*hori
, (int) factor
*vert
);
180 mlt_pool_release (rgb
);
186 /** Filter processing.
189 static mlt_frame
filter_process( mlt_filter
this, mlt_frame frame
)
191 // Get the starting blur level
192 double blur
= (double) mlt_properties_get_int( MLT_FILTER_PROPERTIES( this ), "start" );
193 short hori
= mlt_properties_get_int(MLT_FILTER_PROPERTIES( this ), "hori" );
194 short vert
= mlt_properties_get_int(MLT_FILTER_PROPERTIES( this ), "vert" );
196 // If there is an end adjust gain to the range
197 if ( mlt_properties_get( MLT_FILTER_PROPERTIES( this ), "end" ) != NULL
)
199 // Determine the time position of this frame in the transition duration
200 mlt_position in
= mlt_filter_get_in( this );
201 mlt_position out
= mlt_filter_get_out( this );
202 mlt_position time
= mlt_frame_get_position( frame
);
203 double position
= (double) ( time
- in
) / ( out
- in
+ 1.0 );
204 double end
= (double) mlt_properties_get_int( MLT_FILTER_PROPERTIES( this ), "end" );
205 blur
+= ( end
- blur
) * position
;
208 // Push the frame filter
209 mlt_properties_set_double( MLT_FRAME_PROPERTIES( frame
), "boxblur", blur
);
210 mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame
), "hori", hori
);
211 mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame
), "vert", vert
);
212 mlt_frame_push_get_image( frame
, filter_get_image
);
217 /** Constructor for the filter.
220 mlt_filter
filter_boxblur_init( char *arg
)
222 mlt_filter
this = mlt_filter_new( );
225 this->process
= filter_process
;
226 mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "start", arg
== NULL ?
"10" : arg
);
227 mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "hori", arg
== NULL ?
"1" : arg
);
228 mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "vert", arg
== NULL ?
"1" : arg
);