]> git.sesse.net Git - mlt/commitdiff
added effectv module with BurningTV filter provided by Stephane Fillod
authorddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
Sun, 10 Jun 2007 21:34:57 +0000 (21:34 +0000)
committerddennedy <ddennedy@d19143bc-622f-0410-bfdd-b5b2a6649095>
Sun, 10 Jun 2007 21:34:57 +0000 (21:34 +0000)
git-svn-id: https://mlt.svn.sourceforge.net/svnroot/mlt/trunk/mlt@987 d19143bc-622f-0410-bfdd-b5b2a6649095

src/modules/effectv/Makefile [new file with mode: 0644]
src/modules/effectv/configure [new file with mode: 0755]
src/modules/effectv/factory.c [new file with mode: 0644]
src/modules/effectv/filter_burn.c [new file with mode: 0644]
src/modules/effectv/filter_burn.h [new file with mode: 0644]
src/modules/effectv/gpl [new file with mode: 0644]
src/modules/effectv/image.c [new file with mode: 0644]
src/modules/effectv/utils.c [new file with mode: 0644]
src/modules/effectv/utils.h [new file with mode: 0644]

diff --git a/src/modules/effectv/Makefile b/src/modules/effectv/Makefile
new file mode 100644 (file)
index 0000000..a3ca6bc
--- /dev/null
@@ -0,0 +1,35 @@
+include ../../../config.mak
+
+TARGET = ../libmlteffectv$(LIBSUF)
+
+OBJS = factory.o \
+          filter_burn.o \
+          image.o \
+          utils.o
+
+CFLAGS += -I../..
+
+LDFLAGS+=-L../../framework -lmlt
+
+SRCS := $(OBJS:.o=.c)
+
+all:   $(TARGET)
+
+$(TARGET): $(OBJS)
+               $(CC) $(SHFLAGS) -o $@ $(OBJS) $(LDFLAGS)
+
+depend:        $(SRCS)
+               $(CC) -MM $(CFLAGS) $^ 1>.depend
+
+distclean:     clean
+               rm -f .depend
+
+clean: 
+               rm -f $(OBJS) $(TARGET) 
+
+install: all
+       install -m 755 $(TARGET) "$(DESTDIR)$(prefix)/share/mlt/modules"
+
+ifneq ($(wildcard .depend),)
+include .depend
+endif
diff --git a/src/modules/effectv/configure b/src/modules/effectv/configure
new file mode 100755 (executable)
index 0000000..25f1d82
--- /dev/null
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+if [ "$help" != "1" ]
+then
+
+cat << EOF >> ../producers.dat
+EOF
+
+cat << EOF >> ../filters.dat
+BurningTV      libmlteffectv$LIBSUF
+EOF
+
+cat << EOF >> ../transitions.dat
+EOF
+
+cat << EOF >> ../consumers.dat
+EOF
+
+fi
diff --git a/src/modules/effectv/factory.c b/src/modules/effectv/factory.c
new file mode 100644 (file)
index 0000000..06320d8
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * factory.c -- the factory method interfaces
+ * Copyright (C) 2007 Stephane Fillod
+ *
+ * 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
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <string.h>
+
+#include "filter_burn.h"
+
+void *mlt_create_producer( char *id, void *arg )
+{
+       return NULL;
+}
+
+void *mlt_create_filter( char *id, void *arg )
+{
+       if ( !strcmp( id, "BurningTV" ) )
+               return filter_burn_init( arg );
+       return NULL;
+}
+
+void *mlt_create_transition( char *id, void *arg )
+{
+       return NULL;
+}
+
+void *mlt_create_consumer( char *id, void *arg )
+{
+       return NULL;
+}
diff --git a/src/modules/effectv/filter_burn.c b/src/modules/effectv/filter_burn.c
new file mode 100644 (file)
index 0000000..d5a579b
--- /dev/null
@@ -0,0 +1,214 @@
+/*
+ * filter_burn.c -- burning filter
+ * Copyright (C) 2007 Stephane Fillod
+ *
+ * Filter taken from EffecTV - Realtime Digital Video Effector
+ * Copyright (C) 2001-2006 FUKUCHI Kentaro
+ *
+ * BurningTV - burns incoming objects.
+ * Copyright (C) 2001-2002 FUKUCHI Kentaro
+ *
+ * Fire routine is taken from Frank Jan Sorensen's demo program.
+ *
+ *
+ * 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
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "filter_burn.h"
+
+#include <framework/mlt_frame.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include "utils.h"
+
+
+#define MaxColor 120
+#define Decay 15
+#define MAGIC_THRESHOLD "50"
+
+static RGB32 palette[256];
+
+/* FIXME: endianess? */
+static void makePalette(void)
+{
+       int i, r, g, b;
+
+       for(i=0; i<MaxColor; i++) {
+               HSItoRGB(4.6-1.5*i/MaxColor, (double)i/MaxColor, (double)i/MaxColor, &r, &g, &b);
+               palette[i] = ((r<<16)|(g<<8)|b) & 0xfefeff;
+       }
+       for(i=MaxColor; i<256; i++) {
+               if(r<255)r++;if(r<255)r++;if(r<255)r++;
+               if(g<255)g++;
+               if(g<255)g++;
+               if(b<255)b++;
+               if(b<255)b++;
+               palette[i] = ((r<<16)|(g<<8)|b) & 0xfefeff;
+       }
+}
+
+static int filter_get_image( mlt_frame this, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable )
+{
+       RGB32 *background;
+       unsigned char *diff;
+       unsigned char *buffer;
+
+       // Get the filter
+       mlt_filter filter = mlt_frame_pop_service( this );
+
+       // Get the image
+       int error = mlt_frame_get_image( this, image, format, width, height, 1 );
+
+       // Only process if we have no error and a valid colour space
+       if ( error == 0 && *format == mlt_image_yuv422 )
+       {
+               // Get the "Burn the foreground" value
+               int burn_foreground = mlt_properties_get_int( MLT_FILTER_PROPERTIES( filter ), "foreground" );
+               int y_threshold = image_set_threshold_y(
+                               mlt_properties_get_int( MLT_FILTER_PROPERTIES( filter ), "threshold" ));
+
+               // We'll process pixel by pixel
+               int x = 0;
+               int y = 0;
+               int i;
+
+               int video_width = *width;
+               int video_height = *height;
+               int video_area = video_width * video_height;
+               // We need to create a new frame as this effect modifies the input
+               RGB32 *dest = mlt_pool_alloc( video_area * sizeof(RGB32) );
+               RGB32 *src = (RGB32*)dest;
+
+               unsigned char v, w;
+               RGB32 a, b;
+
+               mlt_convert_yuv422_to_rgb24a(*image, (uint8_t *)dest, video_area);
+
+
+               diff = mlt_properties_get_data( MLT_FILTER_PROPERTIES( filter ), 
+                                               "_diff", NULL );
+               if (diff == NULL)
+               {
+                       diff = mlt_pool_alloc(video_area*sizeof(unsigned char));
+                       mlt_properties_set_data( MLT_FILTER_PROPERTIES( filter ), "_diff", 
+                                       diff, video_area*sizeof(unsigned char), mlt_pool_release, NULL );
+               }
+
+               buffer = mlt_properties_get_data( MLT_FILTER_PROPERTIES( filter ), 
+                                               "_buffer", NULL );
+               if (buffer == NULL)
+               {
+                       buffer = mlt_pool_alloc(video_area*sizeof(unsigned char));
+                       memset(buffer, 0, video_area*sizeof(unsigned char));
+                       mlt_properties_set_data( MLT_FILTER_PROPERTIES( filter ), "_buffer", 
+                                       buffer, video_area*sizeof(unsigned char), mlt_pool_release, NULL );
+               }
+
+
+               if (burn_foreground == 1) {
+                       /* to burn the foreground, we need a background */
+                       background = mlt_properties_get_data( MLT_FILTER_PROPERTIES( filter ), 
+                                               "_background", NULL );
+                       if (background == NULL)
+                       {
+                               background = mlt_pool_alloc(video_area*sizeof(RGB32));
+                               image_bgset_y(background, src, video_area, y_threshold);
+                               mlt_properties_set_data( MLT_FILTER_PROPERTIES( filter ), "_background", 
+                                       background, video_area*sizeof(RGB32), mlt_pool_release, NULL );
+                       }
+               }
+
+               if (burn_foreground == 1) {
+                       image_bgsubtract_y(diff, background, src, video_area, y_threshold);
+               } else {
+                       /* default */
+                       image_y_over(diff, src, video_area, y_threshold);
+               }
+       
+               for(x=1; x<video_width-1; x++) {
+                       v = 0;
+                       for(y=0; y<video_height-1; y++) {
+                               w = diff[y*video_width+x];
+                               buffer[y*video_width+x] |= v ^ w;
+                               v = w;
+                       }
+               }
+               for(x=1; x<video_width-1; x++) {
+                       i = video_width + x;
+                       for(y=1; y<video_height; y++) {
+                               v = buffer[i];
+                               if(v<Decay)
+                                       buffer[i-video_width] = 0;
+                               else
+                                       buffer[i-video_width+fastrand()%3-1] = v - (fastrand()&Decay);
+                               i += video_width;
+                       }
+               }
+       
+               i = 1;
+               for(y=0; y<video_height; y++) {
+                       for(x=1; x<video_width-1; x++) {
+                               /* FIXME: endianess? */
+                               a = (src[i] & 0xfefeff) + palette[buffer[i]];
+                               b = a & 0x1010100;
+                               dest[i] = a | (b - (b >> 8));
+                               i++;
+                       }
+                       i += 2;
+               }
+
+               mlt_convert_rgb24a_to_yuv422((uint8_t *)dest, *width, *height, *width * sizeof(RGB32), 
+                               *image, NULL );
+
+               mlt_pool_release(dest);
+       }
+
+       return error;
+}
+
+/** Filter processing.
+*/
+
+static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
+{
+       // Push the frame filter
+       mlt_frame_push_service( frame, this );
+       mlt_frame_push_get_image( frame, filter_get_image );
+
+       return frame;
+}
+
+/** Constructor for the filter.
+*/
+
+mlt_filter filter_burn_init( char *arg )
+{
+       mlt_filter this = mlt_filter_new( );
+       if ( this != NULL )
+       {
+               this->process = filter_process;
+               mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "foreground", "0" );
+               mlt_properties_set( MLT_FILTER_PROPERTIES( this ), "threshold", MAGIC_THRESHOLD );
+       }
+       if (!palette[128])
+       {
+               makePalette();
+       }
+       return this;
+}
+
diff --git a/src/modules/effectv/filter_burn.h b/src/modules/effectv/filter_burn.h
new file mode 100644 (file)
index 0000000..8c8e731
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * filter_brun.h -- burning filter
+ * Copyright (C) 2007 Stephane Fillod
+ *
+ * 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
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _FILTER_BURN_H_
+#define _FILTER_BURN_H_
+
+#include <framework/mlt_filter.h>
+
+extern mlt_filter filter_burn_init( char *arg );
+
+#endif
diff --git a/src/modules/effectv/gpl b/src/modules/effectv/gpl
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/modules/effectv/image.c b/src/modules/effectv/image.c
new file mode 100644 (file)
index 0000000..dbd848f
--- /dev/null
@@ -0,0 +1,307 @@
+/*
+ * EffecTV - Realtime Digital Video Effector
+ * Copyright (C) 2001-2006 FUKUCHI Kentaro
+ *
+ * image.c: utilities for image processing.
+ *
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include "utils.h"
+
+
+/*
+ * Collection of background subtraction functions
+ */
+
+/* checks only fake-Y value */
+/* In these function Y value is treated as R*2+G*4+B. */
+
+int image_set_threshold_y(int threshold)
+{
+       int y_threshold = threshold * 7; /* fake-Y value is timed by 7 */
+
+       return y_threshold;
+}
+
+void image_bgset_y(RGB32 *background, const RGB32 *src, int video_area, int y_threshold)
+{
+       int i;
+       int R, G, B;
+       const RGB32 *p;
+       short *q;
+
+       p = src;
+       q = (short *)background;
+       for(i=0; i<video_area; i++) {
+               /* FIXME: endianess */
+
+               R = ((*p)&0xff0000)>>(16-1);
+               G = ((*p)&0xff00)>>(8-2);
+               B = (*p)&0xff;
+               *q = (short)(R + G + B);
+               p++;
+               q++;
+       }
+}
+
+void image_bgsubtract_y(unsigned char *diff, const RGB32 *background, const RGB32 *src, int video_area, int y_threshold)
+{
+       int i;
+       int R, G, B;
+       const RGB32 *p;
+       short *q;
+       unsigned char *r;
+       int v;
+
+       p = src;
+       q = (short *)background;
+       r = diff;
+       for(i=0; i<video_area; i++) {
+               /* FIXME: endianess */
+
+               R = ((*p)&0xff0000)>>(16-1);
+               G = ((*p)&0xff00)>>(8-2);
+               B = (*p)&0xff;
+               v = (R + G + B) - (int)(*q);
+               *r = ((v + y_threshold)>>24) | ((y_threshold - v)>>24);
+
+               p++;
+               q++;
+               r++;
+       }
+
+/* The origin of subtraction function is;
+ * diff(src, dest) = (abs(src - dest) > threshold) ? 0xff : 0;
+ *
+ * This functions is transformed to;
+ * (threshold > (src - dest) > -threshold) ? 0 : 0xff;
+ *
+ * (v + threshold)>>24 is 0xff when v is less than -threshold.
+ * (v - threshold)>>24 is 0xff when v is less than threshold.
+ * So, ((v + threshold)>>24) | ((threshold - v)>>24) will become 0xff when
+ * abs(src - dest) > threshold.
+ */
+}
+
+/* Background image is refreshed every frame */
+void image_bgsubtract_update_y(unsigned char *diff, RGB32 *background, const RGB32 *src, int video_area, int y_threshold)
+{
+       int i;
+       int R, G, B;
+       const RGB32 *p;
+       short *q;
+       unsigned char *r;
+       int v;
+
+       p = src;
+       q = (short *)background;
+       r = diff;
+       for(i=0; i<video_area; i++) {
+               /* FIXME: endianess */
+
+               R = ((*p)&0xff0000)>>(16-1);
+               G = ((*p)&0xff00)>>(8-2);
+               B = (*p)&0xff;
+               v = (R + G + B) - (int)(*q);
+               *q = (short)(R + G + B);
+               *r = ((v + y_threshold)>>24) | ((y_threshold - v)>>24);
+
+               p++;
+               q++;
+               r++;
+       }
+}
+
+/* checks each RGB value */
+
+/* The range of r, g, b are [0..7] */
+RGB32 image_set_threshold_RGB(int r, int g, int b)
+{
+       unsigned char R, G, B;
+       RGB32 rgb_threshold;
+
+       R = G = B = 0xff;
+       R = R<<r;
+       G = G<<g;
+       B = B<<b;
+       rgb_threshold = (RGB32)(R<<16 | G<<8 | B);
+
+       return rgb_threshold;
+}
+
+void image_bgset_RGB(RGB32 *background, const RGB32 *src, int video_area)
+{
+       int i;
+       RGB32 *p;
+
+       p = background;
+       for(i=0; i<video_area; i++) {
+               *p++ = (*src++) & 0xfefefe;
+       }
+}
+
+void image_bgsubtract_RGB(unsigned char *diff, const RGB32 *background, const RGB32 *src, int video_area, RGB32 rgb_threshold)
+{
+       int i;
+       const RGB32 *p, *q;
+       unsigned a, b;
+       unsigned char *r;
+
+       p = src;
+       q = background;
+       r = diff;
+       for(i=0; i<video_area; i++) {
+               a = (*p++)|0x1010100;
+               b = *q++;
+               a = a - b;
+               b = a & 0x1010100;
+               b = b - (b>>8);
+               b = b ^ 0xffffff;
+               a = a ^ b;
+               a = a & rgb_threshold;
+               *r++ = (0 - a)>>24;
+       }
+}
+
+void image_bgsubtract_update_RGB(unsigned char *diff, RGB32 *background, const RGB32 *src, int video_area, RGB32 rgb_threshold)
+{
+       int i;
+       const RGB32 *p;
+       RGB32 *q;
+       unsigned a, b;
+       unsigned char *r;
+
+       p = src;
+       q = background;
+       r = diff;
+       for(i=0; i<video_area; i++) {
+               a = *p|0x1010100;
+               b = *q&0xfefefe;
+               *q++ = *p++;
+               a = a - b;
+               b = a & 0x1010100;
+               b = b - (b>>8);
+               b = b ^ 0xffffff;
+               a = a ^ b;
+               a = a & rgb_threshold;
+               *r++ = (0 - a)>>24;
+       }
+}
+
+/* noise filter for subtracted image. */
+void image_diff_filter(unsigned char *diff2, const unsigned char *diff, int width, int height)
+{
+       int x, y;
+       const unsigned char *src;
+       unsigned char *dest;
+       unsigned int count;
+       unsigned int sum1, sum2, sum3;
+
+       src = diff;
+       dest = diff2 + width +1;
+       for(y=1; y<height-1; y++) {
+               sum1 = src[0] + src[width] + src[width*2];
+               sum2 = src[1] + src[width+1] + src[width*2+1];
+               src += 2;
+               for(x=1; x<width-1; x++) {
+                       sum3 = src[0] + src[width] + src[width*2];
+                       count = sum1 + sum2 + sum3;
+                       sum1 = sum2;
+                       sum2 = sum3;
+                       *dest++ = (0xff*3 - count)>>24;
+                       src++;
+               }
+               dest += 2;
+       }
+}
+
+/* Y value filters */
+void image_y_over(unsigned char *diff, const RGB32 *src, int video_area, int y_threshold)
+{
+       int i;
+       int R, G, B, v;
+       unsigned char *p = diff;
+
+       for(i = video_area; i>0; i--) {
+               R = ((*src)&0xff0000)>>(16-1);
+               G = ((*src)&0xff00)>>(8-2);
+               B = (*src)&0xff;
+               v = y_threshold - (R + G + B);
+               *p = (unsigned char)(v>>24);
+               src++;
+               p++;
+       }
+}
+
+void image_y_under(unsigned char *diff, const RGB32 *src, int video_area, int y_threshold)
+{
+       int i;
+       int R, G, B, v;
+       unsigned char *p = diff;
+
+       for(i = video_area; i>0; i--) {
+               R = ((*src)&0xff0000)>>(16-1);
+               G = ((*src)&0xff00)>>(8-2);
+               B = (*src)&0xff;
+               v = (R + G + B) - y_threshold;
+               *p = (unsigned char)(v>>24);
+               src++;
+               p++;
+       }
+}
+
+/* tiny edge detection */
+void image_edge(unsigned char *diff2, const RGB32 *src, int width, int height, int y_threshold)
+{
+       int x, y;
+       unsigned char *p, *q;
+       int r, g, b;
+       int ar, ag, ab;
+       int w;
+
+       p = (unsigned char *)src;
+       q = diff2;
+       w = width * sizeof(RGB32);
+
+       for(y=0; y<height - 1; y++) {
+               for(x=0; x<width - 1; x++) {
+                       b = p[0];
+                       g = p[1];
+                       r = p[2];
+                       ab = abs(b - p[4]);
+                       ag = abs(g - p[5]);
+                       ar = abs(r - p[6]);
+                       ab += abs(b - p[w]);
+                       ag += abs(g - p[w+1]);
+                       ar += abs(r - p[w+2]);
+                       b = ab+ag+ar;
+                       if(b > y_threshold) {
+                               *q = 255;
+                       } else {
+                               *q = 0;
+                       }
+                       q++;
+                       p += 4;
+               }
+               p += 4;
+               *q++ = 0;
+       }
+       memset(q, 0, width);
+}
+
+/* horizontal flipping */
+void image_hflip(const RGB32 *src, RGB32 *dest, int width, int height)
+{
+       int x, y;
+
+       src += width - 1;
+       for(y=0; y<height; y++) {
+               for(x=0; x<width; x++) {
+                       *dest++ = *src--;
+               }
+               src += width * 2;
+       }
+}
+
diff --git a/src/modules/effectv/utils.c b/src/modules/effectv/utils.c
new file mode 100644 (file)
index 0000000..d551844
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * EffecTV - Realtime Digital Video Effector
+ * Copyright (C) 2001-2006 FUKUCHI Kentaro
+ *
+ * utils.c: utilities
+ *
+ */
+
+#include <math.h>
+#include "utils.h"
+
+/*
+ * HSI color system utilities
+ */
+static int itrunc(double f)
+{
+       int i;
+
+       i=(int)f;
+       if(i<0)i=0;
+       if(i>255)i=255;
+       return i;
+}
+
+void HSItoRGB(double H, double S, double I, int *r, int *g, int *b)
+{
+       double T,Rv,Gv,Bv;
+
+       Rv=1+S*sin(H-2*M_PI/3);
+       Gv=1+S*sin(H);
+       Bv=1+S*sin(H+2*M_PI/3);
+       T=255.999*I/2;
+       *r=itrunc(Rv*T);
+       *g=itrunc(Gv*T);
+       *b=itrunc(Bv*T);
+}
+
+/*
+ * fastrand - fast fake random number generator
+ * Warning: The low-order bits of numbers generated by fastrand()
+ *          are bad as random numbers. For example, fastrand()%4
+ *          generates 1,2,3,0,1,2,3,0...
+ *          You should use high-order bits.
+ */
+unsigned int fastrand_val;
+
+unsigned int fastrand(void)
+{
+       return (fastrand_val=fastrand_val*1103515245+12345);
+}
+
+void fastsrand(unsigned int seed)
+{
+       fastrand_val = seed;
+}
diff --git a/src/modules/effectv/utils.h b/src/modules/effectv/utils.h
new file mode 100644 (file)
index 0000000..284db0f
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * EffecTV - Realtime Digital Video Effector
+ * Copyright (C) 2001-2006 FUKUCHI Kentaro
+ *
+ * utils.h: header file for utils
+ *
+ */
+
+#ifndef __UTILS_H__
+#define __UTILS_H__
+
+#include <inttypes.h>
+
+typedef uint32_t RGB32;
+
+/* DEFINE's by nullset@dookie.net */
+#define RED(n)  ((n>>16) & 0x000000FF)
+#define GREEN(n) ((n>>8) & 0x000000FF)
+#define BLUE(n)  ((n>>0) & 0x000000FF)
+#define RGB(r,g,b) ((0<<24) + (r<<16) + (g <<8) + (b))
+#define INTENSITY(n)   ( ( (RED(n)+GREEN(n)+BLUE(n))/3))
+
+/* utils.c */
+void HSItoRGB(double H, double S, double I, int *r, int *g, int *b);
+
+extern unsigned int fastrand_val;
+unsigned int fastrand(void);
+void fastsrand(unsigned int);
+#define inline_fastrand() (fastrand_val=fastrand_val*1103515245+12345)
+
+/* image.c */
+int image_set_threshold_y(int threshold);
+void image_bgset_y(RGB32 *background, const RGB32 *src, int video_area, int y_threshold);
+void image_bgsubtract_y(unsigned char *diff, const RGB32 *background, const RGB32 *src, int video_area, int y_threshold);
+void image_bgsubtract_update_y(unsigned char *diff, RGB32 *background, const RGB32 *src, int video_area, int y_threshold);
+RGB32 image_set_threshold_RGB(int r, int g, int b);
+void image_bgset_RGB(RGB32 *background, const RGB32 *src, int video_area);
+void image_bgsubtract_RGB(unsigned char *diff, const RGB32 *background, const RGB32 *src, int video_area, RGB32 rgb_threshold);
+void image_bgsubtract_update_RGB(unsigned char *diff, RGB32 *background, const RGB32 *src, int video_area, RGB32 rgb_threshold);
+void image_diff_filter(unsigned char *diff2, const unsigned char *diff, int width, int height);
+void image_y_over(unsigned char *diff, const RGB32 *src, int video_area, int y_threshold);
+void image_y_under(unsigned char *diff, const RGB32 *src, int video_area, int y_threshold);
+void image_edge(unsigned char *diff2, const RGB32 *src, int width, int height, int y_threshold);
+void image_hflip(const RGB32 *src, RGB32 *dest, int width, int height);
+
+#endif /* __UTILS_H__ */