Go Back   Cockos Incorporated Forums > REAPER Forums > REAPER for Video Editing/Mangling

Reply
 
Thread Tools Display Modes
Old 06-18-2022, 03:24 PM   #1
papagirafe
Human being with feelings
 
papagirafe's Avatar
 
Join Date: Aug 2020
Location: Brasil
Posts: 225
Default Overlay: text w/adjustable ol/sh/rot/pos v3.0

Hi folks!

Here is my last version of the text overlay preset before I publish the Girafx lib. This version improves on previous version (https://forum.cockos.com/showthread.php?t=262979) and now includes:
  • text rotation independent of background,
  • positionning relative to Left/Middle/Right and Top/Middle/Bottom
  • outline size relative to font size

Unfortunately, I reached the limit of parameters for a preset so I cannot include time code at this time.

*** update: I published a version with a typo that disable the shadow! Official corrected version is now 3.01. Also I forgot to mention that the text size/position is proportional to the dimensions of the video item you apply it to, not necessarily the project dimensions. In other words you can use it on each item with the "grid of videos" preset (but crop the sources first or use smaller text).



Code:
// Overlay: text w/adjustable ol/sh/rot/pos
// by papagirafe
// version 3.01, now includes rotation, relative positioning LMR TMB

// Write your own text inside quotes, multiple lines allowed inside quotes
// if empty, text = item/track name
#text="";

// default font = "Arial" in Windows
#style.font=""; 
/*
  font styles from following list - upto 4 choices allowed - uppercase mandatory 
  'B' - Bold,   'I' - Italics,  'R' - smooth edges,
  'V' - Invert bg/fg, 'U' - underlined
  ugly "stock" shadow and outline styles still work if you insist on using them... 
*/
style.style='';   

// preset paramaters
//@param style.frs 'text height' 0.07 0.01 1.0 0.5 0.001
//@param hRef "x ref L/M/R" 0 -1 1 0 1
//@param vRef "y ref T/M/B" 0 -1 1 0 1
//@param tofx "x offset" 0 -1 1 0 0.001
//@param tofy "y offset" 0 -1 1 0 0.001
//@param rota rotation 0 -180 180 0 0.1
//@param style.fgr 'text r' 1 0 1 0.5 0.001
//@param style.fgg 'text g' 1 0 1 0.5 0.001
//@param style.fgb 'text b' 1 0 1 0.5 0.001
//@param style.fga 'text a' 1 -0.01 1 0.5 0.01
//@param style.bgw 'bg w' 0 0 1 1 0.001
//@param style.bgh 'bg h' -0.001 -0.001 1 0.5 0.001    negative? follow bg w!
//@param style.bgr 'bg r' 0 0 1 0.5 0.001
//@param style.bgg 'bg g' 0 0 1 0.5 0.001
//@param style.bgb 'bg b' 0 0 1 0.5 0.001
//@param style.bga 'bg a' 0.4 0 1 0.5 0.001
//@param style.olr 'outline r' 0 0 1 0.5 0.01
//@param style.olg 'outline g' 0 0 1 0.5 0.01
//@param style.olb 'outline b' 0 0 1 0.5 0.01
//@param style.ola 'outline a' 0.1 0.01 1 0.5 0.01
//@param style.olt 'outline thickness' 0 0 1 0.5 0.01
//@param style.shmode 'shadow mode' 0 0 1 0.5 1
//@param style.shangl 'shadow angle' 45 0 359 180 1

function gfx_img_alloc_alpha(w,h) 
(
  gfx_set(0,0,0,1,0,-1,0); // set black, transparent, clobber
  gfx_img_alloc(w,h,1); // allocate and clear image with above settings
);

function xy2polar(x,y,r*,phi*)(r=sqrt(x^2+y^2);phi=2*atan(y/(x+r)));
function polar2xy(r,phi,x*,y*)(x=r*cos(phi);y=r*sin(phi));
function rotate_coord(x*,y*,rota)(xy2polar(x,y,this.r,this.phi);polar2xy(this.r,this.phi-rota,x,y));
//calc size of reactangle that can contain all text + its rotation
function calc_rot_img_size(sw,sh,dw*,dh*,rot)
  local(xmax,ymax)
  instance(x,y)
(
  xmax=sw;ymax=sh;
  //top left corner
  x=-sw/2;y=-sh/2;rotate_coord(x,y,rot);
  xmax<2*abs(x)?xmax=2*abs(x);
  ymax<2*abs(y)?ymax=2*abs(y);
  //top right corner
  x=sw/2;y=-sh/2;rotate_coord(x,y,rot);
  xmax<2*abs(x)?xmax=2*abs(x);ymax<2*abs(y)?ymax=2*abs(y);
  dw=xmax;dh=ymax;
);

//set the rest of the environment
colorspace='RGBA';
oldiv=128;
rota=rota/180*$pi;
style.fga<0?style.fga=param_wet;
style.bga*=style.fga; //bg alpha dependent upon fg alpha
mode=0x10000|0x100; //use alpha & smoothing

//no text? get it from item name or track name
strlen(#text)==0 ? input_get_name(-1,#text);
// get current input stats and force output to that size
input_info(0,sw,sh); project_w=sw;project_h=sh;
//calculate text stats, fsize=pix height of font
gfx_setfont(fsize=style.frs*min(sw,sh),#style.font,style.style);
gfx_str_measure(#text,tw,th);   

// calculate text background dimensions to parameters & outline/shadow extra space
style.bgw*=tw; 
style.bgh=style.bgh<0?style.bgw:style.bgh*=th; 
style.olt*=fsize/4;  // outline pix thickness
tbw=tw+2*style.bgw+2*style.olt;  //text bg pix width
tbh=th+2*style.bgh+2*style.olt;  //text bg pix height

//calc temporary img size compensated for rotation: (iw,ih) new temporary img dim
calc_rot_img_size(tbw,tbh,iw,ih,rota);

//ok, it's time to render to temporary image  
img=gfx_img_alloc_alpha(iw,ih);

//background if applicable
style.bga>0?(
  gfx_set(style.bgr,style.bgg,style.bgb,style.bga,mode,img);
  gfx_fillrect((iw-tbw)/2,(ih-tbh)/2,tbw,tbh);
);
// outline or shadow of applicable
style.olt>0?(
  style.shmode?(style.ola=exp(style.ola*style.fga*4.5-4);style.shangl=style.shangl*oldiv/360):(style.ola=exp((oldiv/20)*style.ola*style.fga-5.7);style.shangl=0;); 
  gfx_set(style.olr,style.olg,style.olb,style.ola*style.fga,mode,img);
  i=0; loop(style.shmode?oldiv/16:oldiv, 
    phi=2*(i+style.shangl)*$pi/oldiv;
    polar2xy(style.olt,phi,ox,oy);
    gfx_str_draw(#text,(iw-tw)/2+ox,(ih-th)/2+oy);
    i+=1;
  );
);
// 'normal' text 
gfx_set(style.fgr,style.fgg,style.fgb,style.fga,mode,img);
gfx_str_draw(#text,(iw-tw)/2,(ih-th)/2);

//final render
gfx_set(1,1,1,1,mode,-1,1);
gfx_blit(0,1);
//offset factor compensation according to alignement reference  
tofx+=hRef*(sw-tbw)/(2*sw);
tofy+=vRef*(sh-tbh)/(2*sh);
//final position
rx=tofx*sw+sw/2-iw/2;
ry=tofy*sh+sh/2-ih/2;
//final blit + clean
gfx_rotoblit(img,rota,rx,ry,iw,ih);
gfx_img_free(img);

Last edited by papagirafe; 06-19-2022 at 02:11 PM. Reason: omission & bug correction
papagirafe is offline   Reply With Quote
Old 06-19-2022, 06:46 AM   #2
chema001
Human being with feelings
 
Join Date: Feb 2018
Posts: 37
Default

Awesome!!!
chema001 is offline   Reply With Quote
Old 06-19-2022, 09:02 AM   #3
McSound
Human being with feelings
 
McSound's Avatar
 
Join Date: Jun 2021
Location: Moscow, Russia
Posts: 84
Default

AWESOME!!!
__________________
Win10Pro, i9900K, 64GbRAM, system ssd, project ssd, Audio SteinbergUR816c, 4 FullHD monitors.
McSound is offline   Reply With Quote
Old 06-20-2022, 05:12 AM   #4
papagirafe
Human being with feelings
 
papagirafe's Avatar
 
Join Date: Aug 2020
Location: Brasil
Posts: 225
Default

Hi again folks!

As my goal is to replace the stock overlay text preset, I couldn't not resist to leave out the time code. So here is version 3.1 that includes time code. I also added a fast shadow/outline mode (but low quality) to ease video editing process. For time code just insert "[tc]" or "[dftc]" (drop frame tc) anywhere in #text.



Code:
// Overlay: text w/adjustable ol/sh/rot/pos
// by papagirafe
// version 3.1, now includes rotation, relative positioning LMR TMB

// Write your own text inside quotes, multiple lines allowed inside quotes
// if empty, text = item/track name
// for time code, just insert "[tc]" anywhere, for dropframe version insert "[dftc]"
#text="";

// default font = "Arial" in Windows
#style.font=""; 
/*
  font styles from following list - upto 4 choices allowed - uppercase mandatory 
  'B' - Bold,   'I' - Italics,  'R' - smooth edges,
  'V' - Invert bg/fg, 'U' - underlined
  ugly "stock" shadow and outline styles still work if you insist on using them... 
*/
style.style='';   

// preset paramaters
//@param style.frs 'text height' 0.07 0.01 1.0 0.5 0.001
//@param hRef "x ref L/M/R" 0 -1 1 0 1
//@param vRef "y ref T/M/B" 0 -1 1 0 1
//@param tofx "x offset" 0 -1 1 0 0.001
//@param tofy "y offset" 0 -1 1 0 0.001
//@param rota rotation 0 -180 180 0 0.1
//@param style.fgr 'text r' 1 0 1 0.5 0.001
//@param style.fgg 'text g' 1 0 1 0.5 0.001
//@param style.fgb 'text b' 1 0 1 0.5 0.001
//@param style.fga 'text a' 1 -0.01 1 0.5 0.01
//@param style.bgw 'bg w' 0 0 1 1 0.001
//@param style.bgh 'bg h' -0.001 -0.001 1 0.5 0.001    negative? follow bg w!
//@param style.bgr 'bg r' 0 0 1 0.5 0.001
//@param style.bgg 'bg g' 0 0 1 0.5 0.001
//@param style.bgb 'bg b' 0 0 1 0.5 0.001
//@param style.bga 'bg a' 0.4 0 1 0.5 0.001
//@param style.olr 'outline r' 0 0 1 0.5 0.01
//@param style.olg 'outline g' 0 0 1 0.5 0.01
//@param style.olb 'outline b' 0 0 1 0.5 0.01
//@param style.ola 'outline a' 0.1 0.01 1 0.5 0.01
//@param style.olt 'outline thickness' 0 0 1 0.5 0.01
//@param style.shmode 'shadow mode' 0 0 1 0.5 1
//@param style.shangl 'shadow angle' 45 0 359 180 1
//@param HQMode "ol/sh Fast/HQ" 1 0 1 0.5 1

function gfx_img_alloc_alpha(w,h) 
(
  gfx_set(0,0,0,1,0,-1,0); // set black, transparent, clobber
  gfx_img_alloc(w,h,1); // allocate and clear image with above settings
);

function xy2polar(x,y,r*,phi*)(r=sqrt(x^2+y^2);phi=2*atan(y/(x+r)));
function polar2xy(r,phi,x*,y*)(x=r*cos(phi);y=r*sin(phi));
function rotate_coord(x*,y*,rota)(xy2polar(x,y,this.r,this.phi);polar2xy(this.r,this.phi-rota,x,y));
//calc size of reactangle that can contain all text + its rotation
function calc_rot_img_size(sw,sh,dw*,dh*,rot)
  local(xmax,ymax)
  instance(x,y)
(
  xmax=sw;ymax=sh;
  //top left corner
  x=-sw/2;y=-sh/2;rotate_coord(x,y,rot);
  xmax<2*abs(x)?xmax=2*abs(x);
  ymax<2*abs(y)?ymax=2*abs(y);
  //top right corner
  x=sw/2;y=-sh/2;rotate_coord(x,y,rot);
  xmax<2*abs(x)?xmax=2*abs(x);ymax<2*abs(y)?ymax=2*abs(y);
  dw=xmax;dh=ymax;
);

function time_code(df)
  local(t,f,period,ds)
(
  t = floor((project_time + project_timeoffs) * framerate + 0.0000001);
  f = ceil(framerate);
  df > 0.5 && f != framerate ? (
    period = floor(framerate * 600);
    ds = floor(framerate * 60);
    ds > 0 ? t += 18 * ((t / period)|0) + ((((t%period)-2)/ds)|0)*2;
  );
  sprintf(#this.tcs,"%02d:%02d:%02d:%02d",(t/(f*3600))|0,(t/(f*60))%60,(t/f)%60,t%f);
  #this.tcs;
);

//set the rest of the environment
colorspace='RGBA';
oldiv=HQMode?128:6;
rota=rota/180*$pi;
style.fga<0?style.fga=param_wet;
style.bga*=style.fga; //bg alpha dependent upon fg alpha
mode=0x10000|0x100; //use alpha & smoothing

//get text from all possible sources
strcmp(#text,"")==0 ? input_get_name(-1,#text):(
  matchi("%0s[tc]%0s",#text,#left,#right)?
    sprintf(#text,"%s%s%s",#left,time_code(0),#right) :(
      matchi("%0s[dftc]%0s",#text,#left,#right)?
        sprintf(#text,"%s%s%s",#left,time_code(1),#right);
    );
);

// get current input stats and force output to that size
input_info(0,sw,sh); project_w=sw;project_h=sh;
//calculate text stats, fsize=pix height of font
gfx_setfont(fsize=style.frs*min(sw,sh),#style.font,style.style);
gfx_str_measure(#text,tw,th);   

// calculate text background dimensions to parameters & outline/shadow extra space
style.bgw*=tw; 
style.bgh=style.bgh<0?style.bgw:style.bgh*=th; 
style.olt*=fsize/4;  // outline pix thickness
tbw=tw+2*style.bgw+2*style.olt;  //text bg pix width
tbh=th+2*style.bgh+2*style.olt;  //text bg pix height

//calc temporary img size compensated for rotation: (iw,ih) new temporary img dim
calc_rot_img_size(tbw,tbh,iw,ih,rota);

//ok, it's time to render to temporary image  
img=gfx_img_alloc_alpha(iw,ih);

//background if applicable
style.bga>0?(
  gfx_set(style.bgr,style.bgg,style.bgb,style.bga,mode,img);
  gfx_fillrect((iw-tbw)/2,(ih-tbh)/2,tbw,tbh);
);
// outline or shadow of applicable
style.olt>0?(
  !HQMode?style.ola*=40; //opacity compensation for fast mode
  style.shmode?(style.ola=exp(style.ola*style.fga*4.5-4);style.shangl=style.shangl*oldiv/360):(style.ola=exp((oldiv/20)*style.ola*style.fga-5.7);style.shangl=0;); 
  gfx_set(style.olr,style.olg,style.olb,style.ola*style.fga,mode,img);
  i=0; loop(style.shmode?oldiv/16:oldiv, 
    phi=2*(i+style.shangl)*$pi/oldiv;
    polar2xy(style.olt,phi,ox,oy);
    gfx_str_draw(#text,(iw-tw)/2+ox,(ih-th)/2+oy);
    i+=1;
  );
);
// 'normal' text 
gfx_set(style.fgr,style.fgg,style.fgb,style.fga,mode,img);
gfx_str_draw(#text,(iw-tw)/2,(ih-th)/2);

//final render
gfx_set(1,1,1,1,mode,-1,1);
gfx_blit(0,1);
//offset factor compensation according to alignement reference  
tofx+=hRef*(sw-tbw)/(2*sw);
tofy+=vRef*(sh-tbh)/(2*sh);
//final position
rx=tofx*sw+sw/2-iw/2;
ry=tofy*sh+sh/2-ih/2;
//final blit + clean
gfx_rotoblit(img,rota,rx,ry,iw,ih);
gfx_img_free(img);
papagirafe is offline   Reply With Quote
Old 06-21-2022, 08:05 AM   #5
karhide
Human being with feelings
 
Join Date: May 2008
Location: Nottingham
Posts: 192
Default

Very cool!
karhide is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -7. The time now is 12:18 PM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2022, vBulletin Solutions Inc.