Added another Sequence effect: the wellknown Glow effect.

This commit is contained in:
Roel Spruit 2004-06-23 22:11:57 +00:00
parent eec72e3d4b
commit 8a0cd0bc97
7 changed files with 327 additions and 8 deletions

@ -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;
}
}

@ -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);

@ -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

@ -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");
}
}

@ -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);

@ -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, "");

@ -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) {