diff --git a/veejay-current/libvje/effects/blob.c b/veejay-current/libvje/effects/blob.c index 428b335a..e3d905bf 100644 --- a/veejay-current/libvje/effects/blob.c +++ b/veejay-current/libvje/effects/blob.c @@ -69,12 +69,12 @@ typedef struct static blob_t *blobs_; static uint8_t **blob_; static uint8_t *blob_image_; -static int blob_ready_ = 0; +static int blob_ready_ = 0; static int blob_radius_ = 16; static int blob_dradius_ = 0; static int blob_sradius_ = 0; -static int blob_num_ = 50; -static int blob_type_ = 1; +static int blob_num_ = 50; +static int blob_type_ = 1; vj_effect *blob_init(int w, int h) { @@ -83,7 +83,7 @@ vj_effect *blob_init(int w, int h) 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] = 0; + ve->limits[0][0] = 1; ve->limits[1][0] = 360; // radius ve->limits[0][1] = 1; ve->limits[1][1] = 100; // num blobs @@ -124,6 +124,7 @@ int blob_malloc(int w, int h) { blob_[i] = (uint8_t*) vj_malloc(sizeof(uint8_t) * blob_dradius_ ); if(!blob_[i]) return 0; + memset( blob_[i], 0 , blob_dradius_ ); } blobs_ = (blob_t*) vj_malloc(sizeof(blob_t) * blob_num_ ); @@ -131,7 +132,6 @@ int blob_malloc(int w, int h) blob_image_ = (uint8_t*) vj_malloc(sizeof(uint8_t) * w * h ); if(!blob_image_) return 0; - for( i = -blob_radius_ ; i < blob_radius_ ; ++ i ) { @@ -172,6 +172,8 @@ void blob_free() free(blobs_); if(blob_image_) free(blob_image_); + blobs_ = NULL; + blob_image_ = NULL; } typedef void (*blob_func)(int s, int width); diff --git a/veejay-current/libvje/effects/chromapalette.c b/veejay-current/libvje/effects/chromapalette.c index 88aa237a..b4b04e19 100644 --- a/veejay-current/libvje/effects/chromapalette.c +++ b/veejay-current/libvje/effects/chromapalette.c @@ -34,7 +34,7 @@ vj_effect *chromapalette_init(int w, int h) //angle,r,g,b,cbc,crc ve->limits[0][0] = 1; - ve->limits[1][0] = 9000; + ve->limits[1][0] = 900; ve->limits[0][1] = 0; ve->limits[1][1] = 255; ve->limits[0][2] = 0; @@ -48,17 +48,18 @@ vj_effect *chromapalette_init(int w, int h) ve->limits[0][5] = 0; ve->limits[1][5] = 255; - ve->defaults[0] = 1500;//angle - ve->defaults[1] = 0; //r + ve->defaults[0] = 319;//angle + ve->defaults[1] = 255; //r ve->defaults[2] = 0; //g - ve->defaults[3] = 255; //b - ve->defaults[4] = 40; //cb default - ve->defaults[5] = 0; //cr default + ve->defaults[3] = 0; //b + ve->defaults[4] = 200; //cb default + ve->defaults[5] = 20; //cr default ve->description = "Chrominance Palette (rgb key) "; ve->sub_format = 1; ve->extra_frame = 0; ve->has_help = 1; ve->has_user = 0; + ve->rgb_conv = 1; return ve; } @@ -116,14 +117,19 @@ void chromapalette_apply(VJFrame *frame, int width, int height, int angle, int r uint8_t *Cr = frame->data[2]; uint8_t U; uint8_t V; - const float cb_mul = 0.492; + int y,u,v; + const float cb_mul = 0.492; const float cr_mul = 0.877; - const float aa = ((U_Redco * r) - (U_Greenco * g) - (U_Blueco * b) + 128); - const float bb = (-(V_Redco * r) - (V_Greenco * g) + (V_Blueco * b) + 128); + + _rgb2yuv( r,g,b,y,u,v ); + + const float aa = (const float) u; + const float bb = (const float) v; + float tmp = sqrt(((aa * aa) + (bb * bb))); const int colorKeycb = 127 * (aa / tmp); const int colorKeycr = 127 * (bb / tmp); - float angle_f = (angle*0.01); + float angle_f = (angle*0.1); const int accept_angle = 0xf * tan(M_PI * angle_f / 180.0); /* @@ -148,9 +154,9 @@ void chromapalette_apply(VJFrame *frame, int width, int height, int angle, int r { if( _chroma_key( Cb[i] , Cr[i], colorKeycb,colorKeycr, accept_angle)) { - U = 128 + (int)( (float) (color_cb - Y[i]) * cb_mul ); + U = 128+(int)( (float) (color_cb - Y[i]) * cb_mul ); if(U < 16) U = 16; else if ( U > 240 ) U = 240; - V = 128 + (int)( (float) (color_cr - Y[i]) * cr_mul ); + V = 128+(int)( (float) (color_cr - Y[i]) * cr_mul ); if(V < 16) V = 16; else if ( V > 240 ) V = 240; Cb[i] = U; Cr[i] = V; @@ -163,7 +169,7 @@ void chromapalette_apply(VJFrame *frame, int width, int height, int angle, int r { if( _chroma_key( Cb[i], Cr[i], colorKeycb, colorKeycr, accept_angle)) { - V = 128 + (int)( (float) (color_cr - Y[i]) * cr_mul ); + V = 128+(int)( (float) (color_cr - Y[i]) * cr_mul ); if( V < 16 ) V = 16; else if ( V > 240 ) V = 240; Cr[i] = V; } diff --git a/veejay-current/libvje/effects/common.h b/veejay-current/libvje/effects/common.h index 41ad9cc6..494bf0ba 100644 --- a/veejay-current/libvje/effects/common.h +++ b/veejay-current/libvje/effects/common.h @@ -66,15 +66,65 @@ #define V_Green (-0.41869) #define V_Blue (-0.08131) -#define Y_Redco ( 0.257 ) -#define Y_Greenco ( 0.504 ) -#define Y_Blueco ( 0.098 ) -#define U_Redco (-0.148 ) -#define U_Greenco (-0.291 ) -#define U_Blueco ( 0.439 ) -#define V_Redco ( 0.439 ) -#define V_Greenco (-0.368 ) -#define V_Blueco (-0.071 ) +/* RGB to YUV conversion, www.fourcc.org */ + +#define Y_Redco ( 0.257f ) +#define Y_Greenco ( 0.504f ) +#define Y_Blueco ( 0.098f ) + +#define U_Redco ( 0.439f ) +#define U_Greenco ( 0.368f ) +#define U_Blueco ( 0.071f ) + +#define V_Redco ( 0.148f ) +#define V_Greenco (0.291f ) +#define V_Blueco (0.439f ) + + +#define COLOR_rgb2yuv(r,g,b, y,u,v ) \ + {\ + y = (int) ( (Y_Redco * (float) r) + (Y_Greenco * (float)g) + (Y_Blueco * (float)b) + 16.0);\ + u = (int) ( (U_Redco * (float) r) - (U_Greenco * (float)g) + (U_Blueco * (float)b) + 128.0);\ + v = (int) ( -(V_Redco * (float) r) - (V_Greenco * (float)g) + (V_Blueco * (float)b) + 128.0);\ + } + +#define CCIR601_rgb2yuv(r,g,b,y,u,v) \ + {\ + float Ey = (0.299f * (float)r) + (0.587f * (float) g) + (0.114f * (float)b );\ + float Eu = (0.713f * ( ((float)r) - Ey ) );\ + float Ev = (0.564f * ( ((float)b) - Ey ) );\ + y = (int) ( 255.0 * Ey );\ + u = (int) (( 255.0 * Eu ) + 128);\ + v = (int) (( 255.0 * Ev ) + 128);\ +} + + +#define GIMP_rgb2yuv(r,g,b,y,u,v) \ + {\ + float Ey = (0.299 * (float)r) + (0.587 * (float)g) + (0.114 * (float)b);\ + float Eu = (-0.169 * (float)r) - (0.331 * (float)g) + (0.500 * (float)b) + 128.0;\ + float Ev = (0.500 * (float)r) - (0.419 * (float)g) - (0.081 * (float)b) + 128.0;\ + y = (int) Ey;\ + u = (int) Eu;\ + v = (int) Ev;\ + } + +enum +{ + GIMP_RGB=0, + CCIR601_RGB=1, + OLD_RGB=2, +}; + +#define _rgb2yuv(r,g,b,y,u,v)\ +{\ + if( rgb_parameter_conversion_type_ == GIMP_RGB )\ + GIMP_rgb2yuv(r,g,b,y,u,v)\ + if( rgb_parameter_conversion_type_ == CCIR601_RGB )\ + CCIR601_rgb2yuv(r,g,b,y,u,v)\ + if( rgb_parameter_conversion_type_ == OLD_RGB )\ + COLOR_rgb2yuv(r,g,b,y,u,v)\ +} typedef uint8_t (*pix_func_Y) (uint8_t y1, uint8_t y2); typedef uint8_t (*pix_func_C) (uint8_t y1, uint8_t y2); diff --git a/veejay-current/libvje/effects/complexinvert.c b/veejay-current/libvje/effects/complexinvert.c index 4e7c1f0f..fa0f48cb 100644 --- a/veejay-current/libvje/effects/complexinvert.c +++ b/veejay-current/libvje/effects/complexinvert.c @@ -36,11 +36,11 @@ vj_effect *complexinvert_init(int w, int h) 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->defaults[0] = 80; /* angle */ - ve->defaults[1] = 0; /* r */ + ve->defaults[0] = 300; /* angle */ + ve->defaults[1] = 255; /* r */ ve->defaults[2] = 0; /* g */ - ve->defaults[3] = 255; /* b */ - ve->defaults[4] = 1; /* smoothen level */ + ve->defaults[3] = 0; /* b */ + ve->defaults[4] = 2400; /* noise suppression*/ ve->limits[0][0] = 5; ve->limits[1][0] = 900; @@ -53,81 +53,42 @@ vj_effect *complexinvert_init(int w, int h) ve->limits[0][3] = 0; ve->limits[1][3] = 255; - ve->limits[0][4] = 0; - ve->limits[1][4] = 4; + ve->limits[0][4] = 0; + ve->limits[1][4] = 3500; ve->has_user = 0; ve->description = "Complex Invert"; ve->extra_frame = 0; ve->sub_format = 1; + ve->rgb_conv = 1; return ve; } -/* this method decides whether or not a pixel from the fg will be accepted for keying */ -int accept_ipixel(uint8_t fg_cb, uint8_t fg_cr, int cb, int cr, - int accept_angle_tg) -{ - short xx, yy; - /* convert foreground to xz coordinates where x direction is - defined by key color */ - uint8_t val; - - xx = ((fg_cb * cb) + (fg_cr * cr)) >> 7; - - if (xx < -128) { - xx = -128; - } - if (xx > 127) { - xx = 127; - } - - yy = ((fg_cr * cb) - (fg_cb * cr)) >> 7; - - if (yy < -128) { - yy = -128; - } - if (yy > 127) { - yy = 127; - } - - - /* accept angle should not be > 90 degrees - reasonable results between 10 and 80 degrees. - */ - - val = (xx * accept_angle_tg) >> 4; - if (val > 127) - val = 127; - if (abs(yy) < val) { - return 1; - } - return 0; -} - void complexinvert_apply(VJFrame *frame, int width, - int height, int i_angle, int r, int g, int b, - int level ) + int height, int i_angle, int r, int g, int b, int i_noise) { - uint8_t *fg_y, *fg_cb, *fg_cr; + uint8_t *fg_y, *fg_cb, *fg_cr; uint8_t *bg_y, *bg_cb, *bg_cr; int accept_angle_tg, accept_angle_ctg, one_over_kc; int kfgy_scale, kg; - int cb, cr; + int kbg, x1, y1; float kg1, tmp, aa = 128, bb = 128, _y = 0; - float angle = (float) i_angle / 10.0; - //float noise_level = 350.0; + float angle = (float) i_angle * 0.1f; + float noise_level = (i_noise / 100.0); unsigned int pos; - int matrix[5]; - uint8_t val; - const int len = frame->len; - uint8_t *Y = frame->data[0]; - uint8_t *Cb = frame->data[1]; - uint8_t *Cr = frame->data[2]; - - _y = ((Y_Redco * r) + (Y_Greenco * g) + (Y_Blueco * b) + 16); - aa = ((U_Redco * r) - (U_Greenco * g) - (U_Blueco * b) + 128); - bb = (-(V_Redco * r) - (V_Greenco * g) + (V_Blueco * b) + 128); + uint8_t val, tmp1; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + uint8_t *Y2 = frame->data[0]; + uint8_t *Cb2= frame->data[1]; + uint8_t *Cr2= frame->data[2]; + int iy=16,iu=128,iv=128; + _rgb2yuv( r,g,b, iy,iu,iv ); + _y = (float) iy; + aa = (float) iu; + bb = (float) iv; tmp = sqrt(((aa * aa) + (bb * bb))); cb = 127 * (aa / tmp); cr = 127 * (bb / tmp); @@ -151,70 +112,87 @@ void complexinvert_apply(VJFrame *frame, int width, bg_cb = frame->data[1]; bg_cr = frame->data[2]; - for (pos = width + 1; pos < (len) - width - 1; pos++) { - int i = 0; - int smooth = 0; - /* setup matrix - [ - 0 - ] = do not accept. [ - 1 - ] = level 5 , accept only when all n = 1 - [ 0 0 0 ] [ 1 1 1 ] - [ - 0 - ] [ - 1 - ] + for (pos = 0; pos < frame->len; pos++) + { + short xx, yy; - [ - 0 - ] sum of all n is acceptance value for level - [ 1 0 1 ] - [ 0 1 0 ] + xx = (((fg_cb[pos]) * cb) + ((fg_cr[pos]) * cr)) >> 7; + + if (xx < -128) + xx = -128; + + if (xx > 127) + xx = 127; + + + yy = (((fg_cr[pos]) * cb) - ((fg_cb[pos]) * cr)) >> 7; + + if (yy < -128) + yy = -128; + + if (yy > 127) + yy = 127; + + + + /* accept angle should not be > 90 degrees + reasonable results between 10 and 80 degrees. */ - matrix[0] = accept_ipixel(fg_cb[pos], fg_cr[pos], cb, cr, accept_angle_tg); /* center pixel */ - matrix[1] = accept_ipixel(fg_cb[pos - 1], fg_cr[pos - 1], cb, cr, accept_angle_tg); /* left pixel */ - matrix[2] = accept_ipixel(fg_cb[pos + 1], fg_cr[pos + 1], cb, cr, accept_angle_tg); /* right pixel */ - matrix[3] = accept_ipixel(fg_cb[pos + width], fg_cr[pos + width], cb, cr, accept_angle_tg); /* top pixel */ - matrix[4] = accept_ipixel(fg_cb[pos - width], fg_cr[pos - width], cb, cr, accept_angle_tg); /* bottom pixel */ - for (i = 0; i < 5; i++) { - if (matrix[i] == 1) - smooth++; - } - if (smooth >= level) { - short xx, yy; - /* get bg/fg pixels */ - uint8_t p1 = (matrix[0] == 0 ? fg_y[pos] : bg_y[pos]); - uint8_t p2 = (matrix[1] == 0 ? fg_y[pos - 1] : bg_y[pos - 1]); - uint8_t p3 = (matrix[2] == 0 ? fg_y[pos + 1] : bg_y[pos + 1]); - uint8_t p4 = - (matrix[3] == 0 ? fg_y[pos + width] : bg_y[pos + width]); - uint8_t p5 = - (matrix[4] == 0 ? fg_y[pos - width] : bg_y[pos - width]); - /* and blur the pixel */ - fg_y[pos] = (p1 + p2 + p3 + p4 + p5) / 5; - /* convert foreground to xz coordinates where x direction is - defined by key color */ - xx = (((fg_cb[pos]) * cb) + ((fg_cr[pos]) * cr)) >> 7; + val = (xx * accept_angle_tg) >> 4; + if (val > 127) + val = 127; + + if (abs(yy) < val ) + { + val = (yy * accept_angle_ctg) >> 4; - if (xx < -128) { - xx = -128; - } - if (xx > 127) { - xx = 127; - } + x1 = abs(val); + y1 = yy; + tmp1 = xx - x1; - yy = (((fg_cr[pos]) * cb) - ((fg_cb[pos]) * cr)) >> 7; + kbg = (tmp1 * one_over_kc) >> 1; + if (kbg < 0) + kbg = 0; + if (kbg > 255) + kbg = 255; + + val = (tmp1 * kfgy_scale) >> 4; + val = fg_y[pos] - val; + Y[pos] = val; + val = ((x1 * (cb-128)) - (y1 * (cr-128))) >> 7; + Cb[pos] = val; + val = ((x1 * (cr-128)) - (y1 * (cb-128))) >> 7; + Cr[pos] = val; + + val = (yy * yy) + (kg * kg); + if (val < (noise_level * noise_level)) { + kbg = 255; + } + + val = 255 - ((Y[pos] + (kbg * bg_y[pos])) >> 8); + if (val < 16) + val = 16; + else if (val > 235) + val = 235; + Y[pos] = val; + + val = 255 - ((Cb[pos] + (kbg * bg_cb[pos])) >> 8); + if (val < 16) + val = 16; + else if (val > 240) + val = 240; + Cb[pos] = val; + + val = 255 - ( (Cr[pos] + (kbg * bg_cr[pos])) >> 8); + if (val < 16) + val = 16; + else if (val > 240) + val = 240; + Cr[pos] = val; - if (yy < -128) { - yy = -128; - } - if (yy > 127) { - yy = 127; - } - val = (xx * accept_angle_tg) >> 4; - if (val > 127) - val = 127; - /* see if pixel is within range of color and invert it */ - if (abs(yy) < val ) { - Y[pos] = 255 - Y[pos]; - Cb[pos] = 255 - Cb[pos]; - Cr[pos] = 255 - Cr[pos]; } } - } } void complexinvert_free(){} diff --git a/veejay-current/libvje/effects/complexinvert.h b/veejay-current/libvje/effects/complexinvert.h index 99207cf8..e1f629d2 100644 --- a/veejay-current/libvje/effects/complexinvert.h +++ b/veejay-current/libvje/effects/complexinvert.h @@ -27,6 +27,6 @@ vj_effect *complexinvert_init(); void complexinvert_apply(VJFrame *frame, int width, int height, int i_angle, - int red, int green, int blue, int level); + int red, int green, int blue, int i_noise); void complexinvert_free(); #endif diff --git a/veejay-current/libvje/effects/complexopacity.c b/veejay-current/libvje/effects/complexopacity.c new file mode 100644 index 00000000..d4156b4f --- /dev/null +++ b/veejay-current/libvje/effects/complexopacity.c @@ -0,0 +1,222 @@ +/* + * Linux VeeJay + * + * Copyright(C)2004 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 "rgbkey.h" +#include +#include +#include +#include +#include +#include "common.h" +#include "complexopacity.h" + + +vj_effect *complexopacity_init(int w, int h) +{ + vj_effect *ve; + ve = (vj_effect *) vj_malloc(sizeof(vj_effect)); + ve->num_params = 5; + 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->defaults[0] = 80; /* angle */ + ve->defaults[1] = 0; /* r */ + ve->defaults[2] = 0; /* g */ + ve->defaults[3] = 255; /* b */ + ve->defaults[4] = 150; /* opacity */ + ve->limits[0][0] = 5; + ve->limits[1][0] = 900; + + ve->limits[0][1] = 0; + ve->limits[1][1] = 255; + + ve->limits[0][2] = 0; + ve->limits[1][2] = 255; + + ve->limits[0][3] = 0; + ve->limits[1][3] = 255; + + ve->limits[0][4] = 0; + ve->limits[1][4] = 255; + ve->has_user = 0; + ve->description = "Complex Overlay"; + ve->extra_frame = 1; + ve->sub_format = 1; + ve->rgb_conv = 1; + return ve; +} + +/* this method decides whether or not a pixel from the fg will be accepted for keying */ +int accept_ipixel(uint8_t fg_cb, uint8_t fg_cr, int cb, int cr, + int accept_angle_tg) +{ + short xx, yy; + /* convert foreground to xz coordinates where x direction is + defined by key color */ + uint8_t val; + + xx = ((fg_cb * cb) + (fg_cr * cr)) >> 7; + + if (xx < -128) { + xx = -128; + } + if (xx > 127) { + xx = 127; + } + + yy = ((fg_cr * cb) - (fg_cb * cr)) >> 7; + + if (yy < -128) { + yy = -128; + } + if (yy > 127) { + yy = 127; + } + + + /* accept angle should not be > 90 degrees + reasonable results between 10 and 80 degrees. + */ + + val = (xx * accept_angle_tg) >> 4; + if (val > 127) + val = 127; + if (abs(yy) < val) { + return 1; + } + return 0; +} + +void complexopacity_apply(VJFrame *frame, int width, + int height, int i_angle, int r, int g, int b, + int level ) +{ + + uint8_t *fg_y, *fg_cb, *fg_cr; + uint8_t *bg_y, *bg_cb, *bg_cr; + int accept_angle_tg, accept_angle_ctg, one_over_kc; + int kfgy_scale, kg; + + int cb, cr; + float kg1, tmp, aa = 128, bb = 128, _y = 0; + float angle = (float) i_angle / 10.0; + //float noise_level = 350.0; + unsigned int pos; + int matrix[5]; + uint8_t val; + const int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + int iy,iu,iv; + _rgb2yuv(r,g,b,iy,iu,iv); + _y = (float) iy; + aa = (float) iu; + bb = (float) iv; + tmp = sqrt(((aa * aa) + (bb * bb))); + cb = 127 * (aa / tmp); + cr = 127 * (bb / tmp); + kg1 = tmp; + + /* obtain coordinate system for cb / cr */ + accept_angle_tg = 0xf * tan(M_PI * angle / 180.0); + accept_angle_ctg = 0xf / tan(M_PI * angle / 180.0); + + tmp = 1 / kg1; + one_over_kc = 0xff * 2 * tmp - 0xff; + kfgy_scale = 0xf * (float) (_y) / kg1; + kg = kg1; + + /* intialize pointers */ + fg_y = frame->data[0]; + fg_cb = frame->data[1]; + fg_cr = frame->data[2]; + + bg_y = frame->data[0]; + bg_cb = frame->data[1]; + bg_cr = frame->data[2]; + + for (pos = width + 1; pos < (len) - width - 1; pos++) { + int i = 0; + int smooth = 0; + /* setup matrix + [ - 0 - ] = do not accept. [ - 1 - ] = level 5 , accept only when all n = 1 + [ 0 0 0 ] [ 1 1 1 ] + [ - 0 - ] [ - 1 - ] + + [ - 0 - ] sum of all n is acceptance value for level + [ 1 0 1 ] + [ 0 1 0 ] + */ + matrix[0] = accept_ipixel(fg_cb[pos], fg_cr[pos], cb, cr, accept_angle_tg); /* center pixel */ + matrix[1] = accept_ipixel(fg_cb[pos - 1], fg_cr[pos - 1], cb, cr, accept_angle_tg); /* left pixel */ + matrix[2] = accept_ipixel(fg_cb[pos + 1], fg_cr[pos + 1], cb, cr, accept_angle_tg); /* right pixel */ + matrix[3] = accept_ipixel(fg_cb[pos + width], fg_cr[pos + width], cb, cr, accept_angle_tg); /* top pixel */ + matrix[4] = accept_ipixel(fg_cb[pos - width], fg_cr[pos - width], cb, cr, accept_angle_tg); /* bottom pixel */ + for (i = 0; i < 5; i++) { + if (matrix[i] == 1) + smooth++; + } + if (smooth >= level) { + short xx, yy; + /* get bg/fg pixels */ + uint8_t p1 = (matrix[0] == 0 ? fg_y[pos] : bg_y[pos]); + uint8_t p2 = (matrix[1] == 0 ? fg_y[pos - 1] : bg_y[pos - 1]); + uint8_t p3 = (matrix[2] == 0 ? fg_y[pos + 1] : bg_y[pos + 1]); + uint8_t p4 = + (matrix[3] == 0 ? fg_y[pos + width] : bg_y[pos + width]); + uint8_t p5 = + (matrix[4] == 0 ? fg_y[pos - width] : bg_y[pos - width]); + /* and blur the pixel */ + fg_y[pos] = (p1 + p2 + p3 + p4 + p5) / 5; + + /* convert foreground to xz coordinates where x direction is + defined by key color */ + xx = (((fg_cb[pos]) * cb) + ((fg_cr[pos]) * cr)) >> 7; + + if (xx < -128) { + xx = -128; + } + if (xx > 127) { + xx = 127; + } + + yy = (((fg_cr[pos]) * cb) - ((fg_cb[pos]) * cr)) >> 7; + + if (yy < -128) { + yy = -128; + } + if (yy > 127) { + yy = 127; + } + + val = (xx * accept_angle_tg) >> 4; + if (val > 127) + val = 127; + /* see if pixel is within range of color and opacity it */ + if (abs(yy) < val ) { + Y[pos] = 255 - Y[pos]; + Cb[pos] = 255 - Cb[pos]; + Cr[pos] = 255 - Cr[pos]; + } + } + } +} +void complexopacity_free(){} diff --git a/veejay-current/libvje/effects/complexsaturate.c b/veejay-current/libvje/effects/complexsaturate.c index 4e8c0fd0..1be90715 100644 --- a/veejay-current/libvje/effects/complexsaturate.c +++ b/veejay-current/libvje/effects/complexsaturate.c @@ -30,17 +30,17 @@ vj_effect *complexsaturation_init(int w, int h) { vj_effect *ve; ve = (vj_effect *) vj_malloc(sizeof(vj_effect)); - ve->num_params = 6; + ve->num_params = 7; 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->defaults[0] = 80; /* angle */ - ve->defaults[1] = 0; /* r */ + ve->defaults[0] = 300; /* angle */ + ve->defaults[1] = 255; /* r */ ve->defaults[2] = 0; /* g */ - ve->defaults[3] = 255; /* b */ - ve->defaults[4] = 20; /* v_adjust */ - ve->defaults[5] = 1500; /* degrees */ - + ve->defaults[3] = 0; /* b */ + ve->defaults[4] = -46; /* v_adjust */ + ve->defaults[5] = 26000; /* degrees */ + ve->defaults[6] = 2400; /* noise suppression */ ve->limits[0][0] = 5; ve->limits[1][0] = 900; @@ -53,43 +53,51 @@ vj_effect *complexsaturation_init(int w, int h) ve->limits[0][3] = 0; ve->limits[1][3] = 255; - ve->limits[0][4] = -255; - ve->limits[1][4] = 255; + ve->limits[0][4] = -300; + ve->limits[1][4] = 300; - ve->limits[0][5] = 0; + ve->limits[0][5] = 1; ve->limits[1][5] = 36000; + + ve->limits[0][6] = 0; + ve->limits[1][6] = 3500; ve->has_user = 0; ve->description = "Complex Saturation"; ve->extra_frame = 0; ve->sub_format = 1; + ve->rgb_conv = 1; return ve; } void complexsaturation_apply(VJFrame *frame, int width, int height, int i_angle, int r, int g, - int b, int adjust_v, int adjust_degrees) + int b, int adjust_v, int adjust_degrees, int i_noise) { - - uint8_t *fg_y, *fg_cb, *fg_cr; - uint8_t *bg_y, *bg_cb, *bg_cr; - int accept_angle_tg, accept_angle_ctg, one_over_kc; + double dsaturation,dcolor; + double degrees = adjust_degrees * 0.01; + double dsat = adjust_v * 0.01; + uint8_t *fg_y, *fg_cb, *fg_cr; + uint8_t *bg_y, *bg_cb, *bg_cr; + int accept_angle_tg, accept_angle_ctg, one_over_kc; int kfgy_scale, kg; int cb, cr; + int kbg, x1, y1; float kg1, tmp, aa = 128, bb = 128, _y = 0; - float angle = (float) i_angle / 10.0; + float angle = (float) i_angle * 0.1f; + float noise_level = (i_noise * 0.01f); unsigned int pos; - uint8_t val; - double dsaturation, dcolor; - double degrees = ( adjust_degrees / 100.0); - double dsat = adjust_v / 100.0; - const int len = frame->len; - uint8_t *Y = frame->data[0]; - uint8_t *Cb = frame->data[1]; - uint8_t *Cr = frame->data[2]; - - _y = ((Y_Redco * r) + (Y_Greenco * g) + (Y_Blueco * b) + 16); - aa = ((U_Redco * r) - (U_Greenco * g) - (U_Blueco * b) + 128); - bb = (-(V_Redco * r) - (V_Greenco * g) + (V_Blueco * b) + 128); + uint8_t val, tmp1; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + uint8_t *Y2 = frame->data[0]; + uint8_t *Cb2= frame->data[1]; + uint8_t *Cr2= frame->data[2]; + int iy=16,iu=128,iv=128; + _rgb2yuv( r,g,b, iy,iu,iv ); + _y = (float) iy; + aa = (float) iu; + bb = (float) iv; tmp = sqrt(((aa * aa) + (bb * bb))); cb = 127 * (aa / tmp); cr = 127 * (bb / tmp); @@ -98,45 +106,103 @@ void complexsaturation_apply(VJFrame *frame, int width, /* obtain coordinate system for cb / cr */ accept_angle_tg = 0xf * tan(M_PI * angle / 180.0); accept_angle_ctg = 0xf / tan(M_PI * angle / 180.0); - + tmp = 1 / kg1; one_over_kc = 0xff * 2 * tmp - 0xff; kfgy_scale = 0xf * (float) (_y) / kg1; kg = kg1; /* intialize pointers */ - fg_y = Y; - fg_cb = Cb; - fg_cr = Cr; + fg_y = frame->data[0]; + fg_cb = frame->data[1]; + fg_cr = frame->data[2]; - bg_y = Y; - bg_cb = Cb; - bg_cr = Cr; + bg_y = frame->data[0]; + bg_cb = frame->data[1]; + bg_cr = frame->data[2]; - for (pos = len; pos != 0; pos--) { - short xx, yy; - xx = (((fg_cb[pos>>2]) * cb) + ((fg_cr[pos>>2]) * cr)) >> 7; - if (xx < -128) { - xx = -128; - } - if (xx > 127) { - xx = 127; - } - yy = (((fg_cr[pos>>2]) * cb) - ((fg_cb[pos>>2]) * cr)) >> 7; - if (yy < -128) { - yy = -128; - } - if (yy > 127) { - yy = 127; - } - val = (xx * accept_angle_tg) >> 4; - if (val > 127) - val = 127; + for (pos = 0; pos < frame->len; pos++) + { + short xx, yy; + + xx = (((fg_cb[pos]) * cb) + ((fg_cr[pos]) * cr)) >> 7; + + if (xx < -128) + xx = -128; + + if (xx > 127) + xx = 127; + + + yy = (((fg_cr[pos]) * cb) - ((fg_cb[pos]) * cr)) >> 7; + + if (yy < -128) + yy = -128; + + if (yy > 127) + yy = 127; + + + + /* accept angle should not be > 90 degrees + reasonable results between 10 and 80 degrees. + */ + + val = (xx * accept_angle_tg) >> 4; + if (val > 127) + val = 127; if (abs(yy) > val) { /* pixel is within selected color range, saturate */ + val = (yy * accept_angle_ctg) >> 4; + + x1 = abs(val); + y1 = yy; + tmp1 = xx - x1; + + kbg = (tmp1 * one_over_kc) >> 1; + if (kbg < 0) + kbg = 0; + if (kbg > 255) + kbg = 255; + + val = (tmp1 * kfgy_scale) >> 4; + val = fg_y[pos] - val; + Y[pos] = val; + val = ((x1 * (cb-128)) - (y1 * (cr-128))) >> 7; + Cb[pos] = val; + val = ((x1 * (cr-128)) - (y1 * (cb-128))) >> 7; + Cr[pos] = val; + + val = (yy * yy) + (kg * kg); + if (val < (noise_level * noise_level)) { + kbg = 255; + } + + val = (Y[pos] + (kbg * bg_y[pos])) >> 8; + if (val < 16) + val = 16; + else if (val > 235) + val = 235; + Y[pos] = val; + + val = (Cb[pos] + (kbg * bg_cb[pos])) >> 8; + if (val < 16) + val = 16; + else if (val > 240) + val = 240; + Cb[pos] = val; + + val = (Cr[pos] + (kbg * bg_cr[pos])) >> 8; + if (val < 16) + val = 16; + else if (val > 240) + val = 240; + Cr[pos] = val; + int _cb = Cb[pos] - 128; int _cr = Cr[pos] - 128; - if( _cb != 0 && _cr != 0) { + if( _cb != 0 && _cr != 0) + { double co=0.0,si=0.0; //fast_sqrt( dsaturation, (double) (_cb * cr + _cr * _cr) ); dsaturation = ccolor_sqrt( (double) _cb, (double) _cr); @@ -150,8 +216,9 @@ void complexsaturation_apply(VJFrame *frame, int width, Cb[pos] = si * dsaturation + 128; Cr[pos] = co * dsaturation + 128; } + } + } - } } void complexsaturate_free(){} diff --git a/veejay-current/libvje/effects/complexsaturate.h b/veejay-current/libvje/effects/complexsaturate.h index 846d114e..c85de617 100644 --- a/veejay-current/libvje/effects/complexsaturate.h +++ b/veejay-current/libvje/effects/complexsaturate.h @@ -27,6 +27,6 @@ vj_effect *complexsaturation_init(); void complexsaturation_apply(VJFrame *frame, int width, int height, int i_angle, - int red, int green, int blue, int adjust_degrees, int adjust_v ); + int red, int green, int blue, int adjust_degrees, int adjust_v, int i_noise ); void complexsaturate_free(); #endif diff --git a/veejay-current/libvje/effects/complexthreshold.c b/veejay-current/libvje/effects/complexthreshold.c index 8a7b43a8..d6c0e285 100644 --- a/veejay-current/libvje/effects/complexthreshold.c +++ b/veejay-current/libvje/effects/complexthreshold.c @@ -58,10 +58,11 @@ vj_effect *complexthreshold_init(int w, int h) ve->limits[1][5] = 255; ve->limits[0][4] = 0; ve->limits[1][4] = 4; - ve->description = "Complex Threshold"; + ve->description = "Complex Threshold (fixme)"; ve->extra_frame = 1; ve->sub_format = 1; ve->has_user = 0; + ve->rgb_conv = 1; return ve; } @@ -131,10 +132,12 @@ void complexthreshold_apply(VJFrame *frame, VJFrame *frame2, int width, uint8_t *Y2 = frame2->data[0]; uint8_t *Cb2 = frame2->data[1]; uint8_t *Cr2 = frame2->data[2]; + int iy,iv,iu; + _rgb2yuv(r,g,b,iy,iu,iv); + _y = (float)iy; + aa = (float)iu; + bb = (float)iv; - _y = ((Y_Redco * r) + (Y_Greenco * g) + (Y_Blueco * b) + 16); - aa = ((Y_Redco * r) - (U_Greenco * g) - (U_Blueco * b) + 128); - bb = (-(Y_Redco * r) - (V_Greenco * g) + (V_Blueco * b) + 128); tmp = sqrt(((aa * aa) + (bb * bb))); cb = 127 * (aa / tmp); cr = 127 * (bb / tmp); @@ -150,13 +153,13 @@ void complexthreshold_apply(VJFrame *frame, VJFrame *frame2, int width, kg = kg1; /* intialize pointers */ - fg_y = Y; - fg_cb = Cb; - fg_cr = Cr; + fg_y = Y2; + fg_cb = Cb2; + fg_cr = Cr2; - bg_y = Y2; - bg_cb = Cb2; - bg_cr = Cr2; + bg_y = Y; + bg_cb = Cb; + bg_cr = Cr; for (pos = width + 1; pos < (len) - width - 1; pos++) { int i = 0; diff --git a/veejay-current/libvje/effects/dummy.c b/veejay-current/libvje/effects/dummy.c index 9ab9047b..83ae8eaf 100644 --- a/veejay-current/libvje/effects/dummy.c +++ b/veejay-current/libvje/effects/dummy.c @@ -18,9 +18,11 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. */ -#include "dummy.h" -#include "common.h" +#include #include +#include +#include + vj_effect *dummy_init(int w, int h) { @@ -47,16 +49,15 @@ vj_effect *dummy_init(int w, int h) ve->has_user= 0; return ve; } - void dummy_apply( VJFrame *frame, int width, int height, int color) { const int len = frame->len; - const int uv_len = frame->uv_len; + const int uv_len = frame->uv_len; char colorCb, colorCr, colorY; - uint8_t *Y = frame->data[0]; - uint8_t *Cb = frame->data[1]; - uint8_t *Cr = frame->data[2]; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; colorY = bl_pix_get_color_y(color); colorCb = bl_pix_get_color_cb(color); @@ -66,4 +67,22 @@ void dummy_apply( VJFrame *frame, int width, int height, int color) memset( Cb,colorCb,uv_len); memset( Cr,colorCr,uv_len); } + +void dummy_rgb_apply( VJFrame *frame, int width, int height, int r,int g, int b) +{ + const int len = frame->len; + const int uv_len = frame->uv_len; + int colorCb, colorCr, colorY; + + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + + + _rgb2yuv(r,g,b,colorY,colorCb,colorCr); + + memset( Y, colorY, len); + memset( Cb,colorCb,uv_len); + memset( Cr,colorCr,uv_len); +} void dummy_free(){} diff --git a/veejay-current/libvje/effects/dummy.h b/veejay-current/libvje/effects/dummy.h index d5a92293..f202d504 100644 --- a/veejay-current/libvje/effects/dummy.h +++ b/veejay-current/libvje/effects/dummy.h @@ -26,5 +26,6 @@ vj_effect *dummy_init(); void dummy_apply(VJFrame *frame, int width, int height, int n); +void dummy_rgb_apply(VJFrame *frame, int width, int height, int r, int g, int b); void dummy_free(); #endif diff --git a/veejay-current/libvje/effects/greyselect.c b/veejay-current/libvje/effects/greyselect.c index bd183072..1f438738 100644 --- a/veejay-current/libvje/effects/greyselect.c +++ b/veejay-current/libvje/effects/greyselect.c @@ -34,10 +34,10 @@ vj_effect *greyselect_init(int w, int h) 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->defaults[0] = 10; /* angle */ - ve->defaults[1] = 0; /* r */ + ve->defaults[0] = 300; /* angle */ + ve->defaults[1] = 255; /* r */ ve->defaults[2] = 0; /* g */ - ve->defaults[3] = 255; /* b */ + ve->defaults[3] = 0; /* b */ ve->limits[0][0] = 5; ve->limits[1][0] = 900; @@ -53,6 +53,7 @@ vj_effect *greyselect_init(int w, int h) ve->description = "Grayscale by Color Key"; ve->extra_frame = 0; ve->sub_format = 1; + ve->rgb_conv = 1; return ve; } @@ -73,11 +74,12 @@ void greyselect_apply( VJFrame *frame, int width, uint8_t *Y = frame->data[0]; uint8_t *Cb = frame->data[1]; uint8_t *Cr = frame->data[2]; + int iy,iu,iv; + _rgb2yuv(r,g,b,iy,iu,iv); + _y = (float) iy; + aa = (float) iu; + bb = (float) iv; - - _y = ((Y_Redco * r) + (Y_Greenco * g) + (Y_Blueco * b) + 16); - aa = ((U_Redco * r) - (U_Greenco * g) - (U_Blueco * b) + 128); - bb = (-(V_Redco * r) - (V_Greenco * g) + (V_Blueco * b) + 128); tmp = sqrt(((aa * aa) + (bb * bb))); cb = 127 * (aa / tmp); cr = 127 * (bb / tmp); diff --git a/veejay-current/libvje/effects/isolate.c b/veejay-current/libvje/effects/isolate.c index 727707c6..cd1112b2 100644 --- a/veejay-current/libvje/effects/isolate.c +++ b/veejay-current/libvje/effects/isolate.c @@ -34,8 +34,8 @@ vj_effect *isolate_init(int w, int h) 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->defaults[0] = 20; /* angle */ - ve->defaults[1] = 0; /* r */ + ve->defaults[0] = 300; /* angle */ + ve->defaults[1] = 255; /* r */ ve->defaults[2] = 0; /* g */ ve->defaults[3] = 0; /* b */ ve->defaults[4] = 150; /* white transparency */ @@ -57,6 +57,7 @@ vj_effect *isolate_init(int w, int h) ve->description = "Isolate Color"; ve->extra_frame = 0; ve->sub_format = 1; + ve->rgb_conv = 1; return ve; } @@ -82,10 +83,11 @@ void isolate_apply( VJFrame *frame, int width, uint8_t *Y = frame->data[0]; uint8_t *Cb = frame->data[1]; uint8_t *Cr = frame->data[2]; - - _y = ((Y_Redco * r) + (Y_Greenco * g) + (Y_Blueco * b) + 16); - aa = ((U_Redco * r) - (U_Greenco * g) - (U_Blueco * b) + 128); - bb = (-(V_Redco * r) - (V_Greenco * g) + (V_Blueco * b) + 128); + int iy,iu,iv; + _rgb2yuv(r,g,b,iy,iu,iv); + _y = (float) iy; + aa = (float) iu; + bb = (float) iv; tmp = sqrt(((aa * aa) + (bb * bb))); cb = 127 * (aa / tmp); cr = 127 * (bb / tmp); diff --git a/veejay-current/libvje/effects/keyselect.c b/veejay-current/libvje/effects/keyselect.c index 6b409ca3..8a695cac 100644 --- a/veejay-current/libvje/effects/keyselect.c +++ b/veejay-current/libvje/effects/keyselect.c @@ -30,15 +30,16 @@ vj_effect *keyselect_init(int w, int h) { vj_effect *ve; ve = (vj_effect *) vj_malloc(sizeof(vj_effect)); - ve->num_params = 5; + ve->num_params = 6; 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->defaults[0] = 10; /* angle */ - ve->defaults[1] = 0; /* r */ + ve->defaults[0] = 300; /* angle */ + ve->defaults[1] = 255; /* r */ ve->defaults[2] = 0; /* g */ - ve->defaults[3] = 255; /* b */ - ve->defaults[4] = 1; /* blend type */ + ve->defaults[3] = 0; /* b */ + ve->defaults[4] = 3; /* blend type */ + ve->defaults[5] = 2400; /* noise suppression */ ve->limits[0][0] = 5; ve->limits[1][0] = 900; @@ -52,11 +53,15 @@ vj_effect *keyselect_init(int w, int h) ve->limits[1][3] = 256; ve->limits[0][4] = 0; - ve->limits[1][4] = 7; /* total noise suppression off */ + ve->limits[1][4] = 7; + + ve->limits[0][5] = 0; + ve->limits[1][5] = 3500; ve->has_user = 0; ve->description = "Blend by Color Key"; ve->extra_frame = 1; ve->sub_format = 1; + ve->rgb_conv = 1; return ve; } @@ -141,38 +146,42 @@ http://www.cs.utah.edu/~michael/chroma/ */ void keyselect_apply( VJFrame *frame, VJFrame *frame2, int width, int height, int i_angle, int r, int g, - int b, int mode) + int b, int mode, int i_noise) { - uint8_t *fg_y, *fg_cb, *fg_cr; + uint8_t *fg_y, *fg_cb, *fg_cr; uint8_t *bg_y, *bg_cb, *bg_cr; int accept_angle_tg, accept_angle_ctg, one_over_kc; int kfgy_scale, kg; int cb, cr; + int kbg, x1, y1; float kg1, tmp, aa = 128, bb = 128, _y = 0; - float angle = (float) i_angle / 10.0; + float angle = (float) i_angle * 0.1f; + float noise_level = (i_noise * 0.01f); unsigned int pos; - uint8_t val; - uint8_t *Y = frame->data[0]; - uint8_t *Cb = frame->data[1]; - uint8_t *Cr = frame->data[2]; - uint8_t *Y2 = frame2->data[0]; - uint8_t *Cb2=frame2->data[1]; - uint8_t *Cr2=frame2->data[2]; - - blend_func blend_pixel; - _y = ((Y_Redco * r) + (Y_Greenco * g) + (Y_Blueco * b) + 16); - aa = ((U_Redco * r) - (U_Greenco * g) - (U_Blueco * b) + 128); - bb = (-(V_Redco * r) - (V_Greenco * g) + (V_Blueco * b) + 128); + uint8_t val, tmp1; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2= frame2->data[1]; + uint8_t *Cr2= frame2->data[2]; + int iy=16,iu=128,iv=128; + _rgb2yuv( r,g,b, iy,iu,iv ); + _y = (float) iy; + aa = (float) iu; + bb = (float) iv; tmp = sqrt(((aa * aa) + (bb * bb))); cb = 127 * (aa / tmp); cr = 127 * (bb / tmp); kg1 = tmp; - /* obtain coordinate system for cb / cr */ + + blend_func blend_pixel = get_blend_func(mode); + + /* obtain coordinate system for cb / cr */ accept_angle_tg = 0xf * tan(M_PI * angle / 180.0); accept_angle_ctg = 0xf / tan(M_PI * angle / 180.0); - blend_pixel = get_blend_func((const int)mode); - + tmp = 1 / kg1; one_over_kc = 0xff * 2 * tmp - 0xff; kfgy_scale = 0xf * (float) (_y) / kg1; @@ -182,34 +191,81 @@ void keyselect_apply( VJFrame *frame, VJFrame *frame2, int width, fg_y = Y; fg_cb = Cb; fg_cr = Cr; - - bg_y = Y2; + /* 2005: swap these !! */ + bg_y = Y2; bg_cb = Cb2; bg_cr = Cr2; for (pos = (width * height); pos != 0; pos--) { short xx, yy; + /* convert foreground to xz coordinates where x direction is + defined by key color */ + xx = (((fg_cb[pos]) * cb) + ((fg_cr[pos]) * cr)) >> 7; + if (xx < -128) { xx = -128; } if (xx > 127) { xx = 127; } + yy = (((fg_cr[pos]) * cb) - ((fg_cb[pos]) * cr)) >> 7; + if (yy < -128) { yy = -128; } if (yy > 127) { - yy = 127; + yy = 127; } + + + /* accept angle should not be > 90 degrees + reasonable results between 10 and 80 degrees. + */ + val = (xx * accept_angle_tg) >> 4; if (val > 127) val = 127; if (abs(yy) < val) { - Y[pos] = blend_pixel(Y[pos],Y2[pos]); + /* compute fg, suppress fg in xz according to kfg + */ + val = (yy * accept_angle_ctg) >> 4; + + x1 = abs(val); + y1 = yy; + tmp1 = xx - x1; + + kbg = (tmp1 * one_over_kc) >> 1; + if (kbg < 0) + kbg = 0; + if (kbg > 255) + kbg = 255; + + val = (tmp1 * kfgy_scale) >> 4; + val = fg_y[pos] - val; + + Y[pos] = val; + + // convert suppressed fg back to cbcr + // cb,cr are signed, go back to unsigned ! + val = ((x1 * (cb-128)) - (y1 * (cr-128))) >> 7; + Cb[pos] = val; + val = ((x1 * (cr-128)) - (y1 * (cb-128))) >> 7; + Cr[pos] = val; + // deal with noise + + val = (yy * yy) + (kg * kg); + if (val < (noise_level * noise_level)) { + kbg = 255; + } + val = (Y[pos] + (kbg * bg_y[pos])) >> 8; + Y[pos] = blend_pixel( val, fg_y[pos] ); + } } + + } void keyselect_free(){} diff --git a/veejay-current/libvje/effects/keyselect.h b/veejay-current/libvje/effects/keyselect.h index 8880dd80..8837aa15 100644 --- a/veejay-current/libvje/effects/keyselect.h +++ b/veejay-current/libvje/effects/keyselect.h @@ -27,6 +27,6 @@ vj_effect *keyselect_init(); void keyselect_apply( VJFrame *frame, VJFrame *frame2, int width, int height, int i_angle, - int red, int green, int blue, int mode); + int red, int green, int blue, int mode, int noise); void keyselect_free(); #endif diff --git a/veejay-current/libvje/effects/magicphotos.c b/veejay-current/libvje/effects/magicphotos.c new file mode 100644 index 00000000..cb04d04f --- /dev/null +++ b/veejay-current/libvje/effects/magicphotos.c @@ -0,0 +1,227 @@ +/* + * 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 "photoplay.h" +#include +#include "common.h" + +vj_effect *photoplay_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] = 2; // divider + ve->limits[1][0] = max_power(w); + ve->limits[0][1] = 0; + ve->limits[1][1] = 1; // waterfall + ve->limits[0][2] = 0; + ve->limits[1][2] = 3; // mode + ve->defaults[0] = 2; + ve->defaults[1] = 0; + ve->defaults[2] = 1; + ve->description = "Photoplay (timestretched mosaic)"; + ve->sub_format = 1; + ve->extra_frame = 0; + ve->has_user = 0; + return ve; +} + +static picture_t **photo_list = NULL; +static int num_photos = 0; +static int frame_counter = 0; + + +static int prepare_filmstrip(int film_length, int w, int h) +{ + int i,j; + int picture_width = w / sqrt(film_length); + int picture_height = h / sqrt(film_length); + + photo_list = (picture_t**) vj_malloc(sizeof(picture_t*) * (film_length + 1) ); + if(!photo_list) + return 0; + + num_photos = film_length; + + uint8_t val = 0; + int inc = num_photos % 255; + + for ( i = 0; i < num_photos; i ++ ) + { + photo_list[i] = vj_malloc(sizeof(picture_t)); + if(!photo_list[i]) + return 0; + photo_list[i]->w = picture_width; + photo_list[i]->h = picture_height; + for( j = 0; j < 3; j ++ ) + { + photo_list[i]->data[j] = vj_malloc(sizeof(uint8_t) * picture_width * picture_height ); + if(!photo_list[i]->data[j]) + return 0; + memset(photo_list[i]->data[j], (j==0 ? val : 128), picture_width *picture_height ); + } + val+= inc; + } + frame_counter = 0; + + return 1; +} + +static void destroy_filmstrip(void) +{ + if(photo_list) + { + int i = 0; + while(i < num_photos) + { + if( photo_list[i] ) + { + int j; + for( j = 0; j < 3; j ++ ) + if(photo_list[i]->data[j]) + free(photo_list[i]->data[j]); + free(photo_list[i]); + } + i++; + } + free(photo_list); + } + photo_list = NULL; + num_photos = 0; + frame_counter = 0; +} + + + +int photoplay_malloc(int w, int h ) +{ + num_photos = 0; + return 1; +} + + +void photoplay_free(void) +{ + destroy_filmstrip(); +} + +static void take_photo( uint8_t *plane, uint8_t *dst_plane, int w, int h, int index ) +{ + + int x,y,dx,dy; + int sum; + int dst_x, dst_y; + int step_y; + int step_x; + int box_width = photo_list[index]->w; + int box_height = photo_list[index]->h; + + step_x = w / box_width; + step_y = h / box_height; + + for( y = 0 ,dst_y = 0; y < h && dst_y < box_height; y += step_y ) + { + for( x = 0, dst_x = 0; x < w && dst_x < box_width; x+= step_x ) + { + sum = 0; + for( dy = 0; dy < step_y; dy ++ ) + { + for( dx = 0; dx < step_x; dx++) + { + sum += plane[ ((y+dy)*w+(dx+x)) ]; + } + } + // still problem here! + if(sum > 0) + dst_plane[(dst_y*box_width)+dst_x] = sum / (step_y*step_x); + else + dst_plane[(dst_y*box_width)+dst_x] = 16; + + dst_x++; + } + dst_y++; + } +} + +static void put_photo( uint8_t *dst_plane, uint8_t *photo, int dst_w, int dst_h, int index , matrix_t matrix) +{ + int box_w = photo_list[index]->w; + int box_h = photo_list[index]->h; + int x,y; + + uint8_t *P = dst_plane + (matrix.h*dst_w); + int offset = matrix.w; + + for( y = 0; y < box_h; y ++ ) + { + for( x = 0; x < box_w; x ++ ) + { + *(P+offset+x) = photo[(y*box_w)+x]; + } + P += dst_w; + } +} + +void photoplay_apply( VJFrame *frame, int width, int height, int size, int delay, int mode ) +{ + unsigned int i; + uint8_t *dstY = frame->data[0]; + uint8_t *dstU = frame->data[1]; + uint8_t *dstV = frame->data[2]; + + matrix_f matrix_placement = get_matrix_func(mode); + + if( (size*size) != num_photos || num_photos == 0 ) + { + destroy_filmstrip(); + if(!prepare_filmstrip(size*size, width,height)) + { + return; + } + } + + + if(frame_counter < num_photos) + { + for( i = 0; i < 3 ; i ++ ) + memset( frame->data[i], (i==0?16:128), (width*height)); + frame_counter ++; + return; + } + + for( i = 0; i < 3; i ++ ) + { + take_photo( frame->data[i], photo_list[(frame_counter%num_photos)]->data[i], width, height , frame_counter % num_photos); + } + + for ( i = 0; i < num_photos; i ++ ) + { + matrix_t m = matrix_placement(i, size,width,height ); + put_photo( dstY, photo_list[i]->data[0],width,height,i, m); + put_photo( dstU, photo_list[i]->data[1],width,height,i, m); + put_photo( dstV, photo_list[i]->data[2],width,height,i, m); + } + + + frame_counter ++; +} + diff --git a/veejay-current/libvje/effects/neighbours.c b/veejay-current/libvje/effects/neighbours.c index 7044f50a..e62eb0a9 100644 --- a/veejay-current/libvje/effects/neighbours.c +++ b/veejay-current/libvje/effects/neighbours.c @@ -233,7 +233,7 @@ void neighbours_apply( VJFrame *frame, int width, int height, int brush_size, in if(!mode) { - for( y = 0; y < height; y ++ ) + for( y = 0; y < height-1; y ++ ) { for( x = 0; x < width; x ++ ) { diff --git a/veejay-current/libvje/effects/neighbours2.c b/veejay-current/libvje/effects/neighbours2.c index 65535e27..f58e1a0b 100644 --- a/veejay-current/libvje/effects/neighbours2.c +++ b/veejay-current/libvje/effects/neighbours2.c @@ -235,7 +235,7 @@ void neighbours2_apply( VJFrame *frame, int width, int height, int brush_size, i if(!mode) { - for( y = 0; y < height; y ++ ) + for( y = 0; y < height-1; y ++ ) { for( x = 0; x < width; x ++ ) { diff --git a/veejay-current/libvje/effects/neighbours3.c b/veejay-current/libvje/effects/neighbours3.c index 3351a5d5..88c1d5ad 100644 --- a/veejay-current/libvje/effects/neighbours3.c +++ b/veejay-current/libvje/effects/neighbours3.c @@ -140,10 +140,18 @@ static inline pixel_t evaluate_pixel_bc( } 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; - + if( peak_value > 0 ) + { + val.y = y_map[peak_index] / peak_value; + val.u = cb_map[peak_index] / peak_value; + val.v = cr_map[peak_index] / peak_value; + } + else + { + val.y = y_map[y * w + x]; + val.u = cb_map[y * w + x]; + val.v = cb_map[y * w + x]; + } return val; } @@ -250,7 +258,7 @@ void neighbours3_apply( VJFrame *frame, int width, int height, int brush_size, i else { pixel_t tmp; - for( y = 0; y < height; y ++ ) + for( y = 0; y < height-1; y ++ ) { for( x = 0; x < width; x ++ ) { diff --git a/veejay-current/libvje/effects/neighbours4.c b/veejay-current/libvje/effects/neighbours4.c index 1b8fae26..4f5c7bb3 100644 --- a/veejay-current/libvje/effects/neighbours4.c +++ b/veejay-current/libvje/effects/neighbours4.c @@ -171,10 +171,18 @@ static inline pixel_t evaluate_pixel_bc( } 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; - + if(peak_value > 0) + { + val.y = y_map[peak_index] / peak_value; + val.u = cb_map[peak_index] / peak_value; + val.v = cr_map[peak_index] / peak_value; + } + else + { + val.y = y_map[y * w + x]; + val.u = cb_map[y * w + x]; + val.v = cr_map[y * w + x]; + } return val; } @@ -271,7 +279,7 @@ void neighbours4_apply( VJFrame *frame, int width, int height, int radius, int b if(!mode) { - for( y = 0; y < height; y ++ ) + for( y = 0; y < height-1; y ++ ) { for( x = 0; x < width; x ++ ) { diff --git a/veejay-current/libvje/effects/neighbours5.c b/veejay-current/libvje/effects/neighbours5.c index 4225302d..f2aec010 100644 --- a/veejay-current/libvje/effects/neighbours5.c +++ b/veejay-current/libvje/effects/neighbours5.c @@ -139,10 +139,18 @@ static inline pixel_t evaluate_pixel_bc( } 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; - + if(peak_value > 0) + { + val.y = y_map[peak_index] / peak_value; + val.u = cb_map[peak_index] / peak_value; + val.v = cr_map[peak_index] / peak_value; + } + else + { + val.y = y_map[ y * w + x]; + val.u = cb_map[ y * w + x]; + val.v = cr_map[ y * w + x]; + } return val; } @@ -225,7 +233,7 @@ void neighbours5_apply( VJFrame *frame, int width, int height, int brush_size, i if(!mode) { - for( y = 0; y < height; y ++ ) + for( y = 0; y < height-1; y ++ ) { for( x = 0; x < width; x ++ ) { @@ -246,7 +254,7 @@ void neighbours5_apply( VJFrame *frame, int width, int height, int brush_size, i else { pixel_t tmp; - for( y = 0; y < height; y ++ ) + for( y = 0; y < height-1; y ++ ) { for( x = 0; x < width; x ++ ) { diff --git a/veejay-current/libvje/effects/rgbkey.c b/veejay-current/libvje/effects/rgbkey.c index f77cb4ce..cc1e8ca3 100644 --- a/veejay-current/libvje/effects/rgbkey.c +++ b/veejay-current/libvje/effects/rgbkey.c @@ -38,6 +38,10 @@ Isolate by Color , Complex Threshold and Blend by Color Key, */ +/* + (march,2005) fixed flaw (signed vs. unsigned) in algorithm + use selectable rgb -> yuv formula, + */ vj_effect *rgbkey_init(int w,int h) { @@ -47,17 +51,18 @@ vj_effect *rgbkey_init(int w,int h) 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->defaults[0] = 210; /* angle */ - ve->defaults[1] = 3500; /* noise */ - ve->defaults[2] = 255; /* r */ - ve->defaults[3] = 0; /* g */ - ve->defaults[4] = 0; /* b */ - ve->defaults[5] = 1; /* type */ + ve->defaults[0] = 319; /* angle , 45 degrees*/ + ve->defaults[1] = 0; /* r */ + ve->defaults[2] = 0; /* g */ + ve->defaults[3] = 255; /* b */ + ve->defaults[4] = 1; /* type */ + ve->defaults[5] = 3500; /* noise */ + ve->limits[0][0] = 5; ve->limits[1][0] = 900; - ve->limits[0][1] = 1; - ve->limits[1][1] = 6300; + ve->limits[0][1] = 0; + ve->limits[1][1] = 255; ve->limits[0][2] = 0; ve->limits[1][2] = 255; @@ -66,14 +71,17 @@ vj_effect *rgbkey_init(int w,int h) ve->limits[1][3] = 255; ve->limits[0][4] = 0; - ve->limits[1][4] = 255; + ve->limits[1][4] = 1; /* total noise suppression off */ + + ve->limits[0][5] = 1; + ve->limits[1][5] = 6300; + - ve->limits[0][5] = 0; - ve->limits[1][5] = 1; /* total noise suppression off */ ve->has_user = 0; ve->description = "Chroma Key (RGB)"; ve->extra_frame = 1; ve->sub_format = 1; + ve->rgb_conv = 1; return ve; } /* @@ -88,8 +96,8 @@ void rgbkey_scan_fg(uint8_t * src2[3], int *r, int *g, int *b) } */ void rgbkey_apply1(VJFrame *frame, VJFrame *frame2, int width, - int height, int i_angle, int i_noise, int r, int g, - int b) + int height, int i_angle, int r, int g, + int b, int i_noise) { uint8_t *fg_y, *fg_cb, *fg_cr; @@ -99,7 +107,7 @@ void rgbkey_apply1(VJFrame *frame, VJFrame *frame2, int width, int cb, cr; int kbg, x1, y1; float kg1, tmp, aa = 128, bb = 128, _y = 0; - float angle = (float) i_angle / 10.0; + float angle = (float) i_angle * 0.1f; float noise_level = (i_noise / 100.0); unsigned int pos; uint8_t val, tmp1; @@ -109,10 +117,11 @@ void rgbkey_apply1(VJFrame *frame, VJFrame *frame2, int width, uint8_t *Y2 = frame2->data[0]; uint8_t *Cb2= frame2->data[1]; uint8_t *Cr2= frame2->data[2]; - - _y = ((Y_Redco * r) + (Y_Greenco * g) + (Y_Blueco * b) + 16); - aa = ((U_Redco * r) - (U_Greenco * g) - (U_Blueco * b) + 128); - bb = (-(V_Redco * r) - (V_Greenco * g) + (V_Blueco * b) + 128); + int iy=16,iu=128,iv=128; + _rgb2yuv( r,g,b, iy,iu,iv ); + _y = (float) iy; + aa = (float) iu; + bb = (float) iv; tmp = sqrt(((aa * aa) + (bb * bb))); cb = 127 * (aa / tmp); cr = 127 * (bb / tmp); @@ -131,7 +140,7 @@ void rgbkey_apply1(VJFrame *frame, VJFrame *frame2, int width, fg_y = Y; fg_cb = Cb; fg_cr = Cr; - + /* 2005: swap these !! */ bg_y = Y2; bg_cb = Cb2; bg_cr = Cr2; @@ -156,7 +165,7 @@ void rgbkey_apply1(VJFrame *frame, VJFrame *frame2, int width, yy = -128; } if (yy > 127) { - yy = 127; + yy = 127; } @@ -184,26 +193,22 @@ void rgbkey_apply1(VJFrame *frame, VJFrame *frame2, int width, kbg = 255; val = (tmp1 * kfgy_scale) >> 4; - if (val > 0xff) - val = 0xff; val = fg_y[pos] - val; Y[pos] = val; // convert suppressed fg back to cbcr - - val = ((x1 * cb) - (y1 * cr)) >> 7; + // cb,cr are signed, go back to unsigned ! + val = ((x1 * (cb-128)) - (y1 * (cr-128))) >> 7; Cb[pos] = val; - val = ((x1 * cr) - (y1 * cb)) >> 7; + val = ((x1 * (cr-128)) - (y1 * (cb-128))) >> 7; Cr[pos] = val; // deal with noise val = (yy * yy) + (kg * kg); - if (val > 0xff) - val = 0xff; if (val < (noise_level * noise_level)) { kbg = 255; } @@ -234,8 +239,8 @@ void rgbkey_apply1(VJFrame *frame, VJFrame *frame2, int width, } void rgbkey_apply2(VJFrame *frame, VJFrame *frame2, int width, - int height, int i_angle, int i_noise, int r, int g, - int b) + int height, int i_angle,int r, int g, + int b, int i_noise) { uint8_t *fg_y, *fg_cb, *fg_cr; @@ -245,7 +250,7 @@ void rgbkey_apply2(VJFrame *frame, VJFrame *frame2, int width, int cb, cr; int kbg, x1, y1; float kg1, tmp, aa = 128, bb = 128, _y = 0; - float angle = (float) i_angle; + float angle = (float) i_angle * 0.1f; float noise_level = (i_noise / 100.0); unsigned int pos; uint8_t val, tmp1; @@ -255,10 +260,11 @@ void rgbkey_apply2(VJFrame *frame, VJFrame *frame2, int width, uint8_t *Y2 = frame2->data[0]; uint8_t *Cb2= frame2->data[1]; uint8_t *Cr2= frame2->data[2]; - - _y = ((Y_Redco * r) + (Y_Greenco * g) + (Y_Blueco * b) + 16); - aa = ((U_Redco * r) - (U_Greenco * g) - (U_Blueco * b) + 128); - bb = (-(V_Redco * r) - (V_Greenco * g) + (V_Blueco * b) + 128); + int iy=16,iu=128,iv=128; + _rgb2yuv( r,g,b, iy,iu,iv ); + _y = (float) iy; + aa = (float) iu; + bb = (float) iv; tmp = sqrt(((aa * aa) + (bb * bb))); cb = 127 * (aa / tmp); cr = 127 * (bb / tmp); @@ -282,7 +288,9 @@ void rgbkey_apply2(VJFrame *frame, VJFrame *frame2, int width, bg_cb = Cb2; bg_cr = Cr2; - for (pos = (width * height); pos != 0; pos--) { + int len = frame->len; + + for (pos = 0; pos < len; pos++) { short xx, yy; /* convert foreground to xz coordinates where x direction is defined by key color */ @@ -330,26 +338,22 @@ void rgbkey_apply2(VJFrame *frame, VJFrame *frame2, int width, kbg = 255; val = (tmp1 * kfgy_scale) >> 4; - if (val > 0xff) - val = 0xff; val = fg_y[pos] - val; Y[pos] = val; /* convert suppressed fg back to cbcr */ - val = ((x1 * cb) - (y1 * cr)) >> 7; + val = ((x1 * (cb-128)) - (y1 * (cr-128))) >> 7; Cb[pos] = val; - val = ((x1 * cr) - (y1 * cb)) >> 7; + val = ((x1 * (cr-128)) - (y1 * (cb-128))) >> 7; Cr[pos] = val; /* deal with noise */ val = (yy * yy) + (kg * kg); - if (val > 0xff) - val = 0xff; if (val < (noise_level * noise_level)) { Y[pos] = Cb[pos] = Cr[pos] = 0; kbg = 255; @@ -383,18 +387,18 @@ void rgbkey_apply2(VJFrame *frame, VJFrame *frame2, int width, */ void rgbkey_apply(VJFrame *frame, VJFrame *frame2, int width, - int height, int i_angle, int i_noise, int red, int green, - int blue, int type) + int height, int i_angle, int red, int green, + int blue, int type, int i_noise) { switch (type) { case 0: - rgbkey_apply1(frame, frame2, width, height, i_angle, i_noise, red, - green, blue); + rgbkey_apply1(frame, frame2, width, height, i_angle, red, + green, blue, i_noise); break; case 1: - rgbkey_apply2(frame, frame2, width, height, i_angle, i_noise, red, - green, blue); + rgbkey_apply2(frame, frame2, width, height, i_angle, red, + green, blue, i_noise); break; } diff --git a/veejay-current/libvje/effects/rgbkeysmooth.c b/veejay-current/libvje/effects/rgbkeysmooth.c index e8a47803..c65f9f0f 100644 --- a/veejay-current/libvje/effects/rgbkeysmooth.c +++ b/veejay-current/libvje/effects/rgbkeysmooth.c @@ -32,15 +32,16 @@ vj_effect *rgbkeysmooth_init(int w,int h) { vj_effect *ve; ve = (vj_effect *) vj_malloc(sizeof(vj_effect)); - ve->num_params = 5; + ve->num_params = 6; 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->defaults[0] = 2990; /* angle */ - ve->defaults[1] = 255; /* b */ - ve->defaults[2] = 0; /* b */ - ve->defaults[3] = 0; /* g */ - ve->defaults[4] = 1; /* smoothen level */ + ve->defaults[0] = 290; /* angle */ + ve->defaults[1] = 255; /* r */ + ve->defaults[2] = 0; /* g */ + ve->defaults[3] = 0; /* b */ + ve->defaults[4] = 1; /* opacity */ + ve->defaults[5] = 1500; /* noise level */ ve->limits[0][0] = 5; ve->limits[1][0] = 900; @@ -54,72 +55,35 @@ vj_effect *rgbkeysmooth_init(int w,int h) ve->limits[1][3] = 255; ve->limits[0][4] = 0; - ve->limits[1][4] = 4; + ve->limits[1][4] = 255; + + ve->limits[0][5] = 0; + ve->limits[1][5] = 3500; + ve->has_user = 0; - ve->description = "Smooth Chroma Key (RGB)"; + ve->description = "Transparent Chroma Key (RGB)"; ve->extra_frame = 1; ve->sub_format = 1; + ve->rgb_conv = 1; return ve; } -/* this method decides whether or not a pixel from the fg will be accepted for keying */ -static inline int accept_pixel(uint8_t fg_cb, uint8_t fg_cr, int cb, int cr, - int accept_angle_tg) -{ - short xx, yy; - /* convert foreground to xz coordinates where x direction is - defined by key color */ - uint8_t val; - - xx = ((fg_cb * cb) + (fg_cr * cr)) >> 7; - - if (xx < -128) { - xx = -128; - } - if (xx > 127) { - xx = 127; - } - - yy = ((fg_cr * cb) - (fg_cb * cr)) >> 7; - - if (yy < -128) { - yy = -128; - } - if (yy > 127) { - yy = 127; - } - - - /* accept angle should not be > 90 degrees - reasonable results between 10 and 80 degrees. - */ - - val = (xx * accept_angle_tg) >> 4; - if (val > 127) - val = 127; - if (abs(yy) < val) { - return 1; - } - return 0; -} void rgbkeysmooth_apply(VJFrame *frame, VJFrame *frame2, int width, int height, int i_angle, int r, int g, int b, - int level) + int opacity, int i_noise) { - uint8_t *fg_y, *fg_cb, *fg_cr; + uint8_t *fg_y, *fg_cb, *fg_cr; uint8_t *bg_y, *bg_cb, *bg_cr; int accept_angle_tg, accept_angle_ctg, one_over_kc; int kfgy_scale, kg; - int cb, cr; int kbg, x1, y1; float kg1, tmp, aa = 128, bb = 128, _y = 0; - float angle = (float) i_angle / 10.0; - //float noise_level = 350.0; + float angle = (float) i_angle * 0.1f; + float noise_level = (i_noise / 100.0); unsigned int pos; - int matrix[5]; uint8_t val, tmp1; uint8_t *Y = frame->data[0]; uint8_t *Cb= frame->data[1]; @@ -127,12 +91,15 @@ void rgbkeysmooth_apply(VJFrame *frame, VJFrame *frame2, int width, uint8_t *Y2 = frame2->data[0]; uint8_t *Cb2= frame2->data[1]; uint8_t *Cr2= frame2->data[2]; + int iy=16,iu=128,iv=128; + unsigned int op0 = opacity > 255 ? 255 : opacity; + unsigned int op1 = 255 - op0; - _y = ((Y_Redco * r) + (Y_Greenco * g) + (Y_Blueco * b) + 16); - aa = ((U_Redco * r) - (U_Greenco *g ) - (U_Blueco * b) + 128); - bb = (-(V_Redco * r) - (V_Greenco * g) + (V_Greenco * b) + 128); - fast_sqrt(tmp, (double)((aa*aa)+(bb*bb))); - //tmp = sqrt(((aa * aa) + (bb * bb))); + _rgb2yuv( r,g,b, iy,iu,iv ); + _y = (float) iy; + aa = (float) iu; + bb = (float) iv; + tmp = sqrt(((aa * aa) + (bb * bb))); cb = 127 * (aa / tmp); cr = 127 * (bb / tmp); kg1 = tmp; @@ -150,127 +117,101 @@ void rgbkeysmooth_apply(VJFrame *frame, VJFrame *frame2, int width, fg_y = Y; fg_cb = Cb; fg_cr = Cr; - + /* 2005: swap these !! */ bg_y = Y2; bg_cb = Cb2; bg_cr = Cr2; - for (pos = width + 1; pos < (width * height) - width - 1; pos++) { - int i = 0; - int smooth = 0; - /* setup matrix - [ - 0 - ] = do not accept. [ - 1 - ] = level 5 , accept only when all n = 1 - [ 0 0 0 ] [ 1 1 1 ] - [ - 0 - ] [ - 1 - ] + for (pos = (width * height); pos != 0; pos--) { + short xx, yy; + /* convert foreground to xz coordinates where x direction is + defined by key color */ - [ - 0 - ] sum of all n is acceptance value for level - [ 1 0 1 ] - [ 0 1 0 ] - */ - matrix[0] = accept_pixel(fg_cb[pos], fg_cr[pos], cb, cr, accept_angle_tg); /* center pixel */ - matrix[1] = accept_pixel(fg_cb[pos - 1], fg_cr[pos - 1], cb, cr, accept_angle_tg); /* left pixel */ - matrix[2] = accept_pixel(fg_cb[pos + 1], fg_cr[pos + 1], cb, cr, accept_angle_tg); /* right pixel */ - matrix[3] = accept_pixel(fg_cb[pos + width], fg_cr[pos + width], cb, cr, accept_angle_tg); /* top pixel */ - matrix[4] = accept_pixel(fg_cb[pos - width], fg_cr[pos - width], cb, cr, accept_angle_tg); /* bottom pixel */ - for (i = 0; i < 5; i++) { - if (matrix[i] == 1) - smooth++; + xx = (((fg_cb[pos]) * cb) + ((fg_cr[pos]) * cr)) >> 7; + + if (xx < -128) { + xx = -128; + } + if (xx > 127) { + xx = 127; } - if (smooth >= level) { - short xx, yy; - /* get bg/fg pixels */ - uint8_t p1 = (matrix[0] == 0 ? fg_y[pos] : bg_y[pos]); - uint8_t p2 = (matrix[1] == 0 ? fg_y[pos - 1] : bg_y[pos - 1]); - uint8_t p3 = (matrix[2] == 0 ? fg_y[pos + 1] : bg_y[pos + 1]); - uint8_t p4 = - (matrix[3] == 0 ? fg_y[pos + width] : bg_y[pos + width]); - uint8_t p5 = - (matrix[4] == 0 ? fg_y[pos - width] : bg_y[pos - width]); - /* and blur the pixel */ - fg_y[pos] = (p1 + p2 + p3 + p4 + p5) / 5; - /* convert foreground to xz coordinates where x direction is - defined by key color */ - xx = (((fg_cb[pos]) * cb) + ((fg_cr[pos]) * cr)) >> 7; + yy = (((fg_cr[pos]) * cb) - ((fg_cb[pos]) * cr)) >> 7; - if (xx < -128) { - xx = -128; - } - if (xx > 127) { - xx = 127; + if (yy < -128) { + yy = -128; + } + if (yy > 127) { + yy = 127; + } + + + /* accept angle should not be > 90 degrees + reasonable results between 10 and 80 degrees. + */ + + val = (xx * accept_angle_tg) >> 4; + if (val > 127) + val = 127; + // if (abs(yy) > val) { + if (abs(yy) < val) { + /* compute fg, suppress fg in xz according to kfg + */ + val = (yy * accept_angle_ctg) >> 4; + + x1 = abs(val); + y1 = yy; + tmp1 = xx - x1; + + kbg = (tmp1 * one_over_kc) >> 1; + if (kbg < 0) + kbg = 0; + if (kbg > 255) + kbg = 255; + + val = (tmp1 * kfgy_scale) >> 4; + val = fg_y[pos] - val; + + Y[pos] = val; + + // convert suppressed fg back to cbcr + // cb,cr are signed, go back to unsigned ! + val = ((x1 * (cb-128)) - (y1 * (cr-128))) >> 7; + + Cb[pos] = val; + + val = ((x1 * (cr-128)) - (y1 * (cb-128))) >> 7; + Cr[pos] = val; + + // deal with noise + + val = (yy * yy) + (kg * kg); + if (val < (noise_level * noise_level)) { + kbg = 255; } - yy = (((fg_cr[pos]) * cb) - ((fg_cb[pos]) * cr)) >> 7; + val = (Y[pos] + (kbg * bg_y[pos])) >> 8; + if (val < 16) + val = 16; + else if (val > 235) + val = 235; + Y[pos] = ((val*op0)+(fg_y[pos]*op1) )>>8 ; - if (yy < -128) { - yy = -128; - } - if (yy > 127) { - yy = 127; - } + val = (Cb[pos] + (kbg * bg_cb[pos])) >> 8; + if (val < 16) + val = 16; + else if (val > 240) + val = 240; + Cb[pos] = ((val*op0) + (fg_cb[pos]*op1) )>>8; - val = (xx * accept_angle_tg) >> 4; - if (val > 127) - val = 127; - if (abs(yy) < val) { - - val = (xx * accept_angle_tg) >> 4; - if (val > 127) - val = 127; - val = (yy * accept_angle_ctg) >> 4; - x1 = abs(val); - y1 = yy; - tmp1 = xx - x1; - - kbg = (tmp1 * one_over_kc) >> 1; - if (kbg < 0) - kbg = 0; - if (kbg > 255) - kbg = 255; - - val = (tmp1 * kfgy_scale) >> 4; - if (val > 0xff) - val = 0xff; - val = fg_y[pos] - val; - - Y[pos] = val; - - /* convert suppressed fg back to cbcr */ - - val = ((x1 * cb) - (y1 * cr)) >> 7; - - Cb[pos] = val; - - val = ((x1 * cr) - (y1 * cb)) >> 7; - Cr[pos] = val; - val = (yy * yy) + (kg * kg); - if (val > 0xff) - val = 0xff; - if (val < (35 * 35)) { - kbg = 255; - } - - val =( Y[pos] + (kbg * bg_y[pos])) >> 8; - if (val < 16) - val = 16; - else if (val > 235) - val = 235; - Y[pos] = val; - - val = (Cb[pos] + (kbg * bg_cb[pos])) >> 8; - if (val < 16) - val = 16; - else if (val > 240) - val = 240; - Cb[pos] = val; - - val = (Cr[pos] + (kbg * bg_cr[pos])) >> 8; - if (val < 16) - val = 16; - else if (val > 240) - val = 240; - Cr[pos] = val; - } + val = (Cr[pos] + (kbg * bg_cr[pos])) >> 8; + if (val < 16) + val = 16; + else if (val > 240) + val = 240; + Cr[pos] = ((val*op0) + (fg_cr[pos]*op1) )>>8; + } } + } diff --git a/veejay-current/libvje/effects/rgbkeysmooth.h b/veejay-current/libvje/effects/rgbkeysmooth.h index b9d52b56..84b2064e 100644 --- a/veejay-current/libvje/effects/rgbkeysmooth.h +++ b/veejay-current/libvje/effects/rgbkeysmooth.h @@ -27,6 +27,6 @@ vj_effect *rgbkeysmooth_init(); void rgbkeysmooth_apply( VJFrame *frame, VJFrame *frame2, int width, int height, int i_angle, int red, int green, - int blue, int level); + int blue, int op, int noise); void rgbkeysmooth_free(); #endif diff --git a/veejay-current/libvje/internal.h b/veejay-current/libvje/internal.h index 8fa36ae1..5776ca41 100644 --- a/veejay-current/libvje/internal.h +++ b/veejay-current/libvje/internal.h @@ -364,7 +364,7 @@ extern void diffimg_apply(VJFrame *frame, int zeta); extern void rgbkeysmooth_apply(VJFrame *frame, VJFrame *frame2, int w, int h, int angle, int r, int g, int b, - int level); + int level, int noise); extern void scratcher_apply(VJFrame *frame, int w, int h, int o, int n, int r); extern void colorshift_apply(VJFrame *frame, int width, int height, @@ -390,7 +390,7 @@ extern void mtracer_apply(VJFrame *frame, VJFrame *frame2, int w, int h, int mode, int n); extern void keyselect_apply(VJFrame *frame, VJFrame *frame2,int w,int h, int angle,int r, - int g, int b, int mode); + int g, int b, int mode, int noise); extern void greyselect_apply(VJFrame *frame, int w, int h, int angle, int r, int g, int b); extern void isolate_apply(VJFrame *frame, int w, int h, int angle, int r, int g, int b, @@ -398,9 +398,9 @@ int opacity); extern void bwselect_apply(VJFrame *frame, int w, int h, int a , int b); -extern void complexinvert_apply(VJFrame *frame, int w, int h, int angle, int r, int g, int b, int level); +extern void complexinvert_apply(VJFrame *frame, int w, int h, int angle, int r, int g, int b, int i_noise); -extern void complexsaturation_apply(VJFrame *frame, int w, int h, int angle, int r, int g, int b, int adj, int adjv); +extern void complexsaturation_apply(VJFrame *frame, int w, int h, int angle, int r, int g, int b, int adj, int adjv, int inoise); extern void complexthreshold_apply(VJFrame *frame, VJFrame *frame2, int w, int h, int angle, int r, int g, int b, int level, int threshold); diff --git a/veejay-current/libvje/vj-effect.c b/veejay-current/libvje/vj-effect.c index a1b4ea1d..9a679f57 100644 --- a/veejay-current/libvje/vj-effect.c +++ b/veejay-current/libvje/vj-effect.c @@ -211,6 +211,8 @@ int max_width = 0; int max_height =0; +int rgb_parameter_conversion_type_ = 0; + static int _get_simple_effect( int effect_id) { int i; @@ -486,6 +488,10 @@ void vj_effect_initialize(int width, int height) { if(i!=3) vj_effects[i]->static_bg = 0; if(i!=(VJ_VIDEO_COUNT+58)) vj_effects[i]->has_help = 0; + + /* bah really need to clean this up: */ + if(vj_effects[i]->rgb_conv != 1) + vj_effects[i]->rgb_conv = 0; } } @@ -688,12 +694,13 @@ int vj_effect_get_summary(int entry, char *dst) if(!vj_effects[entry]) return 0; - - sprintf(dst,"%03d%s%03d%1d%02d", + + sprintf(dst,"%03d%s%03d%1d%1d%02d", strlen( vj_effects[entry]->description), vj_effects[entry]->description, vj_effect_get_real_id(entry), vj_effects[entry]->extra_frame, + vj_effects[entry]->rgb_conv, p ); for(i=0; i < p; i++) @@ -775,6 +782,18 @@ int vj_effect_get_max_v() return VJ_VIDEO_EFFECT_MAX; } +int vj_effect_has_rgbkey(int effect_id) +{ + int entry; + entry = vj_effect_real_to_sequence(effect_id); + if (entry >= 0) + { + return ( vj_effects[entry]->rgb_conv); + + } + return 0; +} + int vj_effect_is_valid(int effect_id) { if (effect_id > VJ_IMAGE_EFFECT_MIN && effect_id < VJ_IMAGE_EFFECT_MAX) { diff --git a/veejay-current/libvje/vj-effman.c b/veejay-current/libvje/vj-effman.c index 17f2a8fc..46fd1557 100644 --- a/veejay-current/libvje/vj-effman.c +++ b/veejay-current/libvje/vj-effman.c @@ -93,7 +93,7 @@ void vj_effman_apply_image_effect( complexinvert_apply(frames[0], frameinfo->width,frameinfo->height,arg[0],arg[1],arg[2],arg[3],arg[4]); break; case VJ_IMAGE_EFFECT_COMPLEXSATURATE: - complexsaturation_apply(frames[0], frameinfo->width,frameinfo->height,arg[0],arg[1],arg[2],arg[3],arg[4],arg[5]); + complexsaturation_apply(frames[0], frameinfo->width,frameinfo->height,arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6]); break; case VJ_IMAGE_EFFECT_REFLECTION: reflection_apply(frames[0], frameinfo->width, frameinfo->height, @@ -375,7 +375,7 @@ void vj_effman_apply_video_effect( VJFrame **frames, VJFrameInfo *frameinfo ,vjp break; case VJ_VIDEO_EFFECT_KEYSELECT: keyselect_apply(frames[0],frames[1],frameinfo->width,frameinfo->height, - arg[0],arg[1],arg[2],arg[3],arg[4]); + arg[0],arg[1],arg[2],arg[3],arg[4],arg[5]); break; case VJ_VIDEO_EFFECT_CHROMAMAGICK: chromamagick_apply(frames[0], frames[1], frameinfo->width, @@ -483,7 +483,7 @@ void vj_effman_apply_video_effect( VJFrame **frames, VJFrameInfo *frameinfo ,vjp case VJ_VIDEO_EFFECT_RGBKEYSMOOTH: rgbkeysmooth_apply(frames[0], frames[1], frameinfo->width, frameinfo->height, arg[0], arg[1], arg[2], arg[3], - arg[4]); + arg[4],arg[5]); break; case VJ_VIDEO_EFFECT_SPLIT: split_apply(frames[0], frames[1], frameinfo->width, frameinfo->height, diff --git a/veejay-current/libvje/vje.h b/veejay-current/libvje/vje.h index b6e3df0a..89b1f381 100644 --- a/veejay-current/libvje/vje.h +++ b/veejay-current/libvje/vje.h @@ -81,6 +81,7 @@ typedef struct vj_effect_t { int has_user; // has private data? int static_bg; // unused int has_help; // unused + int rgb_conv; // temporary fix for color effects void *user_data; // private effect data } vj_effect; @@ -103,7 +104,8 @@ extern int vj_effect_get_max_limit(int effect_id, int param_nr); extern int vj_effect_valid_value(int effect_id, int param_nr, int value); extern int vj_effect_get_subformat(int effect_id); extern int vj_effect_has_cb(int effect_id); - +// if effect has rgbkey its always p1,p2,p3 (r,g,b) +extern int vj_effect_has_rgbkey(int effect_id); extern int vj_effect_is_valid(int effect_id); extern int vj_effect_get_summary(int entry, char *dst); @@ -126,4 +128,6 @@ extern void vj_effect_dump(void); // see veejay/vj-perform 'apply_first' for an example on how to use this. +extern int rgb_parameter_conversion_type_; + #endif