diff --git a/veejay-current/libvje/Makefile.am b/veejay-current/libvje/Makefile.am index 850b7d62..86539596 100644 --- a/veejay-current/libvje/Makefile.am +++ b/veejay-current/libvje/Makefile.am @@ -36,7 +36,7 @@ libvje_la_SOURCES = vj-effect.c vj-effman.c effects/common.c \ effects/contrast.c effects/motionblur.c effects/sinoids.c effects/average.c \ effects/ripple.c effects/water.c effects/noisepencil.c effects/bathroom.c effects/slice.c \ effects/crosspixel.c effects/morphology.c effects/ghost.c effects/blob.c effects/boids.c effects/nervous.c \ - effects/cartonize.c effects/tripplicity.c effects/neighbours.c + effects/cartonize.c effects/tripplicity.c effects/neighbours.c effects/neighbours2.c effects/neighbours3.c effects/neighbours4.c effects/neighbours5.c libvje_la_LDFLAGS = $(VJE_ALL_LIB_OPTS) \ diff --git a/veejay-current/libvje/effects/neighbours.c b/veejay-current/libvje/effects/neighbours.c index 147a081b..7044f50a 100644 --- a/veejay-current/libvje/effects/neighbours.c +++ b/veejay-current/libvje/effects/neighbours.c @@ -38,7 +38,7 @@ vj_effect *neighbours_init(int w, int h) ve->defaults[0] = 4; ve->defaults[1] = 4; ve->defaults[2] = 0; - ve->description = "Artistic Filter (Oilpainting, non RT)"; + ve->description = "Artistic Filter (Oilpainting, acc. add )"; ve->sub_format = 1; ve->extra_frame = 0; ve->has_user = 0; @@ -125,7 +125,7 @@ static inline uint8_t evaluate_pixel( } } if( peak_value < 16) - return 16; + return image[ y * w + x]; return( (uint8_t) ( y_map[ peak_index] / peak_value )); } @@ -208,6 +208,7 @@ static inline pixel_t evaluate_pixel_c( } + void neighbours_apply( VJFrame *frame, int width, int height, int brush_size, int intensity_level, int mode ) { int x,y; diff --git a/veejay-current/libvje/effects/neighbours2.c b/veejay-current/libvje/effects/neighbours2.c new file mode 100644 index 00000000..65535e27 --- /dev/null +++ b/veejay-current/libvje/effects/neighbours2.c @@ -0,0 +1,278 @@ +/* + * Linux VeeJay + * + * Copyright(C)2005 Niels Elburg + * + * 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 +#include +#include "neighbours2.h" + +vj_effect *neighbours2_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_malloc(sizeof(vj_effect)); + ve->num_params = 3; + + ve->defaults = (int *) vj_malloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_malloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_malloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 1; + ve->limits[1][0] = 64; /* brush size (shape is rectangle)*/ + ve->limits[0][1] = 1; + ve->limits[1][1] = 255; /* smoothness */ + ve->limits[0][2] = 0; /* luma only / include chroma */ + ve->limits[1][2] = 1; + ve->defaults[0] = 4; + ve->defaults[1] = 15; + ve->defaults[2] = 0; + ve->description = "Artistic Filter (Oilpaint, acc. avg)"; + ve->sub_format = 1; + ve->extra_frame = 0; + ve->has_user = 0; + return ve; +} + +static int pixel_histogram[256]; +static int y_map[256]; +static int cb_map[256]; +static int cr_map[256]; +static uint8_t *tmp_buf[2]; +static uint8_t *chromacity[2]; + + +int neighbours2_malloc(int w, int h ) +{ + tmp_buf[0] = (uint8_t*) vj_malloc(sizeof(uint8_t) * w * h ); + if(!tmp_buf[0] ) return 0; + tmp_buf[1] = (uint8_t*) vj_malloc(sizeof(uint8_t) * w * h ); + chromacity[0] = (uint8_t*) vj_malloc(sizeof(uint8_t) * w * h ); + chromacity[1] = (uint8_t*) vj_malloc(sizeof(uint8_t) * w * h ); + return 1; +} + +int neighbours2_free(void) +{ + if(tmp_buf[0]) free(tmp_buf[0]); + if(tmp_buf[1]) free(tmp_buf[1]); + if(chromacity[0]) free(chromacity[0]); + if(chromacity[1]) free(chromacity[1]); + return 1; +} + +typedef struct +{ + uint8_t y; + uint8_t u; + uint8_t v; +} pixel_t; + + +static inline pixel_t evaluate_pixel_bc( + int x, int y, /* center pixel */ + const int brush_size, /* brush size (works like equal sized rectangle) */ + const double intensity, /* Luma value * scaling factor */ + const int w, /* width of image */ + const int h, /* height of image */ + const uint8_t *premul, /* map data */ + const uint8_t *image, /* image data */ + const uint8_t *image_cb, + const uint8_t *image_cr +) +{ + unsigned int brightness; /* scaled brightnes */ + int peak_value = 0; + int peak_index = 0; + int i,j; + int x0 = x - brush_size; + int x1 = x + brush_size; + int y0 = y - brush_size; + int y1 = y + brush_size; + const int max_ = (int) ( 0xff * intensity ); + + if( x0 < 0 ) x0 = 0; + if( x1 > w ) x1 = w; + if( y0 < 0 ) y0 = 0; + if( y1 > h ) y1 = h; + + /* clear histogram and y_map */ + for( i =0 ; i < max_; i ++ ) + { + pixel_histogram[i] = 0; + y_map[i] = 0; + cb_map[i] = 0; + cr_map[i] = 0; + } + + /* fill histogram, cummulative add of luma values */ + /* this innerloop is executed w * h * brush_size * brush_size and counts + many loads and stores. */ + for( i = y0; i < y1; i ++ ) + { + for( j = x0; j < x1; j ++ ) + { + brightness = premul[ i * w + j]; + pixel_histogram[ brightness ] ++; + y_map[ brightness ] = (image[ i * w + j] + y_map[brightness])>>1; + cb_map[ brightness ] = (cb_map[brightness] + image_cb[ i * w + j ])>>1; + cr_map[ brightness ] = (cr_map[brightness] + image_cr[ i * w + j ])>>1; + } + } + + /* find most occuring value */ + for( i = 0; i < max_ ; i ++ ) + { + if( pixel_histogram[i] >= peak_value ) + { + peak_value = pixel_histogram[i]; + peak_index = i; + } + } + pixel_t val; + + val.y = y_map[peak_index]; + val.u = cb_map[peak_index]; + val.v = cr_map[peak_index]; + + return val; + +} + + +static inline uint8_t evaluate_pixel_b( + int x, int y, /* center pixel */ + const int brush_size, /* brush size (works like equal sized rectangle) */ + const double intensity, /* Luma value * scaling factor */ + const int w, /* width of image */ + const int h, /* height of image */ + const uint8_t *premul, /* map data */ + const uint8_t *image /* image data */ +) +{ + unsigned int brightness; /* scaled brightnes */ + int peak_value = 0; + int peak_index = 0; + int i,j; + int x0 = x - brush_size; + int x1 = x + brush_size; + int y0 = y - brush_size; + int y1 = y + brush_size; + const int max_ = (int) ( 0xff * intensity ); + + if( x0 < 0 ) x0 = 0; + if( x1 > w ) x1 = w; + if( y0 < 0 ) y0 = 0; + if( y1 > h ) y1 = h; + + /* clear histogram and y_map */ + for( i =0 ; i < max_; i ++ ) + { + pixel_histogram[i] = 0; + y_map[i] = 0; + } + + /* fill histogram, cummulative add of luma values */ + for( i = y0; i < y1; i ++ ) + { + for( j = x0; j < x1; j ++ ) + { + // average while adding + brightness = premul[ i * w + j]; + pixel_histogram[ brightness ] ++; + y_map[ brightness ] = (y_map[brightness] + image[ i * w + j]) / 2; + + } + } + + /* find most occuring value */ + for( i = 0; i < max_ ; i ++ ) + { + if( pixel_histogram[i] >= peak_value ) + { + peak_value = pixel_histogram[i]; + peak_index = i; + } + } + if( peak_value < 16) + return image[y*w+x]; + + return( (uint8_t) ( y_map[ peak_index] )); +} + +void neighbours2_apply( VJFrame *frame, int width, int height, int brush_size, int intensity_level, int mode ) +{ + int x,y; + const double intensity = intensity_level / 255.0; + uint8_t *Y = tmp_buf[0]; + uint8_t *Y2 = tmp_buf[1]; + uint8_t *dstY = frame->data[0]; + uint8_t *dstCb = frame->data[1]; + uint8_t *dstCr = frame->data[2]; + // keep luma + veejay_memcpy( Y2, frame->data[0], frame->len ); + + if(mode) + { + veejay_memcpy( chromacity[0], frame->data[1], frame->len ); + veejay_memcpy( chromacity[1], frame->data[2], frame->len ); + } + + // premultiply intensity map + for( y = 0 ; y < frame->len ; y ++ ) + Y[y] = (uint8_t) ( (double)Y2[y] * intensity ); + + if(!mode) + { + for( y = 0; y < height; y ++ ) + { + for( x = 0; x < width; x ++ ) + { + *(dstY)++ = evaluate_pixel_b( + x,y, + brush_size, + intensity, + width, + height, + Y, + Y2 + ); + } + } + } + else + { + pixel_t tmp; + for( y = 0; y < height; y ++ ) + { + for( x = 0; x < width; x ++ ) + { + tmp = evaluate_pixel_bc( + x,y, + brush_size, + intensity, + width, + height, + Y, + Y2, + chromacity[0], + chromacity[1] + ); + *(dstY++) = tmp.y; + *(dstCb++) = tmp.u; + *(dstCr++) = tmp.v; + } + } + } +} diff --git a/veejay-current/libvje/effects/neighbours2.h b/veejay-current/libvje/effects/neighbours2.h new file mode 100644 index 00000000..6ac41180 --- /dev/null +++ b/veejay-current/libvje/effects/neighbours2.h @@ -0,0 +1,31 @@ +/* + * Linux VeeJay + * + * Copyright(C)2005 Niels Elburg + * + * 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 NEIGHBOURS2_H +#define NEIGHBOURS2_H +#include +#include +#include + +vj_effect *neighbours2_init(int w, int h); +int neighbours2_malloc(int w, int h); +int neighbours2_free(void); +void neighbours2_apply( VJFrame *frame, int width, int height, int brush_size, int level,int mode); +#endif diff --git a/veejay-current/libvje/effects/neighbours3.c b/veejay-current/libvje/effects/neighbours3.c new file mode 100644 index 00000000..3351a5d5 --- /dev/null +++ b/veejay-current/libvje/effects/neighbours3.c @@ -0,0 +1,274 @@ +/* + * Linux VeeJay + * + * Copyright(C)2005 Niels Elburg + * + * 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 +#include +#include "neighbours3.h" + +vj_effect *neighbours3_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_malloc(sizeof(vj_effect)); + ve->num_params = 3; + + ve->defaults = (int *) vj_malloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_malloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_malloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 1; + ve->limits[1][0] = 64; /* line size */ + ve->limits[0][1] = 1; + ve->limits[1][1] = 255; /* smoothness */ + ve->limits[0][2] = 0; /* luma only / include chroma */ + ve->limits[1][2] = 1; + ve->defaults[0] = 9; + ve->defaults[1] = 7; + ve->defaults[2] = 1; + ve->description = "Artistic Filter (Horizontal strokes)"; + ve->sub_format = 1; + ve->extra_frame = 0; + ve->has_user = 0; + return ve; +} + +static int pixel_histogram[256]; +static int y_map[256]; +static int cb_map[256]; +static int cr_map[256]; +static uint8_t *tmp_buf[2]; +static uint8_t *chromacity[2]; + + +int neighbours3_malloc(int w, int h ) +{ + tmp_buf[0] = (uint8_t*) vj_malloc(sizeof(uint8_t) * w * h ); + if(!tmp_buf[0] ) return 0; + tmp_buf[1] = (uint8_t*) vj_malloc(sizeof(uint8_t) * w * h ); + chromacity[0] = (uint8_t*) vj_malloc(sizeof(uint8_t) * w * h ); + chromacity[1] = (uint8_t*) vj_malloc(sizeof(uint8_t) * w * h ); + return 1; +} + +int neighbours3_free(void) +{ + if(tmp_buf[0]) free(tmp_buf[0]); + if(tmp_buf[1]) free(tmp_buf[1]); + if(chromacity[0]) free(chromacity[0]); + if(chromacity[1]) free(chromacity[1]); + return 1; +} + +typedef struct +{ + uint8_t y; + uint8_t u; + uint8_t v; +} pixel_t; + +static inline pixel_t evaluate_pixel_bc( + int x, int y, /* center pixel */ + const int brush_size, /* brush size (works like equal sized rectangle) */ + const double intensity, /* Luma value * scaling factor */ + const int w, /* width of image */ + const int h, /* height of image */ + const uint8_t *premul, /* map data */ + const uint8_t *image, /* image data */ + const uint8_t *image_cb, + const uint8_t *image_cr +) +{ + unsigned int brightness; /* scaled brightnes */ + int peak_value = 0; + int peak_index = 0; + int i,j; + int x0 = x - brush_size; + int x1 = x + brush_size; + int y0 = y - brush_size; + int y1 = y + brush_size; + const int max_ = (int) ( 0xff * intensity ); + + if( x0 < 0 ) x0 = 0; + if( x1 > w ) x1 = w; + if( y0 < 0 ) y0 = 0; + if( y1 > h ) y1 = h; + + /* clear histogram and y_map */ + for( i =0 ; i < max_; i ++ ) + { + pixel_histogram[i] = 0; + y_map[i] = 0; + cb_map[i] = 0; + cr_map[i] = 0; + } + + /* fill histogram, cummulative add of luma values */ + /* this innerloop is executed w * h * brush_size and counts + many loads and stores. */ + i = y; + for( j = x0; j < x1; j ++ ) + { + brightness = premul[ i * w + j]; + pixel_histogram[ brightness ] ++; + y_map[ brightness ] += image[ i * w + j]; + cb_map[ brightness ] += image_cb[ i * w + j ]; + cr_map[ brightness ] += image_cr[ i * w + j ]; + } + + + /* find most occuring value */ + for( i = 0; i < max_ ; i ++ ) + { + if( pixel_histogram[i] >= peak_value ) + { + peak_value = pixel_histogram[i]; + peak_index = i; + } + } + pixel_t val; + + val.y = y_map[peak_index] / peak_value; + val.u = cb_map[peak_index] / peak_value; + val.v = cr_map[peak_index] / peak_value; + + return val; + +} + + +static inline uint8_t evaluate_pixel_b( + int x, int y, /* center pixel */ + const int brush_size, /* brush size (works like equal sized rectangle) */ + const double intensity, /* Luma value * scaling factor */ + const int w, /* width of image */ + const int h, /* height of image */ + const uint8_t *premul, /* map data */ + const uint8_t *image /* image data */ +) +{ + unsigned int brightness; /* scaled brightnes */ + int peak_value = 0; + int peak_index = 0; + int i,j; + int x0 = x - brush_size; + int x1 = x + brush_size; + int y0 = y - brush_size; + int y1 = y + brush_size; + const int max_ = (int) ( 0xff * intensity ); + + if( x0 < 0 ) x0 = 0; + if( x1 > w ) x1 = w; + if( y0 < 0 ) y0 = 0; + if( y1 > h ) y1 = h; + + /* clear histogram and y_map */ + for( i =0 ; i < max_; i ++ ) + { + pixel_histogram[i] = 0; + y_map[i] = 0; + } + + i = y; + for( j = x0; j < x1; j ++ ) + { + // average while adding + brightness = premul[ i * w + j]; + pixel_histogram[ brightness ] ++; + y_map[ brightness ] += image[ i * w + j]; + } + + /* find most occuring value */ + for( i = 0; i < max_ ; i ++ ) + { + if( pixel_histogram[i] >= peak_value ) + { + peak_value = pixel_histogram[i]; + peak_index = i; + } + } + if( peak_value < 16) + return image[ y * w + x]; + + return( (uint8_t) ( y_map[ peak_index] / peak_value )); +} + +void neighbours3_apply( VJFrame *frame, int width, int height, int brush_size, int intensity_level, int mode ) +{ + int x,y; + const double intensity = intensity_level / 255.0; + uint8_t *Y = tmp_buf[0]; + uint8_t *Y2 = tmp_buf[1]; + uint8_t *dstY = frame->data[0]; + uint8_t *dstCb = frame->data[1]; + uint8_t *dstCr = frame->data[2]; + // keep luma + veejay_memcpy( Y2, frame->data[0], frame->len ); + + if(mode) + { + veejay_memcpy( chromacity[0], frame->data[1], frame->len ); + veejay_memcpy( chromacity[1], frame->data[2], frame->len ); + } + + // premultiply intensity map + for( y = 0 ; y < frame->len ; y ++ ) + Y[y] = (uint8_t) ( (double)Y2[y] * intensity ); + + if(!mode) + { + for( y = 0; y < height; y ++ ) + { + for( x = 0; x < width; x ++ ) + { + *(dstY)++ = evaluate_pixel_b( + x,y, + brush_size, + intensity, + width, + height, + Y, + Y2 + ); + } + } + memset( frame->data[1], 128, frame->len ); + memset( frame->data[2], 128, frame->len ); + } + else + { + pixel_t tmp; + for( y = 0; y < height; y ++ ) + { + for( x = 0; x < width; x ++ ) + { + tmp = evaluate_pixel_bc( + x,y, + brush_size, + intensity, + width, + height, + Y, + Y2, + chromacity[0], + chromacity[1] + ); + *(dstY++) = tmp.y; + *(dstCb++) = tmp.u; + *(dstCr++) = tmp.v; + } + } + } +} diff --git a/veejay-current/libvje/effects/neighbours3.h b/veejay-current/libvje/effects/neighbours3.h new file mode 100644 index 00000000..b2f81fe7 --- /dev/null +++ b/veejay-current/libvje/effects/neighbours3.h @@ -0,0 +1,31 @@ +/* + * Linux VeeJay + * + * Copyright(C)2005 Niels Elburg + * + * 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 NEIGHBOURS3_H +#define NEIGHBOURS3_H +#include +#include +#include + +vj_effect *neighbours3_init(int w, int h); +int neighbours3_malloc(int w, int h); +int neighbours3_free(void); +void neighbours3_apply( VJFrame *frame, int width, int height, int brush_size, int level,int mode); +#endif diff --git a/veejay-current/libvje/effects/neighbours4.c b/veejay-current/libvje/effects/neighbours4.c new file mode 100644 index 00000000..1b8fae26 --- /dev/null +++ b/veejay-current/libvje/effects/neighbours4.c @@ -0,0 +1,319 @@ +/* + * Linux VeeJay + * + * Copyright(C)2005 Niels Elburg + * + * 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 +#include +#include "neighbours4.h" + +vj_effect *neighbours4_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_malloc(sizeof(vj_effect)); + ve->num_params = 4; + + ve->defaults = (int *) vj_malloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_malloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_malloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 1; + ve->limits[1][0] = w; /* radius */ + ve->limits[0][1] = 1; + ve->limits[1][1] = 200; /* distance from center */ + ve->limits[0][2] = 1; + ve->limits[1][2] = 255; /* smoothness */ + ve->limits[0][3] = 0; /* luma only / include chroma */ + ve->limits[1][3] = 1; + ve->defaults[0] = 4; + ve->defaults[1] = 24; + ve->defaults[2] = 8; + ve->defaults[3] = 1; + ve->description = "Artistic Filter (Round Brush)"; + ve->sub_format = 1; + ve->extra_frame = 0; + ve->has_user = 0; + return ve; +} + +static int pixel_histogram[256]; +static int y_map[256]; +static int cb_map[256]; +static int cr_map[256]; +static uint8_t *tmp_buf[2]; +static uint8_t *chromacity[2]; +typedef struct +{ + uint8_t y; + uint8_t u; + uint8_t v; +} pixel_t; + +typedef struct +{ + double x; + double y; +} relpoint_t; + +static relpoint_t points[2048]; + +int neighbours4_malloc(int w, int h ) +{ + tmp_buf[0] = (uint8_t*) vj_malloc(sizeof(uint8_t) * w * h ); + if(!tmp_buf[0] ) return 0; + tmp_buf[1] = (uint8_t*) vj_malloc(sizeof(uint8_t) * w * h ); + chromacity[0] = (uint8_t*) vj_malloc(sizeof(uint8_t) * w * h ); + chromacity[1] = (uint8_t*) vj_malloc(sizeof(uint8_t) * w * h ); + int i; + for(i = 0; i < w; i ++ ) + { + points[i].x = 0.0; + points[i].y = 0.0; + } + return 1; +} + +int neighbours4_free(void) +{ + if(tmp_buf[0]) free(tmp_buf[0]); + if(tmp_buf[1]) free(tmp_buf[1]); + if(chromacity[0]) free(chromacity[0]); + if(chromacity[1]) free(chromacity[1]); + return 1; +} + +static void create_circle( double radius, int depth, int w ) +{ + double t = 0.0; + int index = 0; + double theta = ((double)w/depth); + while( index <= depth) + { + double r = (t / 180.0) * M_PI; + points[index].x = cos(r) * radius; + points[index].y = sin(r) * radius; + t += theta; + index++; + } +} + +static inline pixel_t evaluate_pixel_bc( + int x, int y, /* center pixel */ + const int brush_size, /* brush size (works like equal sized rectangle) */ + const double intensity, /* Luma value * scaling factor */ + const int w, /* width of image */ + const int h, /* height of image */ + const uint8_t *premul, /* map data */ + const uint8_t *image, /* image data */ + const uint8_t *image_cb, + const uint8_t *image_cr, + const relpoint_t *points /* relative coordinate map */ +) +{ + unsigned int brightness; /* scaled brightnes */ + int peak_value = 0; + int peak_index = 0; + int i,j; + const int max_ = (int) ( 0xff * intensity ); + int dx,dy; + + /* clear histogram and y_map */ + for( i =0 ; i < max_; i ++ ) + { + pixel_histogram[i] = 0; + y_map[i] = 0; + cb_map[i] = 0; + cr_map[i] = 0; + } + + /* fill histogram, cummulative add of luma values */ + /* this innerloop is executed w * h * brush_size and counts + many loads and stores. */ + i = y; + + /* loop over perimter of circle (!) */ + for( i = 0; i < brush_size; i ++) + { + dx = points[i].x + x; + dy = points[i].y + y; + if(dx < 0) dx = 0; else if (dx > w) dx = w; + if(dy < 0) dy = 0; else if (dy >= h) dy = h-1; + + brightness = premul[ dy * w + dx]; + pixel_histogram[ brightness ] ++; + + y_map[ brightness ] += image[ dy * w + dx]; + cb_map[ brightness ] += image_cb[ dy * w + dx ]; + cr_map[ brightness ] += image_cr[ dy * w + dx ]; + } + + + /* find most occuring value */ + for( i = 0; i < max_ ; i ++ ) + { + if( pixel_histogram[i] >= peak_value ) + { + peak_value = pixel_histogram[i]; + peak_index = i; + } + } + pixel_t val; + + val.y = y_map[peak_index] / peak_value; + val.u = cb_map[peak_index] / peak_value; + val.v = cr_map[peak_index] / peak_value; + + return val; + +} + + +static inline uint8_t evaluate_pixel_b( + int x, int y, /* center pixel */ + const int brush_size, /* brush size (works like equal sized rectangle) */ + const double intensity, /* Luma value * scaling factor */ + const int w, /* width of image */ + const int h, /* height of image */ + const uint8_t *premul, /* map data */ + const uint8_t *image, /* image data */ + const relpoint_t *points /* relative coordinate map*/ +) +{ + unsigned int brightness; /* scaled brightnes */ + int peak_value = 0; + int peak_index = 0; + int i,j; + int x0 = x - brush_size; + int x1 = x + brush_size; + int y0 = y - brush_size; + int y1 = y + brush_size; + const int max_ = (int) ( 0xff * intensity ); + int dx,dy; + if( x0 < 0 ) x0 = 0; + if( x1 > w ) x1 = w; + if( y0 < 0 ) y0 = 0; + if( y1 > h ) y1 = h; + + /* clear histogram and y_map */ + for( i =0 ; i < max_; i ++ ) + { + pixel_histogram[i] = 0; + y_map[i] = 0; + } + + // points in circle + for( i = 0; i < brush_size; i ++) + { + dx = points[i].x + x; + dy = points[i].y + y; + if(dx < 0) dx = 0; else if (dx > w) dx = w; + if(dy < 0) dy = 0; else if (dy >= h) dy = h-1; + + brightness = premul[ dy * w + dx]; + pixel_histogram[ brightness ] ++; + y_map[ brightness ] += image[ dy * w + dx]; + } + + /* find most occuring value */ + for( i = 0; i < max_ ; i ++ ) + { + if( pixel_histogram[i] >= peak_value ) + { + peak_value = pixel_histogram[i]; + peak_index = i; + } + } + if( peak_value < 16) + return image[ y * w + x]; + + return( (uint8_t) ( y_map[ peak_index] / peak_value )); +} + +void neighbours4_apply( VJFrame *frame, int width, int height, int radius, int brush_size, int intensity_level, int mode ) +{ + int x,y; + const double intensity = intensity_level / 255.0; + uint8_t *Y = tmp_buf[0]; + uint8_t *Y2 = tmp_buf[1]; + uint8_t *dstY = frame->data[0]; + uint8_t *dstCb = frame->data[1]; + uint8_t *dstCr = frame->data[2]; + double r = (double)radius; + // keep luma + veejay_memcpy( Y2, frame->data[0], frame->len ); + + create_circle( r, brush_size,width ); + + relpoint_t *p_points = &points[0]; + + if(mode) + { + veejay_memcpy( chromacity[0], frame->data[1], frame->len ); + veejay_memcpy( chromacity[1], frame->data[2], frame->len ); + } + + + // premultiply intensity map + for( y = 0 ; y < frame->len ; y ++ ) + Y[y] = (uint8_t) ( (double)Y2[y] * intensity ); + + if(!mode) + { + for( y = 0; y < height; y ++ ) + { + for( x = 0; x < width; x ++ ) + { + *(dstY)++ = evaluate_pixel_b( + x,y, + brush_size, + intensity, + width, + height, + Y, + Y2, + p_points + ); + } + } + memset( frame->data[1], 128, frame->len ); + memset( frame->data[2], 128, frame->len ); + } + else + { + pixel_t tmp; + for( y = 0; y < height; y ++ ) + { + for( x = 0; x < width; x ++ ) + { + tmp = evaluate_pixel_bc( + x,y, + brush_size, + intensity, + width, + height, + Y, + Y2, + chromacity[0], + chromacity[1], + p_points + ); + *(dstY++) = tmp.y; + *(dstCb++) = tmp.u; + *(dstCr++) = tmp.v; + } + } + } + +} diff --git a/veejay-current/libvje/effects/neighbours4.h b/veejay-current/libvje/effects/neighbours4.h new file mode 100644 index 00000000..8b889b51 --- /dev/null +++ b/veejay-current/libvje/effects/neighbours4.h @@ -0,0 +1,31 @@ +/* + * Linux VeeJay + * + * Copyright(C)2005 Niels Elburg + * + * 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 NEIGHBOURS4_H +#define NEIGHBOURS4_H +#include +#include +#include + +vj_effect *neighbours4_init(int w, int h); +int neighbours4_malloc(int w, int h); +int neighbours4_free(void); +void neighbours4_apply( VJFrame *frame, int width, int height, int radius,int brush_size, int level,int mode); +#endif diff --git a/veejay-current/libvje/effects/neighbours5.c b/veejay-current/libvje/effects/neighbours5.c new file mode 100644 index 00000000..4225302d --- /dev/null +++ b/veejay-current/libvje/effects/neighbours5.c @@ -0,0 +1,270 @@ +/* + * Linux VeeJay + * + * Copyright(C)2005 Niels Elburg + * + * 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 +#include +#include "neighbours5.h" + +vj_effect *neighbours5_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_malloc(sizeof(vj_effect)); + ve->num_params = 3; + + ve->defaults = (int *) vj_malloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_malloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_malloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 1; + ve->limits[1][0] = 64; /* line size */ + ve->limits[0][1] = 1; + ve->limits[1][1] = 255; /* smoothness */ + ve->limits[0][2] = 0; /* luma only / include chroma */ + ve->limits[1][2] = 1; + ve->defaults[0] = 6; + ve->defaults[1] = 5; + ve->defaults[2] = 1; + ve->description = "Artistic Filter (Vertical strokes)"; + ve->sub_format = 1; + ve->extra_frame = 0; + ve->has_user = 0; + return ve; +} + +static int pixel_histogram[256]; +static int y_map[256]; +static int cb_map[256]; +static int cr_map[256]; +static uint8_t *tmp_buf[2]; +static uint8_t *chromacity[2]; + + +int neighbours5_malloc(int w, int h ) +{ + tmp_buf[0] = (uint8_t*) vj_malloc(sizeof(uint8_t) * w * h ); + if(!tmp_buf[0] ) return 0; + tmp_buf[1] = (uint8_t*) vj_malloc(sizeof(uint8_t) * w * h ); + chromacity[0] = (uint8_t*) vj_malloc(sizeof(uint8_t) * w * h ); + chromacity[1] = (uint8_t*) vj_malloc(sizeof(uint8_t) * w * h ); + return 1; +} + +int neighbours5_free(void) +{ + if(tmp_buf[0]) free(tmp_buf[0]); + if(tmp_buf[1]) free(tmp_buf[1]); + if(chromacity[0]) free(chromacity[0]); + if(chromacity[1]) free(chromacity[1]); + return 1; +} + +typedef struct +{ + uint8_t y; + uint8_t u; + uint8_t v; +} pixel_t; + +static inline pixel_t evaluate_pixel_bc( + int x, int y, /* center pixel */ + const int brush_size, /* brush size (works like equal sized rectangle) */ + const double intensity, /* Luma value * scaling factor */ + const int w, /* width of image */ + const int h, /* height of image */ + const uint8_t *premul, /* map data */ + const uint8_t *image, /* image data */ + const uint8_t *image_cb, + const uint8_t *image_cr +) +{ + unsigned int brightness; /* scaled brightnes */ + int peak_value = 0; + int peak_index = 0; + int i,j; + int x0 = x - brush_size; + int x1 = x + brush_size; + int y0 = y - brush_size; + int y1 = y + brush_size; + const int max_ = (int) ( 0xff * intensity ); + + if( y0 < 0 ) y0 = 0; + if( y1 > h ) y1 = h; + + /* clear histogram and y_map */ + for( i =0 ; i < max_; i ++ ) + { + pixel_histogram[i] = 0; + y_map[i] = 0; + cb_map[i] = 0; + cr_map[i] = 0; + } + + /* fill histogram, cummulative add of luma values */ + /* this innerloop is executed w * h * brush_size and counts + many loads and stores. + vertical passing + */ + for( j = y0; j < y1; j ++ ) + { + brightness = premul[ j * w + x]; + pixel_histogram[ brightness ] ++; + y_map[ brightness ] += (image[ j * w + x]); + cb_map[ brightness ] += (image_cb[ j * w + x ]); + cr_map[ brightness ] += (image_cr[ j * w + x ]); + } + + + /* find most occuring value */ + for( i = 0; i < max_ ; i ++ ) + { + if( pixel_histogram[i] >= peak_value ) + { + peak_value = pixel_histogram[i]; + peak_index = i; + } + } + pixel_t val; + + val.y = y_map[peak_index] / peak_value; + val.u = cb_map[peak_index] / peak_value; + val.v = cr_map[peak_index] / peak_value; + + return val; + +} + + +static inline uint8_t evaluate_pixel_b( + int x, int y, /* center pixel */ + const int brush_size, /* brush size (works like equal sized rectangle) */ + const double intensity, /* Luma value * scaling factor */ + const int w, /* width of image */ + const int h, /* height of image */ + const uint8_t *premul, /* map data */ + const uint8_t *image /* image data */ +) +{ + unsigned int brightness; /* scaled brightnes */ + int peak_value = 0; + int peak_index = 0; + int i,j; + int x0 = x - brush_size; + int x1 = x + brush_size; + int y0 = y - brush_size; + int y1 = y + brush_size; + const int max_ = (int) ( 0xff * intensity ); + + if( y0 < 0 ) y0 = 0; + if( y1 > h ) y1 = h; + + /* clear histogram and y_map */ + for( i =0 ; i < max_; i ++ ) + { + pixel_histogram[i] = 0; + y_map[i] = 0; + } + + for( j = y0; j < y1; j ++ ) + { + // average while adding + brightness = premul[ j * w + x]; + pixel_histogram[ brightness ] ++; + y_map[ brightness ] += image[ j * w + x]; + } + + /* find most occuring value */ + for( i = 0; i < max_ ; i ++ ) + { + if( pixel_histogram[i] >= peak_value ) + { + peak_value = pixel_histogram[i]; + peak_index = i; + } + } + if( peak_value < 16) + return image[ y * w + x]; + + return( (uint8_t) ( y_map[ peak_index] / peak_value )); +} + +void neighbours5_apply( VJFrame *frame, int width, int height, int brush_size, int intensity_level, int mode ) +{ + int x,y; + const double intensity = intensity_level / 255.0; + uint8_t *Y = tmp_buf[0]; + uint8_t *Y2 = tmp_buf[1]; + uint8_t *dstY = frame->data[0]; + uint8_t *dstCb = frame->data[1]; + uint8_t *dstCr = frame->data[2]; + // keep luma + veejay_memcpy( Y2, frame->data[0], frame->len ); + + if(mode) + { + veejay_memcpy( chromacity[0], frame->data[1], frame->len ); + veejay_memcpy( chromacity[1], frame->data[2], frame->len ); + } + + // premultiply intensity map + for( y = 0 ; y < frame->len ; y ++ ) + Y[y] = (uint8_t) ( (double)Y2[y] * intensity ); + + if(!mode) + { + for( y = 0; y < height; y ++ ) + { + for( x = 0; x < width; x ++ ) + { + *(dstY)++ = evaluate_pixel_b( + x,y, + brush_size, + intensity, + width, + height, + Y, + Y2 + ); + } + } + memset( frame->data[1], 128, frame->len ); + memset( frame->data[2], 128, frame->len ); + } + else + { + pixel_t tmp; + for( y = 0; y < height; y ++ ) + { + for( x = 0; x < width; x ++ ) + { + tmp = evaluate_pixel_bc( + x,y, + brush_size, + intensity, + width, + height, + Y, + Y2, + chromacity[0], + chromacity[1] + ); + *(dstY++) = tmp.y; + *(dstCb++) = tmp.u; + *(dstCr++) = tmp.v; + } + } + } +} diff --git a/veejay-current/libvje/effects/neighbours5.h b/veejay-current/libvje/effects/neighbours5.h new file mode 100644 index 00000000..619116d8 --- /dev/null +++ b/veejay-current/libvje/effects/neighbours5.h @@ -0,0 +1,31 @@ +/* + * Linux VeeJay + * + * Copyright(C)2005 Niels Elburg + * + * 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 NEIGHBOURS5_H +#define NEIGHBOURS5_H +#include +#include +#include + +vj_effect *neighbours5_init(int w, int h); +int neighbours5_malloc(int w, int h); +int neighbours5_free(void); +void neighbours5_apply( VJFrame *frame, int width, int height, int radius,int brush_size, int level); +#endif diff --git a/veejay-current/libvje/internal.h b/veejay-current/libvje/internal.h index a8d9d0b1..3b4b5e46 100644 --- a/veejay-current/libvje/internal.h +++ b/veejay-current/libvje/internal.h @@ -182,11 +182,15 @@ enum { VJ_IMAGE_EFFECT_VIDBOIDS = 165, VJ_IMAGE_EFFECT_GHOST = 166, VJ_IMAGE_EFFECT_NEIGHBOUR = 167, + VJ_IMAGE_EFFECT_NEIGHBOUR2= 168, + VJ_IMAGE_EFFECT_NEIGHBOUR3= 169, + VJ_IMAGE_EFFECT_NEIGHBOUR4= 170, + VJ_IMAGE_EFFECT_NEIGHBOUR5= 171, VJ_IMAGE_EFFECT_DUMMY = 100, }; #define VJ_IMAGE_EFFECT_MIN 100 -#define VJ_IMAGE_EFFECT_MAX 168 +#define VJ_IMAGE_EFFECT_MAX 172 #define VJ_VIDEO_EFFECT_MIN 200 #define VJ_VIDEO_EFFECT_MAX 237 @@ -485,5 +489,9 @@ extern void boids_apply( VJFrame *frame, int w, int h, int p0,int p1, int p2, i extern void ghost_apply(VJFrame *frame, int w, int h, int o ); extern void neighbours_apply( VJFrame *frame, int width, int height, int brush_size, int level, int mode); +extern void neighbours_apply2( VJFrame *frame, int width, int height, int brush_size, int level, int mode); +extern void neighbours_apply3( VJFrame *frame, int width, int height, int brush_size, int level, int mode); +extern void neighbours_apply4( VJFrame *frame, int width, int height, int radius, int brush_size, int level, int mode); +extern void neighbours_apply5( VJFrame *frame, int width, int height, int radius, int brush_size, int level); #endif diff --git a/veejay-current/libvje/vj-effect.c b/veejay-current/libvje/vj-effect.c index 983565a8..976788aa 100644 --- a/veejay-current/libvje/vj-effect.c +++ b/veejay-current/libvje/vj-effect.c @@ -131,7 +131,10 @@ #include "effects/boids.h" #include "effects/tripplicity.h" #include "effects/neighbours.h" - +#include "effects/neighbours2.h" +#include "effects/neighbours3.h" +#include "effects/neighbours4.h" +#include "effects/neighbours5.h" static struct { int (*mem_init)(int width, int height); @@ -172,6 +175,10 @@ static struct { boids_malloc, boids_free, VJ_IMAGE_EFFECT_VIDBOIDS }, { ghost_malloc, ghost_free, VJ_IMAGE_EFFECT_GHOST }, { neighbours_malloc, neighbours_free, VJ_IMAGE_EFFECT_NEIGHBOUR }, +{ neighbours2_malloc, neighbours2_free, VJ_IMAGE_EFFECT_NEIGHBOUR2 }, +{ neighbours3_malloc, neighbours3_free, VJ_IMAGE_EFFECT_NEIGHBOUR3 }, +{ neighbours4_malloc, neighbours4_free, VJ_IMAGE_EFFECT_NEIGHBOUR4 }, +{ neighbours5_malloc, neighbours5_free, VJ_IMAGE_EFFECT_NEIGHBOUR5 }, { NULL , NULL ,0 }, }; @@ -450,7 +457,11 @@ void vj_effect_initialize(int width, int height) vj_effects[i + 64] = blob_init(width,height); vj_effects[i + 65] = boids_init(width,height); vj_effects[i + 66] = ghost_init(width,height); - vj_effects[i + 67] = neighbours_init(width,height); + vj_effects[i + 67] = neighbours_init(width,height); + vj_effects[i + 68] = neighbours2_init(width,height); + vj_effects[i + 69] = neighbours3_init(width,height); + vj_effects[i + 70] = neighbours4_init(width,height); + vj_effects[i + 71] = neighbours5_init(width,height); max_width = width; max_height = height; diff --git a/veejay-current/libvje/vj-effman.c b/veejay-current/libvje/vj-effman.c index 757f509b..531fc5be 100644 --- a/veejay-current/libvje/vj-effman.c +++ b/veejay-current/libvje/vj-effman.c @@ -41,9 +41,26 @@ void vj_effman_apply_image_effect( int j; switch (e) { + case VJ_IMAGE_EFFECT_NEIGHBOUR4: + neighbours4_apply(frames[0],frameinfo->width, + frameinfo->height,arg[0],arg[1],arg[2],arg[3]); + break; + case VJ_IMAGE_EFFECT_NEIGHBOUR5: + neighbours5_apply(frames[0],frameinfo->width, + frameinfo->height,arg[0],arg[1],arg[2]); + break; + case VJ_IMAGE_EFFECT_NEIGHBOUR2: + neighbours2_apply(frames[0],frameinfo->width, + frameinfo->height,arg[0],arg[1],arg[2]); + break; case VJ_IMAGE_EFFECT_NEIGHBOUR: neighbours_apply(frames[0],frameinfo->width,frameinfo->height,arg[0],arg[1],arg[2]); break; + case VJ_IMAGE_EFFECT_NEIGHBOUR3: + neighbours3_apply(frames[0],frameinfo->width, + frameinfo->height,arg[0],arg[1],arg[2]); + break; + case VJ_IMAGE_EFFECT_RIPPLETV: water_apply(frames[0],frameinfo->width,frameinfo->height,arg[0],arg[1],arg[2]); break; diff --git a/veejay-current/libvje/vje.h b/veejay-current/libvje/vje.h index ec973c38..a9eeda2a 100644 --- a/veejay-current/libvje/vje.h +++ b/veejay-current/libvje/vje.h @@ -25,7 +25,7 @@ #include #include -#define MAX_EFFECTS 105 +#define MAX_EFFECTS 109 #define PARAM_WIDTH (1<<0x2) #define PARAM_HEIGHT (1<<0x3)