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…