diff options
-rw-r--r-- | source/blender/blenloader/intern/writefile.c | 3 | ||||
-rw-r--r-- | source/blender/include/BSE_sequence.h | 20 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_sequence_types.h | 10 | ||||
-rw-r--r-- | source/blender/src/drawseq.c | 15 | ||||
-rw-r--r-- | source/blender/src/editseq.c | 26 | ||||
-rw-r--r-- | source/blender/src/header_seq.c | 4 | ||||
-rw-r--r-- | source/blender/src/sequence.c | 257 |
7 files changed, 327 insertions, 8 deletions
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 953f76f3317..5b49f952140 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -1045,6 +1045,9 @@ static void write_scenes(WriteData *wd, ListBase *scebase) case SEQ_SWEEP: writestruct(wd, DATA, "SweepVars", 1, seq->effectdata); break; + case SEQ_GLOW: + writestruct(wd, DATA, "GlowVars", 1, seq->effectdata); + break; } } diff --git a/source/blender/include/BSE_sequence.h b/source/blender/include/BSE_sequence.h index dcef4b8f4f3..f4d7c99ec02 100644 --- a/source/blender/include/BSE_sequence.h +++ b/source/blender/include/BSE_sequence.h @@ -96,17 +96,31 @@ void do_mul_effect(float facf0, float facf1, unsigned int *rect1, unsigned int *rect2, unsigned int *out); /* Sweep effect */ -enum {DO_LEFT_RIGHT, DO_RIGHT_LEFT, DO_DOWN_UP, DO_UP_DOWN, +enum {DO_LEFT_RIGHT, DO_RIGHT_LEFT, DO_DOWN_UP, DO_UP_DOWN, DO_LOWER_LEFT_UPPER_RIGHT, DO_UPPER_RIGHT_LOWER_LEFT, - DO_UPPER_LEFT_LOWER_RIGHT, DO_LOWER_RIGHT_UPPER_LEFT, + DO_UPPER_LEFT_LOWER_RIGHT, DO_LOWER_RIGHT_UPPER_LEFT, DO_HORZ_OUT, DO_HORZ_IN, DO_VERT_OUT, DO_VERT_IN, DO_HORZ_VERT_OUT, DO_HORZ_VERT_IN, DO_LEFT_DOWN_RIGHT_UP_OUT, - DO_LEFT_DOWN_RIGHT_UP_IN, DO_LEFT_UP_RIGHT_DOWN_OUT, + DO_LEFT_DOWN_RIGHT_UP_IN, DO_LEFT_UP_RIGHT_DOWN_OUT, DO_LEFT_UP_RIGHT_DOWN_IN, DO_DIAG_OUT, DO_DIAG_IN, DO_DIAG_OUT_2, DO_DIAG_IN_2}; int check_zone(int x, int y, int xo, int yo, struct Sequence *seq, float facf0); +void init_sweep_effect(struct Sequence *seq); void do_sweep_effect(struct Sequence *seq, float facf0, float facf1, int x, int y, unsigned int *rect1, unsigned int *rect2, unsigned int *out); +/* Glow effect */ +enum { + GlowR=0, + GlowG=1, + GlowB=2, + GlowA=3 +}; +void RVBlurBitmap2( unsigned char* map, int width, int height, float blur, int quality); +void RVIsolateHighlights (unsigned char* in, unsigned char* out, int width, int height, int threshold, float boost, float clamp); +void RVAddBitmaps (unsigned char* a,unsigned char* b, unsigned char* c, int width, int height); +void init_glow_effect(struct Sequence *seq); +void do_glow_effect(struct Sequence *seq, float facf0, float facf1, int x, int y, unsigned int *rect1, unsigned int *rect2, unsigned int *out); + void make_black_ibuf(struct ImBuf *ibuf); void multibuf(struct ImBuf *ibuf, float fmul); void do_effect(int cfra, struct Sequence *seq, struct StripElem *se); diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h index 54eae60747d..ec9f276bb84 100644 --- a/source/blender/makesdna/DNA_sequence_types.h +++ b/source/blender/makesdna/DNA_sequence_types.h @@ -143,6 +143,15 @@ typedef struct SweepVars { short sweeptype; } SweepVars; +typedef struct GlowVars { + float fMini; /* Minimum intensity to trigger a glow */ + float fClamp; + float fBoost; /* Amount to multiply glow intensity */ + float dDist; /* Radius of glow blurring */ + int dQuality; + int bNoComp; /* SHOW/HIDE glow buffer */ +} GlowVars; + /* ***************** SEQUENCE ****************** */ @@ -171,6 +180,7 @@ typedef struct SweepVars { #define SEQ_OVERDROP 15 #define SEQ_PLUGIN 24 #define SEQ_SWEEP 25 +#define SEQ_GLOW 26 #endif diff --git a/source/blender/src/drawseq.c b/source/blender/src/drawseq.c index 5f043e7d11f..6e49c9958c5 100644 --- a/source/blender/src/drawseq.c +++ b/source/blender/src/drawseq.c @@ -121,6 +121,7 @@ static char *give_seqname(Sequence *seq) else if(seq->type==SEQ_ALPHAUNDER) return "ALPHAUNDER"; else if(seq->type==SEQ_OVERDROP) return "OVER DROP"; else if(seq->type==SEQ_SWEEP) return "SWEEP"; + else if(seq->type==SEQ_GLOW) return "GLOW"; else if(seq->type==SEQ_PLUGIN) { if(seq->plugin && seq->plugin->doit) return seq->plugin->pname; return "PLUGIN"; @@ -165,8 +166,10 @@ static unsigned int seq_color(Sequence *seq) return 0x9080A0; case SEQ_OVERDROP: return 0x5080B0; - case SEQ_SWEEP: + case SEQ_SWEEP: return 0x2080B0; + case SEQ_GLOW: + return 0x0080B0; case SEQ_PLUGIN: return 0x906000; case SEQ_SOUND: @@ -715,6 +718,16 @@ static void seq_panel_properties(short cntrl) // SEQ_HANDLER_PROPERTIES uiDefButS(block, MENU,SEQ_BUT_EFFECT, formatstring, 10,90,220,22, &sweep->sweeptype, 0, 0, 0, 0, "What type of sweep should be performed"); } + else if(last_seq->type==SEQ_GLOW){ + GlowVars *glow = (GlowVars *)last_seq->effectdata; + + uiDefButF(block, NUM, SEQ_BUT_EFFECT, "Threshold:", 10,90,150,19, &glow->fMini, 0.0, 1.0, 0, 0, "Trigger Intensity"); + uiDefButF(block, NUM, SEQ_BUT_EFFECT, "Clamp:", 10,70,150,19, &glow->fClamp, 0.0, 1.0, 0, 0, "Brightness limit of intensity"); + uiDefButF(block, NUM, SEQ_BUT_EFFECT, "Boost factor:", 10,50,150,19, &glow->fBoost, 0.0, 10.0, 0, 0, "Brightness multiplier"); + uiDefButF(block, NUM, SEQ_BUT_EFFECT, "Blur distance:", 10,30,150,19, &glow->dDist, 0.5, 20.0, 0, 0, "Radius of glow effect"); + uiDefButS(block, NUM, 0, "Quality:", 10,10,150,19, &glow->dQuality, 1.0, 5.0, 0, 0, "Accuracy of the blur effect"); + uiDefButS(block, TOG, 0, "Only boost", 10,-10,150,19, &glow->bNoComp, 0.0, 0.0, 0, 0, "Show the glow buffer only"); + } } diff --git a/source/blender/src/editseq.c b/source/blender/src/editseq.c index aef76886ba2..e9546641ca8 100644 --- a/source/blender/src/editseq.c +++ b/source/blender/src/editseq.c @@ -837,6 +837,7 @@ static int event_to_efftype(int event) if(event==9) return SEQ_OVERDROP; if(event==10) return SEQ_PLUGIN; if(event==13) return SEQ_SWEEP; + if(event==14) return SEQ_GLOW; return 0; } @@ -871,7 +872,7 @@ static int add_seq_effect(int type) seq= seq->next; } - if(type==10 || type==13) { /* plugin: minimal 1 select */ + if(type==10 || type==13 || type==14) { /* plugin: minimal 1 select */ if(seq2==0) { error("Need at least one selected sequence strip"); return 0; @@ -901,7 +902,10 @@ static int add_seq_effect(int type) /* Allocate variable structs for effects with settings */ if(seq->type==SEQ_SWEEP){ - seq->effectdata = MEM_callocN(sizeof(struct SweepVars), "sweepvars"); + init_sweep_effect(seq); + } + else if(seq->type==SEQ_GLOW){ + init_glow_effect(seq); } if(seq->type==SEQ_ALPHAUNDER || seq->type==SEQ_ALPHAOVER) { @@ -1003,13 +1007,16 @@ void add_sequence(int type) case SEQ_SWEEP: event = 13; break; + case SEQ_GLOW: + event = 14; + break; default: event = 0; break; } } else { - event= pupmenu("Add Sequence Strip%t|Images%x1|Movie%x102|Audio%x103|Scene%x101|Plugin%x10|Cross%x2|Gamma Cross%x3|Add%x4|Sub%x5|Mul%x6|Alpha Over%x7|Alpha Under%x8|Alpha Over Drop%x9|Sweep%x13"); + event= pupmenu("Add Sequence Strip%t|Images%x1|Movie%x102|Audio%x103|Scene%x101|Plugin%x10|Cross%x2|Gamma Cross%x3|Add%x4|Sub%x5|Mul%x6|Alpha Over%x7|Alpha Under%x8|Alpha Over Drop%x9|Sweep%x13|Glow%x14"); } if(event<1) return; @@ -1080,6 +1087,7 @@ void add_sequence(int type) case 9: case 10: case 13: + case 14: if(last_seq==0) error("Need at least one active sequence strip"); else if(event==10) { @@ -1105,7 +1113,7 @@ void change_sequence(void) if(last_seq==0) return; if(last_seq->type & SEQ_EFFECT) { - event= pupmenu("Change Effect%t|Switch A <-> B %x1|Switch B <-> C %x10|Plugin%x11|Recalculate%x12|Cross%x2|Gamma Cross%x3|Add%x4|Sub%x5|Mul%x6|Alpha Over%x7|Alpha Under%x8|Alpha Over Drop%x9"); + event= pupmenu("Change Effect%t|Switch A <-> B %x1|Switch B <-> C %x10|Plugin%x11|Recalculate%x12|Cross%x2|Gamma Cross%x3|Add%x4|Sub%x5|Mul%x6|Alpha Over%x7|Alpha Under%x8|Alpha Over Drop%x9|Sweep%x13|Glow%x14"); if(event>0) { if(event==1) { SWAP(Sequence *, last_seq->seq1, last_seq->seq2); @@ -1122,6 +1130,16 @@ void change_sequence(void) free_plugin_seq(last_seq->plugin); last_seq->plugin= 0; last_seq->type= event_to_efftype(event); + + switch(last_seq->type){ + case SEQ_SWEEP: + init_sweep_effect(last_seq); + break; + case SEQ_GLOW: + init_glow_effect(last_seq); + break; + } + } new_stripdata(last_seq); allqueue(REDRAWSEQ, 0); diff --git a/source/blender/src/header_seq.c b/source/blender/src/header_seq.c index 861c2995413..ba7454387ef 100644 --- a/source/blender/src/header_seq.c +++ b/source/blender/src/header_seq.c @@ -209,6 +209,9 @@ static void do_seq_addmenu_effectmenu(void *arg, int event) case 9: add_sequence(SEQ_SWEEP); break; + case 10: + add_sequence(SEQ_GLOW); + break; } } @@ -229,6 +232,7 @@ static uiBlock *seq_addmenu_effectmenu(void *arg_unused) uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Alpha Under", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 6, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Alpha Over Drop", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 7, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Sweep", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 9, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Glow", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 10, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Plugin...", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 8, ""); diff --git a/source/blender/src/sequence.c b/source/blender/src/sequence.c index f483d77114f..5a5b74724c2 100644 --- a/source/blender/src/sequence.c +++ b/source/blender/src/sequence.c @@ -31,6 +31,7 @@ */ #include <string.h> +#include <math.h> #ifdef HAVE_CONFIG_H #include <config.h> @@ -1087,6 +1088,11 @@ int check_zone(int x, int y, int xo, int yo, Sequence *seq, float facf0) { return 0; } +void init_sweep_effect(Sequence *seq) +{ + if(seq->effectdata)MEM_freeN(seq->effectdata); + seq->effectdata = MEM_callocN(sizeof(struct SweepVars), "sweepvars"); +} void do_sweep_effect(Sequence *seq, float facf0, float facf1, int x, int y, unsigned int *rect1, unsigned int *rect2, unsigned int *out) { @@ -1139,6 +1145,254 @@ void do_sweep_effect(Sequence *seq, float facf0, float facf1, int x, int y, unsi } } +/* Glow Functions */ + +void RVBlurBitmap2 ( unsigned char* map, int width,int height,float blur, + int quality) +/* MUUUCCH better than the previous blur. */ +/* We do the blurring in two passes which is a whole lot faster. */ +/* I changed the math arount to implement an actual Gaussian */ +/* distribution. */ +/* */ +/* Watch out though, it tends to misbehaven with large blur values on */ +/* a small bitmap. Avoid avoid avoid. */ +/*=============================== */ +{ + unsigned char* temp=NULL,*swap; + float *filter=NULL; + int x,y,i,fx,fy; + int index, ix, halfWidth; + float fval, k, weight, curColor[3], curColor2[3]; + + /* If we're not really blurring, bail out */ + if (blur<=0) + return; + + /* Allocate memory for the tempmap and the blur filter matrix */ + temp= MEM_mallocN( (width*height*4), "blurbitmaptemp"); + if (!temp) + return; + + /* Allocate memory for the filter elements */ + halfWidth = ((quality+1)*blur); + filter = (float *)MEM_mallocN(sizeof(float)*halfWidth*2, "blurbitmapfilter"); + if (!filter){ + MEM_freeN (temp); + return; + } + + /* Apparently we're calculating a bell curve */ + /* based on the standard deviation (or radius) */ + /* This code is based on an example */ + /* posted to comp.graphics.algorithms by */ + /* Blancmange (bmange@airdmhor.gen.nz) */ + + k = -1.0/(2.0*3.14159*blur*blur); + fval=0; + for (ix = 0;ix< halfWidth;ix++){ + weight = (float)exp(k*(ix*ix)); + filter[halfWidth - ix] = weight; + filter[halfWidth + ix] = weight; + } + filter[0] = weight; + + /* Normalize the array */ + fval=0; + for (ix = 0;ix< halfWidth*2;ix++) + fval+=filter[ix]; + + for (ix = 0;ix< halfWidth*2;ix++) + filter[ix]/=fval; + + /* Blur the rows */ + for (y=0;y<height;y++){ + /* Do the left & right strips */ + for (x=0;x<halfWidth;x++){ + index=(x+y*width)*4; + fx=0; + curColor[0]=curColor[1]=curColor[2]=0; + curColor2[0]=curColor2[1]=curColor2[2]=0; + + for (i=x-halfWidth;i<x+halfWidth;i++){ + if ((i>=0)&&(i<width)){ + curColor[0]+=map[(i+y*width)*4+GlowR]*filter[fx]; + curColor[1]+=map[(i+y*width)*4+GlowG]*filter[fx]; + curColor[2]+=map[(i+y*width)*4+GlowB]*filter[fx]; + + curColor2[0]+=map[(width-1-i+y*width)*4+GlowR] * + filter[fx]; + curColor2[1]+=map[(width-1-i+y*width)*4+GlowG] * + filter[fx]; + curColor2[2]+=map[(width-1-i+y*width)*4+GlowB] * + filter[fx]; + } + fx++; + } + temp[index+GlowR]=curColor[0]; + temp[index+GlowG]=curColor[1]; + temp[index+GlowB]=curColor[2]; + + temp[((width-1-x+y*width)*4)+GlowR]=curColor2[0]; + temp[((width-1-x+y*width)*4)+GlowG]=curColor2[1]; + temp[((width-1-x+y*width)*4)+GlowB]=curColor2[2]; + + } + /* Do the main body */ + for (x=halfWidth;x<width-halfWidth;x++){ + index=(x+y*width)*4; + fx=0; + curColor[0]=curColor[1]=curColor[2]=0; + for (i=x-halfWidth;i<x+halfWidth;i++){ + curColor[0]+=map[(i+y*width)*4+GlowR]*filter[fx]; + curColor[1]+=map[(i+y*width)*4+GlowG]*filter[fx]; + curColor[2]+=map[(i+y*width)*4+GlowB]*filter[fx]; + fx++; + } + temp[index+GlowR]=curColor[0]; + temp[index+GlowG]=curColor[1]; + temp[index+GlowB]=curColor[2]; + } + } + + /* Swap buffers */ + swap=temp;temp=map;map=swap; + + + /* Blur the columns */ + for (x=0;x<width;x++){ + /* Do the top & bottom strips */ + for (y=0;y<halfWidth;y++){ + index=(x+y*width)*4; + fy=0; + curColor[0]=curColor[1]=curColor[2]=0; + curColor2[0]=curColor2[1]=curColor2[2]=0; + for (i=y-halfWidth;i<y+halfWidth;i++){ + if ((i>=0)&&(i<height)){ + /* Bottom */ + curColor[0]+=map[(x+i*width)*4+GlowR]*filter[fy]; + curColor[1]+=map[(x+i*width)*4+GlowG]*filter[fy]; + curColor[2]+=map[(x+i*width)*4+GlowB]*filter[fy]; + + /* Top */ + curColor2[0]+=map[(x+(height-1-i)*width) * + 4+GlowR]*filter[fy]; + curColor2[1]+=map[(x+(height-1-i)*width) * + 4+GlowG]*filter[fy]; + curColor2[2]+=map[(x+(height-1-i)*width) * + 4+GlowB]*filter[fy]; + } + fy++; + } + temp[index+GlowR]=curColor[0]; + temp[index+GlowG]=curColor[1]; + temp[index+GlowB]=curColor[2]; + temp[((x+(height-1-y)*width)*4)+GlowR]=curColor2[0]; + temp[((x+(height-1-y)*width)*4)+GlowG]=curColor2[1]; + temp[((x+(height-1-y)*width)*4)+GlowB]=curColor2[2]; + } + /* Do the main body */ + for (y=halfWidth;y<height-halfWidth;y++){ + index=(x+y*width)*4; + fy=0; + curColor[0]=curColor[1]=curColor[2]=0; + for (i=y-halfWidth;i<y+halfWidth;i++){ + curColor[0]+=map[(x+i*width)*4+GlowR]*filter[fy]; + curColor[1]+=map[(x+i*width)*4+GlowG]*filter[fy]; + curColor[2]+=map[(x+i*width)*4+GlowB]*filter[fy]; + fy++; + } + temp[index+GlowR]=curColor[0]; + temp[index+GlowG]=curColor[1]; + temp[index+GlowB]=curColor[2]; + } + } + + + /* Swap buffers */ + swap=temp;temp=map;map=swap; + + /* Tidy up */ + MEM_freeN (filter); + MEM_freeN (temp); +} + + +/* Adds two bitmaps and puts the results into a third map. */ +/* C must have been previously allocated but it may be A or B. */ +/* We clamp values to 255 to prevent weirdness */ +/*=============================== */ +void RVAddBitmaps (unsigned char* a, unsigned char* b, unsigned char* c, int width, int height) +{ + int x,y,index; + + for (y=0;y<height;y++){ + for (x=0;x<width;x++){ + index=(x+y*width)*4; + c[index+GlowR]=MIN2(255,a[index+GlowR]+b[index+GlowR]); + c[index+GlowG]=MIN2(255,a[index+GlowG]+b[index+GlowG]); + c[index+GlowB]=MIN2(255,a[index+GlowB]+b[index+GlowB]); + c[index+GlowA]=MIN2(255,a[index+GlowA]+b[index+GlowA]); + } + } +} + +/* For each pixel whose total luminance exceeds the threshold, */ +/* Multiply it's value by BOOST and add it to the output map */ +void RVIsolateHighlights (unsigned char* in, unsigned char* out, int width, int height, int threshold, float boost, float clamp) +{ + int x,y,index; + int intensity; + + + for(y=0;y< height;y++) { + for (x=0;x< width;x++) { + index= (x+y*width)*4; + + /* Isolate the intensity */ + intensity=(in[index+GlowR]+in[index+GlowG]+in[index+GlowB]-threshold); + if (intensity>0){ + out[index+GlowR]=MIN2(255*clamp, (in[index+GlowR]*boost*intensity)/255); + out[index+GlowG]=MIN2(255*clamp, (in[index+GlowG]*boost*intensity)/255); + out[index+GlowB]=MIN2(255*clamp, (in[index+GlowB]*boost*intensity)/255); + } + else{ + out[index+GlowR]=0; + out[index+GlowG]=0; + out[index+GlowB]=0; + } + } + } +} + +void init_glow_effect(Sequence *seq) +{ + GlowVars *glow; + + if(seq->effectdata)MEM_freeN(seq->effectdata); + seq->effectdata = MEM_callocN(sizeof(struct GlowVars), "glowvars"); + + glow = (GlowVars *)seq->effectdata; + glow->fMini = 0.5; + glow->fClamp = 1.0; + glow->fBoost = 0.5; + glow->dDist = 3.0; + glow->dQuality = 3; + glow->bNoComp = 0; +} + + +//void do_glow_effect(Cast *cast, float facf0, float facf1, int xo, int yo, ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *outbuf, ImBuf *use) +void do_glow_effect(Sequence *seq, float facf0, float facf1, int x, int y, unsigned int *rect1, unsigned int *rect2, unsigned int *out) +{ + unsigned char *outbuf=(unsigned char *)out; + unsigned char *inbuf=(unsigned char *)rect1; + GlowVars *glow = (GlowVars *)seq->effectdata; + + RVIsolateHighlights (inbuf, outbuf , x, y, glow->fMini*765, glow->fBoost, glow->fClamp); + RVBlurBitmap2 (outbuf, x, y, glow->dDist,glow->dQuality); + if (!glow->bNoComp) + RVAddBitmaps (inbuf , outbuf, outbuf, x, y); +} void make_black_ibuf(ImBuf *ibuf) { @@ -1253,6 +1507,9 @@ void do_effect(int cfra, Sequence *seq, StripElem *se) case SEQ_SWEEP: do_sweep_effect(seq, fac, facf, x, y, se1->ibuf->rect, se2->ibuf->rect, se->ibuf->rect); break; + case SEQ_GLOW: + do_glow_effect(seq, fac, facf, x, y, se1->ibuf->rect, se2->ibuf->rect, se->ibuf->rect); + break; case SEQ_PLUGIN: if(seq->plugin && seq->plugin->doit) { |