G'MIC Tutorial Fragments

For the first time in months and months! playtime with G’MIC. Topic: some illustrations for the upcoming arabesque plotting Cookbook recipe, an exercise in spectral play and using the math parser’s polygon() command. The demo code for all that lives in spectralarabesque.gmic.

First, basic use:

gmic -command spectralarabesque.gmic  \
     sw=512                           \
     -input '{$sw}','{$sw}',1,1       \
     -name. template                  \
     -repeat 360 k='{$>}'             \
         u='{$k/360}'                 \
         v='{2*$u*(1-$u)}'            \
         +gtutor_fwheelie[template] '{0.05+0.45*$v}',90,-1,'{0.125+0.5*$v}','{3*$k}',2,'{0.375*$v}','{-$k}',-5,'{0.25*$v}','{2*$k}',7 \
         -gtutor_specplot.            \
     -done                            \
     -remove[template]                \
     -output basic.mp4,24,H264        \

Next, an excuse to use thin plate splines in radial basis functions:

gmic -command spectralarabesque.gmic  \
     sw=1024                          \
     bi=15                            \
    -input '{$sw}','{$sw}',1,1        \
    -name. template                   \
    -repeat 360 k='{$>}'              \
        u='{$k/360}'                  \
        v='{3*$u*(1-$u)^2}'           \
        w='{3*($u^2)*(1-$u)}'         \
        +gtutor_fwheelie[template] '{0.5*$v}',90,-3,'{0.75*$w}','{3*$k}',2,'{0.5*$v}','{-$k}',-5,'{0.45+0.05*$w}','{2*$k}',-1 \
        -gtutor_specplot.             \
        -name. spiral_'{$k}'          \
    -done                             \
    -remove[template]                 \
    -append z                         \
    -deriche. '{$bi}',1,z,2           \
    -name. swirl                      \
    -normalize[swirl] 0,255           \
    -apply_curve[swirl] 1,0,0,63,40,127,160,200,240,255,255                          \
    -input '(0,63,127,189,255^255,250,220,0,0^127,230,220,50,255^20,80,180,100,255)' \
    -rbf. 255                         \
    -name. palette                    \
    -normalize[palette] 0,255         \
    -map[swirl] [palette],2           \
    -keep[swirl]                      \
    -split[swirl] z                   \
    -resize2dx '{0.5*$sw}',5,1        \
    -output rbfderiche.mp4,24,H264

Finally, let’s torment the cat.

gmic -command spectralarabesque.gmic  \
    bi=80                             \
    sw=512                            \
    -sample cat,'{$sw}'               \
    -name. cat                        \
    -input 100%,100%,1,1              \
    -name. template                   \
    -repeat 360 k='{$>}'              \
        u='{$k/360}'                  \
        v='{3*$u*(1-$u)^2}'           \
        w='{3*($u^2)*(1-$u)}'         \
        +gtutor_fwheelie[template]   '{0.5*$v}',90,1,'{0.5*$w}','{$k}',-2,'{0.5*(1-$v)}','{$k}',5 \
        -gtutor_specplot.             \
        -blur. '{$bi*$w}',1           \
        -resize. '{w#$template}','{h#$template}',100%,100%,5 \
        -normalize. 0,255             \
        +deriche. '{$bi*$w}',1,y,2    \
        -deriche.. '{$bi*$v}',1,x,2   \
        -append[-2,-1] c              \
        -normalize. -1,1              \
        -name. warper                 \
        -mul[warper] '{w#$cat*$w}'    \
        +warp[cat]  [warper],1,2,3    \
        -remove[warper]               \
        -name. warpedcat_'{$k}'       \
    -done                             \
    -remove[cat,template]             \
    -output warpedcat.mp4,24,H264

Here is where gtutor_fwheelie and gtutor_specplot live.

spectralarabesque.gmic
#@cli : gtutor_fwheelie : radius₀,angle₀,angular_velocity₀…
#@cli : Plot a two channel discrete frequency domain image corresponding to
#@cli : the supplied wheelie parameters: r, θ and ±ω triplet(s) on the command
#@cli : line, One triplet for each wheelie. Image suitable as a gtutor_specplot
#@cli : selection, which generates the arabesque.
#@cli : $ 1024,1024,1,1 gtutor_fwheelie. 0.5,67,1,0.25,0,-3 gtutor_specplot. name. circ_segment_triangle

gtutor_fwheelie :
   # Pseudo assignment expands to command line arguments
   $=a

   # Expect data triplets $a1,$a2,$a3…

   -check {!($#%3)}
 
    $=a
    dwheelcnt={$#/3}
    -input $dwheelcnt,1,1,3
    -name. args
    -repeat $# j=$>
       if   $j%3==0
           -set[args] ${a{$j+1}},{int($j/3)},0,0,0
       elif $j%3==1
           -set[args] ${a{$j+1}},{int($j/3)},0,0,1
       else
           -set[args] ${a{$j+1}},{int($j/3)},0,0,2
       fi
    -done
    -store[args] deltawheelies

   foreach {
      # For each selected image:
      # Fetch and check radius
      # velocity parameters. Aggregate Σf -> $accsf; Σθ → $acca
      # specw={k=int(min(w,h)/2);!(k%2)?k+1:k}
      specw={int(min(w,h)/2)}

      #coeffcient image
      -input $specw,1,1,2
      -name carray
      -store[carray] coefficientarray

      # Iterate over arguments; populate carray and aggregate.
   
      -eval "const wc=$dwheelcnt;
             const sw=$specw;
	     dw=get('deltawheelies',wc*3);
	     ca=get('coefficientarray',sw*2);
	     acca=0;
	     accsf=0;
	     repeat(
                      wc,
                      k,
                      r=dw[k];
                      acca+=deg2rad(dw[wc+k]);
                      accsf=dw[2*wc+k]+accsf;
		      aidx=accsf%sw;
                      ca[aidx]+=r*cos(acca);
                      ca[sw+aidx]+=r*sin(acca);
                   );
             store('coefficientarray',ca,sw,1,1,2)"
   
      # Scale freq. dom. by dom. length - for ifft.
      # carray: frequency domain image generated from
      # the given wheelie chain.
      -input $coefficientarray
      -name. carray
      -mul[carray] $specw
      -keep[carray]
   }

#@cli gtutor_specplot : 
#@cli : Generate a phase plot from the selected frequency
#@cli : domain images.

gtutor_specplot :
   -foreach {
        # Frequency domain → time domain
        -name. carray
        -split[carray] c
        -ifft[-2,-1]
        -append[-2,-1] c
        -name. temporal
        sw={w#$temporal}
     
        # Screenspace transform.
        -fill[temporal] ">
                         begin(
                                specw=w#$temporal;
                                id=eye(3);
                                id[0]=specw;
                                id[2]=specw;
                                id[4]=-specw;
                                id[5]=specw;
                              );
                         (id*[I(x,y),1])[0,2];
                       "
        -permute[temporal] cyzx
        -input {2*$sw},{2*$sw},1,1
        -name. canvas
        -eval[canvas] "begin(
                              PV=crop(#$temporal);
                              polygon(
                                       #$canvas,
                                       -int(size(PV)/2),
                                       PV,
                                       1,
                                       0xffffffff,
                                       255
                                     )
                            )"
        -keep[canvas]
     }

Tomorrow looks like a good writing day. Might even push this Cookbook thing…

5 Likes