--- /dev/null
+/*
+ * filter_boxblur.c -- blur filter
+ * Author: Leny Grisel <leny.grisel@laposte.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * aint32_t with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "filter_boxblur.h"
+
+#include <framework/mlt_frame.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+
+void PreCompute(uint8_t *yuv, int32_t *rgb, unsigned int width, unsigned int height)
+{
+ register int x, y, z;
+ register int uneven = width % 2;
+ int w = (width - uneven ) / 2;
+ int yy, uu, vv;
+ int r, g, b;
+ int32_t pts[3];
+ for (y=0; y<height; y++)
+ {
+ for (x=0; x<w; x++)
+ {
+ uu = yuv[1];
+ vv = yuv[3];
+ yy = yuv[0];
+ YUV2RGB(yy, uu, vv, r, g, b);
+ pts[0] = r;
+ pts[1] = g;
+ pts[2] = b;
+ for (z = 0; z < 3; z++)
+ {
+ if (x>0) pts[z]+=rgb[-3];
+ if (y>0) pts[z]+=rgb[-(width*3)];
+ if (x>0 && y>0) pts[z]-=rgb[-((width+1)*3)];
+ *rgb++=pts[z];
+ }
+
+ yy = yuv[2];
+ YUV2RGB(yy, uu, vv, r, g, b);
+ pts[0] = r;
+ pts[1] = g;
+ pts[2] = b;
+ for (z = 0; z < 3; z++)
+ {
+ pts[z]+=rgb[-3];
+ if (y>0)
+ {
+ pts[z]+=rgb[-(width*3)];
+ pts[z]-=rgb[-((width+1)*3)];
+ }
+ *rgb++=pts[z];
+ }
+ yuv += 4;
+ }
+ if (uneven)
+ {
+ uu = yuv[1];
+ vv = yuv[3];
+ yy = yuv[0];
+ YUV2RGB(yy, uu, vv, r, g, b);
+ pts[0] = r;
+ pts[1] = g;
+ pts[2] = b;
+ for (z = 0; z < 3; z++)
+ {
+ pts[z]+=rgb[-3];
+ if (y>0)
+ {
+ pts[z]+=rgb[-(width*3)];
+ pts[z]-=rgb[-((width+1)*3)];
+ }
+ *rgb++=pts[z];
+ }
+ yuv += 2;
+ }
+ }
+}
+
+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)
+{
+ int xtheo = x * 2 + offsetx;
+ int ytheo = y + offsety;
+ if (xtheo < 0) xtheo = 0; else if (xtheo >= w) xtheo = w - 1;
+ if (ytheo < 0) ytheo = 0; else if (ytheo >= h) ytheo = h - 1;
+ return rgb[3*(xtheo+ytheo*w)+z];
+}
+
+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)
+{
+ int xtheo = x * 2 + 1 + offsetx;
+ int ytheo = y + offsety;
+ if (xtheo < 0) xtheo = 0; else if (xtheo >= w) xtheo = w - 1;
+ if (ytheo < 0) ytheo = 0; else if (ytheo >= h) ytheo = h - 1;
+ return rgb[3*(xtheo+ytheo*w)+z];
+}
+
+void DoBoxBlur(uint8_t *yuv, int32_t *rgb, unsigned int width, unsigned int height, unsigned int boxw, unsigned int boxh)
+{
+ register int x, y;
+ int32_t r, g, b;
+ register int uneven = width % 2;
+ register int y0, y1, u0, u1, v0, v1;
+ int w = (width - uneven ) / 2;
+ float mul = 1.f / ((boxw*2) * (boxh*2));
+
+ for (y = 0; y < height; y++)
+ {
+ for (x = 0; x < w; x++)
+ {
+ 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);
+ 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);
+ 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);
+ r = (int32_t) (r * mul);
+ g = (int32_t) (g * mul);
+ b = (int32_t) (b * mul);
+ RGB2YUV (r, g, b, y0, u0, v0);
+
+ 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);
+ 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);
+ 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);
+ r = (int32_t) (r * mul);
+ g = (int32_t) (g * mul);
+ b = (int32_t) (b * mul);
+ RGB2YUV (r, g, b, y1, u1, v1);
+ *yuv++ = y0;
+ *yuv++ = (u0+u1) >> 1;
+ *yuv++ = y1;
+ *yuv++ = (v0+v1) >> 1;
+ }
+ if (uneven)
+ {
+ 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);
+ 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);
+ 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);
+ r = (int32_t) (r * mul);
+ g = (int32_t) (g * mul);
+ b = (int32_t) (b * mul);
+ RGB2YUV (r, g, b, y0, u0, v0);
+ *yuv++ = mul * y0;
+ *yuv++ = mul * u0;
+ }
+ }
+}
+
+static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
+{
+ // Get the image
+ int error = mlt_frame_get_image( this, image, format, width, height, 1 );
+ short hori = mlt_properties_get_int(MLT_FRAME_PROPERTIES( this ), "hori" );
+ short vert = mlt_properties_get_int(MLT_FRAME_PROPERTIES( this ), "vert" );
+
+ // Only process if we have no error and a valid colour space
+ if ( error == 0 && *format == mlt_image_yuv422 )
+ {
+ double factor = mlt_properties_get_double( MLT_FRAME_PROPERTIES( this ), "boxblur" );
+ if (factor != 0) {
+ int h = *height + 1;
+ int32_t *rgb = mlt_pool_alloc (3 * *width * h * sizeof(int32_t));
+ PreCompute (*image, rgb, *width, h);
+ DoBoxBlur (*image, rgb, *width, h, (int) factor*hori, (int) factor*vert);
+ mlt_pool_release (rgb);
+ }
+ }
+ return error;
+}
+
+/** Filter processing.
+*/
+
+static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
+{
+ // Get the starting blur level
+ double blur = (double) mlt_properties_get_int( MLT_FILTER_PROPERTIES( this ), "start" );
+ short hori = mlt_properties_get_int(MLT_FILTER_PROPERTIES( this ), "hori" );
+ short vert = mlt_properties_get_int(MLT_FILTER_PROPERTIES( this ), "vert" );
+
+ // If there is an end adjust gain to the range
+ if ( mlt_properties_get( MLT_FILTER_PROPERTIES( this ), "end" ) != NULL )
+ {
+ // Determine the time position of this frame in the transition duration
+ mlt_position in = mlt_filter_get_in( this );
+ mlt_position out = mlt_filter_get_out( this );
+ mlt_position time = mlt_frame_get_position( frame );
+ double position = (double) ( time - in ) / ( out - in + 1.0 );
+ double end = (double) mlt_properties_get_int( MLT_FILTER_PROPERTIES( this ), "end" );
+ blur += ( end - blur ) * position;
+ }
+
+ // Push the frame filter
+ mlt_properties_set_double( MLT_FRAME_PROPERTIES( frame ), "boxblur", blur );
+ mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "hori", hori );
+ mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "vert", vert );
+ mlt_frame_push_get_image( frame, filter_get_image );
+
+ return frame;
+}
+
+/** Constructor for the filter.
+*/
+
+mlt_filter filter_boxblur_init( char *arg )
+{
+ mlt_filter this = mlt_filter_new( );
+ if ( this != NULL )
+ {
+ this->process = filter_process;
+ mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "start", arg == NULL ? "10" : arg);
+ mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "hori", arg == NULL ? "1" : arg);
+ mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "vert", arg == NULL ? "1" : arg);
+ }
+ return this;
+}
+
+
+
--- /dev/null
+/*
+ * wave.c -- wave filter
+ * Author: Leny Grisel <leny.grisel@laposte.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * aint32_t with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "filter_wave.h"
+
+#include <framework/mlt_frame.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+// this is a utility function used by DoWave below
+uint8_t getPoint(uint8_t *src, int w, int h, int x, int y, int z)
+{
+ if (x<0) x+=-((-x)%w)+w; else if (x>=w) x=x%w;
+ if (y<0) y+=-((-y)%h)+h; else if (y>=h) y=y%h;
+ return src[(x+y*w)*4+z];
+}
+
+// the main meat of the algorithm lies here
+void DoWave(uint8_t *src, int src_w, int src_h, uint8_t *dst, mlt_position position, int speed, int factor, int deformX, int deformY)
+{
+ register int x, y;
+ int decalY, decalX, z;
+ float amplitude, phase, pulsation;
+ register int uneven = src_w % 2;
+ int w = (src_w - uneven ) / 2;
+ amplitude = factor;
+ pulsation = 0.5 / factor; // smaller means bigger period
+ phase = position * pulsation * speed / 10; // smaller means longer
+ for (y=0;y<src_h;y++) {
+ decalX = deformX ? sin(pulsation * y + phase) * amplitude : 0;
+ for (x=0;x<w;x++) {
+ decalY = deformY ? sin(pulsation * x * 2 + phase) * amplitude : 0;
+ for (z=0; z<4; z++)
+ *dst++ = getPoint(src, w, src_h, (x+decalX), (y+decalY), z);
+ }
+ if (uneven) {
+ decalY = sin(pulsation * x * 2 + phase) * amplitude;
+ for (z=0; z<2; z++)
+ *dst++ = getPoint(src, w, src_h, (x+decalX), (y+decalY), z);
+ }
+ }
+}
+
+static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
+{
+ // Get the image
+ int error = mlt_frame_get_image( this, image, format, width, height, 1 );
+ mlt_position position = mlt_frame_get_position( this );
+
+ // Only process if we have no error and a valid colour space
+ if ( error == 0 && *format == mlt_image_yuv422 )
+ {
+ double factor = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "wave" );
+ int speed = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "speed" );
+ int deformX = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "deformX" );
+ int deformY = mlt_properties_get_int( MLT_FRAME_PROPERTIES( this ), "deformY" );
+ if (factor != 0) {
+ int image_size = *width * (*height + 1) * 2;
+ int8_t *dest = mlt_pool_alloc (image_size);
+ DoWave(*image, *width, (*height + 1), dest, position, speed, factor, deformX, deformY);
+ memcpy(*image, dest, image_size);
+ mlt_pool_release(dest);
+ }
+ }
+
+ return error;
+}
+
+/** Filter processing.
+*/
+
+static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
+{
+ // Get the starting wave level
+ double wave = mlt_properties_get_double( MLT_FILTER_PROPERTIES( this ), "start" );
+ int speed = mlt_properties_get_int( MLT_FILTER_PROPERTIES( this ), "speed" );
+ int deformX = mlt_properties_get_int( MLT_FILTER_PROPERTIES( this ), "deformX" );
+ int deformY = mlt_properties_get_int( MLT_FILTER_PROPERTIES( this ), "deformY" );
+
+ // If there is an end adjust gain to the range
+ if ( mlt_properties_get( MLT_FILTER_PROPERTIES( this ), "end" ) != NULL )
+ {
+ // Determine the time position of this frame in the transition duration
+ mlt_position in = mlt_filter_get_in( this );
+ mlt_position out = mlt_filter_get_out( this );
+ mlt_position time = mlt_frame_get_position( frame );
+ double position = ( double )( time - in ) / ( double )( out - in + 1 );
+ double end = fabs( mlt_properties_get_double( MLT_FILTER_PROPERTIES( this ), "end" ) );
+ wave += ( end - wave ) * position;
+ }
+
+ // Push the frame filter
+ mlt_properties_set_double( MLT_FRAME_PROPERTIES( frame ), "wave", wave );
+ mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "speed", speed );
+ mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "deformX", deformX );
+ mlt_properties_set_int( MLT_FRAME_PROPERTIES( frame ), "deformY", deformY );
+ mlt_frame_push_get_image( frame, filter_get_image );
+
+ return frame;
+}
+
+/** Constructor for the filter.
+*/
+
+mlt_filter filter_wave_init( char *arg )
+{
+ mlt_filter this = mlt_filter_new( );
+ if ( this != NULL )
+ {
+ this->process = filter_process;
+ mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "start", arg == NULL ? "10" : arg);
+ mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "speed", arg == NULL ? "5" : arg);
+ mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "deformX", arg == NULL ? "1" : arg);
+ mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "deformY", arg == NULL ? "1" : arg);
+ }
+ return this;
+}
+
+
+