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: 679
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: 42
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: 280
Default

AWESOME!!!
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: 679
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: 200
Default

Very cool!
karhide is offline   Reply With Quote
Old 12-07-2022, 08:21 AM   #6
greatzot
Human being with feelings
 
Join Date: Mar 2020
Posts: 52
Default

Quote:
Originally Posted by papagirafe View Post
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.


Papagirafe, if you have multiple lines of text as in your above timecode example, the only way I've found so far to center them all (as they would look with a typical word processor's "center justified/aligned" option...right now the text block is centered, but the text within it is left-aligned) is to make a separate instance for each line of text and adjust the y offset to move it below the previous lines. Is there a better way to pull it off that I'm missing?
greatzot is offline   Reply With Quote
Old 12-07-2022, 12:56 PM   #7
papagirafe
Human being with feelings
 
papagirafe's Avatar
 
Join Date: Aug 2020
Location: Brasil
Posts: 679
Default

Quote:
Originally Posted by greatzot View Post
Papagirafe, if you have multiple lines of text as in your above timecode example, the only way I've found so far to center them all (as they would look with a typical word processor's "center justified/aligned" option...right now the text block is centered, but the text within it is left-aligned) is to make a separate instance for each line of text and adjust the y offset to move it below the previous lines. Is there a better way to pull it off that I'm missing?
You're right, that's a limit of the preset. You can justify (sort of) with spaces within the text block but that's only a palliative. I have been working on a better solution that involves a tagged text decoder and renderer but it's a daunting task. We could probably patch it to auto-space justify but that will have to wait unfortunately (Christmas is comig!)
papagirafe is offline   Reply With Quote
Old 12-07-2022, 01:34 PM   #8
Fabian
Human being with feelings
 
Fabian's Avatar
 
Join Date: Sep 2008
Location: Sweden
Posts: 7,416
Default

When it comes to splitting multi-line text at line break ("\n") and centering the lines, this was solved in this thread

Specifically, there is a video processor preset for that in post number 9
__________________
// MVHMF
I never always did the right thing, but all I did wasn't wrong...
Fabian is offline   Reply With Quote
Old 12-10-2022, 07:26 AM   #9
papagirafe
Human being with feelings
 
papagirafe's Avatar
 
Join Date: Aug 2020
Location: Brasil
Posts: 679
Default

Quote:
Originally Posted by Fabian View Post
When it comes to splitting multi-line text at line break ("\n") and centering the lines, this was solved in this thread

Specifically, there is a video processor preset for that in post number 9
Thanks! I'll see if I can incorporate it in this preset.
papagirafe 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 05:06 AM.


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