G'MIC Tutorial Fragments

Tutorial request:

I found this on cimg.h

#if cimg_display==1
    // Define keycodes for X11-based graphical systems.
    const unsigned int keyESC        = XK_Escape;
    const unsigned int keyF1         = XK_F1;
    const unsigned int keyF2         = XK_F2;
    const unsigned int keyF3         = XK_F3;
    const unsigned int keyF4         = XK_F4;
    const unsigned int keyF5         = XK_F5;
    const unsigned int keyF6         = XK_F6;
    const unsigned int keyF7         = XK_F7;
    const unsigned int keyF8         = XK_F8;
    const unsigned int keyF9         = XK_F9;
    const unsigned int keyF10        = XK_F10;
    const unsigned int keyF11        = XK_F11;
    const unsigned int keyF12        = XK_F12;
    const unsigned int keyPAUSE      = XK_Pause;
    const unsigned int key1          = XK_1;
    const unsigned int key2          = XK_2;
    const unsigned int key3          = XK_3;
    const unsigned int key4          = XK_4;
    const unsigned int key5          = XK_5;
    const unsigned int key6          = XK_6;
    const unsigned int key7          = XK_7;
    const unsigned int key8          = XK_8;
    const unsigned int key9          = XK_9;
    const unsigned int key0          = XK_0;
    const unsigned int keyBACKSPACE  = XK_BackSpace;
    const unsigned int keyINSERT     = XK_Insert;
    const unsigned int keyHOME       = XK_Home;
    const unsigned int keyPAGEUP     = XK_Page_Up;
    const unsigned int keyTAB        = XK_Tab;
    const unsigned int keyQ          = XK_q;
    const unsigned int keyW          = XK_w;
    const unsigned int keyE          = XK_e;
    const unsigned int keyR          = XK_r;
    const unsigned int keyT          = XK_t;
    const unsigned int keyY          = XK_y;
    const unsigned int keyU          = XK_u;
    const unsigned int keyI          = XK_i;
    const unsigned int keyO          = XK_o;
    const unsigned int keyP          = XK_p;
    const unsigned int keyDELETE     = XK_Delete;
    const unsigned int keyEND        = XK_End;
    const unsigned int keyPAGEDOWN   = XK_Page_Down;
    const unsigned int keyCAPSLOCK   = XK_Caps_Lock;
    const unsigned int keyA          = XK_a;
    const unsigned int keyS          = XK_s;
    const unsigned int keyD          = XK_d;
    const unsigned int keyF          = XK_f;
    const unsigned int keyG          = XK_g;
    const unsigned int keyH          = XK_h;
    const unsigned int keyJ          = XK_j;
    const unsigned int keyK          = XK_k;
    const unsigned int keyL          = XK_l;
    const unsigned int keyENTER      = XK_Return;
    const unsigned int keySHIFTLEFT  = XK_Shift_L;
    const unsigned int keyZ          = XK_z;
    const unsigned int keyX          = XK_x;
    const unsigned int keyC          = XK_c;
    const unsigned int keyV          = XK_v;
    const unsigned int keyB          = XK_b;
    const unsigned int keyN          = XK_n;
    const unsigned int keyM          = XK_m;
    const unsigned int keySHIFTRIGHT = XK_Shift_R;
    const unsigned int keyARROWUP    = XK_Up;
    const unsigned int keyCTRLLEFT   = XK_Control_L;
    const unsigned int keyAPPLEFT    = XK_Super_L;
    const unsigned int keyALT        = XK_Alt_L;
    const unsigned int keySPACE      = XK_space;
    const unsigned int keyALTGR      = XK_Alt_R;
    const unsigned int keyAPPRIGHT   = XK_Super_R;
    const unsigned int keyMENU       = XK_Menu;
    const unsigned int keyCTRLRIGHT  = XK_Control_R;
    const unsigned int keyARROWLEFT  = XK_Left;
    const unsigned int keyARROWDOWN  = XK_Down;
    const unsigned int keyARROWRIGHT = XK_Right;
    const unsigned int keyPAD0       = XK_KP_0;
    const unsigned int keyPAD1       = XK_KP_1;
    const unsigned int keyPAD2       = XK_KP_2;
    const unsigned int keyPAD3       = XK_KP_3;
    const unsigned int keyPAD4       = XK_KP_4;
    const unsigned int keyPAD5       = XK_KP_5;
    const unsigned int keyPAD6       = XK_KP_6;
    const unsigned int keyPAD7       = XK_KP_7;
    const unsigned int keyPAD8       = XK_KP_8;
    const unsigned int keyPAD9       = XK_KP_9;
    const unsigned int keyPADADD     = XK_KP_Add;
    const unsigned int keyPADSUB     = XK_KP_Subtract;
    const unsigned int keyPADMUL     = XK_KP_Multiply;
    const unsigned int keyPADDIV     = XK_KP_Divide;

#elif cimg_display==2
    // Define keycodes for Windows.
    const unsigned int keyESC        = VK_ESCAPE;
    const unsigned int keyF1         = VK_F1;
    const unsigned int keyF2         = VK_F2;
    const unsigned int keyF3         = VK_F3;
    const unsigned int keyF4         = VK_F4;
    const unsigned int keyF5         = VK_F5;
    const unsigned int keyF6         = VK_F6;
    const unsigned int keyF7         = VK_F7;
    const unsigned int keyF8         = VK_F8;
    const unsigned int keyF9         = VK_F9;
    const unsigned int keyF10        = VK_F10;
    const unsigned int keyF11        = VK_F11;
    const unsigned int keyF12        = VK_F12;
    const unsigned int keyPAUSE      = VK_PAUSE;
    const unsigned int key1          = '1';
    const unsigned int key2          = '2';
    const unsigned int key3          = '3';
    const unsigned int key4          = '4';
    const unsigned int key5          = '5';
    const unsigned int key6          = '6';
    const unsigned int key7          = '7';
    const unsigned int key8          = '8';
    const unsigned int key9          = '9';
    const unsigned int key0          = '0';
    const unsigned int keyBACKSPACE  = VK_BACK;
    const unsigned int keyINSERT     = VK_INSERT;
    const unsigned int keyHOME       = VK_HOME;
    const unsigned int keyPAGEUP     = VK_PRIOR;
    const unsigned int keyTAB        = VK_TAB;
    const unsigned int keyQ          = 'Q';
    const unsigned int keyW          = 'W';
    const unsigned int keyE          = 'E';
    const unsigned int keyR          = 'R';
    const unsigned int keyT          = 'T';
    const unsigned int keyY          = 'Y';
    const unsigned int keyU          = 'U';
    const unsigned int keyI          = 'I';
    const unsigned int keyO          = 'O';
    const unsigned int keyP          = 'P';
    const unsigned int keyDELETE     = VK_DELETE;
    const unsigned int keyEND        = VK_END;
    const unsigned int keyPAGEDOWN   = VK_NEXT;
    const unsigned int keyCAPSLOCK   = VK_CAPITAL;
    const unsigned int keyA          = 'A';
    const unsigned int keyS          = 'S';
    const unsigned int keyD          = 'D';
    const unsigned int keyF          = 'F';
    const unsigned int keyG          = 'G';
    const unsigned int keyH          = 'H';
    const unsigned int keyJ          = 'J';
    const unsigned int keyK          = 'K';
    const unsigned int keyL          = 'L';
    const unsigned int keyENTER      = VK_RETURN;
    const unsigned int keySHIFTLEFT  = VK_SHIFT;
    const unsigned int keyZ          = 'Z';
    const unsigned int keyX          = 'X';
    const unsigned int keyC          = 'C';
    const unsigned int keyV          = 'V';
    const unsigned int keyB          = 'B';
    const unsigned int keyN          = 'N';
    const unsigned int keyM          = 'M';
    const unsigned int keySHIFTRIGHT = VK_SHIFT;
    const unsigned int keyARROWUP    = VK_UP;
    const unsigned int keyCTRLLEFT   = VK_CONTROL;
    const unsigned int keyAPPLEFT    = VK_LWIN;
    const unsigned int keyALT        = VK_LMENU;
    const unsigned int keySPACE      = VK_SPACE;
    const unsigned int keyALTGR      = VK_CONTROL;
    const unsigned int keyAPPRIGHT   = VK_RWIN;
    const unsigned int keyMENU       = VK_APPS;
    const unsigned int keyCTRLRIGHT  = VK_CONTROL;
    const unsigned int keyARROWLEFT  = VK_LEFT;
    const unsigned int keyARROWDOWN  = VK_DOWN;
    const unsigned int keyARROWRIGHT = VK_RIGHT;
    const unsigned int keyPAD0       = 0x60;
    const unsigned int keyPAD1       = 0x61;
    const unsigned int keyPAD2       = 0x62;
    const unsigned int keyPAD3       = 0x63;
    const unsigned int keyPAD4       = 0x64;
    const unsigned int keyPAD5       = 0x65;
    const unsigned int keyPAD6       = 0x66;
    const unsigned int keyPAD7       = 0x67;
    const unsigned int keyPAD8       = 0x68;
    const unsigned int keyPAD9       = 0x69;
    const unsigned int keyPADADD     = VK_ADD;
    const unsigned int keyPADSUB     = VK_SUBTRACT;
    const unsigned int keyPADMUL     = VK_MULTIPLY;
    const unsigned int keyPADDIV     = VK_DIVIDE;

#else
    // Define random keycodes when no display is available.
    // (should rarely be used then!).
    const unsigned int keyESC        = 1U;   //!< Keycode for the \c ESC key (architecture-dependent)
    const unsigned int keyF1         = 2U;   //!< Keycode for the \c F1 key (architecture-dependent)
    const unsigned int keyF2         = 3U;   //!< Keycode for the \c F2 key (architecture-dependent)
    const unsigned int keyF3         = 4U;   //!< Keycode for the \c F3 key (architecture-dependent)
    const unsigned int keyF4         = 5U;   //!< Keycode for the \c F4 key (architecture-dependent)
    const unsigned int keyF5         = 6U;   //!< Keycode for the \c F5 key (architecture-dependent)
    const unsigned int keyF6         = 7U;   //!< Keycode for the \c F6 key (architecture-dependent)
    const unsigned int keyF7         = 8U;   //!< Keycode for the \c F7 key (architecture-dependent)
    const unsigned int keyF8         = 9U;   //!< Keycode for the \c F8 key (architecture-dependent)
    const unsigned int keyF9         = 10U;  //!< Keycode for the \c F9 key (architecture-dependent)
    const unsigned int keyF10        = 11U;  //!< Keycode for the \c F10 key (architecture-dependent)
    const unsigned int keyF11        = 12U;  //!< Keycode for the \c F11 key (architecture-dependent)
    const unsigned int keyF12        = 13U;  //!< Keycode for the \c F12 key (architecture-dependent)
    const unsigned int keyPAUSE      = 14U;  //!< Keycode for the \c PAUSE key (architecture-dependent)
    const unsigned int key1          = 15U;  //!< Keycode for the \c 1 key (architecture-dependent)
    const unsigned int key2          = 16U;  //!< Keycode for the \c 2 key (architecture-dependent)
    const unsigned int key3          = 17U;  //!< Keycode for the \c 3 key (architecture-dependent)
    const unsigned int key4          = 18U;  //!< Keycode for the \c 4 key (architecture-dependent)
    const unsigned int key5          = 19U;  //!< Keycode for the \c 5 key (architecture-dependent)
    const unsigned int key6          = 20U;  //!< Keycode for the \c 6 key (architecture-dependent)
    const unsigned int key7          = 21U;  //!< Keycode for the \c 7 key (architecture-dependent)
    const unsigned int key8          = 22U;  //!< Keycode for the \c 8 key (architecture-dependent)
    const unsigned int key9          = 23U;  //!< Keycode for the \c 9 key (architecture-dependent)
    const unsigned int key0          = 24U;  //!< Keycode for the \c 0 key (architecture-dependent)
    const unsigned int keyBACKSPACE  = 25U;  //!< Keycode for the \c BACKSPACE key (architecture-dependent)
    const unsigned int keyINSERT     = 26U;  //!< Keycode for the \c INSERT key (architecture-dependent)
    const unsigned int keyHOME       = 27U;  //!< Keycode for the \c HOME key (architecture-dependent)
    const unsigned int keyPAGEUP     = 28U;  //!< Keycode for the \c PAGEUP key (architecture-dependent)
    const unsigned int keyTAB        = 29U;  //!< Keycode for the \c TAB key (architecture-dependent)
    const unsigned int keyQ          = 30U;  //!< Keycode for the \c Q key (architecture-dependent)
    const unsigned int keyW          = 31U;  //!< Keycode for the \c W key (architecture-dependent)
    const unsigned int keyE          = 32U;  //!< Keycode for the \c E key (architecture-dependent)
    const unsigned int keyR          = 33U;  //!< Keycode for the \c R key (architecture-dependent)
    const unsigned int keyT          = 34U;  //!< Keycode for the \c T key (architecture-dependent)
    const unsigned int keyY          = 35U;  //!< Keycode for the \c Y key (architecture-dependent)
    const unsigned int keyU          = 36U;  //!< Keycode for the \c U key (architecture-dependent)
    const unsigned int keyI          = 37U;  //!< Keycode for the \c I key (architecture-dependent)
    const unsigned int keyO          = 38U;  //!< Keycode for the \c O key (architecture-dependent)
    const unsigned int keyP          = 39U;  //!< Keycode for the \c P key (architecture-dependent)
    const unsigned int keyDELETE     = 40U;  //!< Keycode for the \c DELETE key (architecture-dependent)
    const unsigned int keyEND        = 41U;  //!< Keycode for the \c END key (architecture-dependent)
    const unsigned int keyPAGEDOWN   = 42U;  //!< Keycode for the \c PAGEDOWN key (architecture-dependent)
    const unsigned int keyCAPSLOCK   = 43U;  //!< Keycode for the \c CAPSLOCK key (architecture-dependent)
    const unsigned int keyA          = 44U;  //!< Keycode for the \c A key (architecture-dependent)
    const unsigned int keyS          = 45U;  //!< Keycode for the \c S key (architecture-dependent)
    const unsigned int keyD          = 46U;  //!< Keycode for the \c D key (architecture-dependent)
    const unsigned int keyF          = 47U;  //!< Keycode for the \c F key (architecture-dependent)
    const unsigned int keyG          = 48U;  //!< Keycode for the \c G key (architecture-dependent)
    const unsigned int keyH          = 49U;  //!< Keycode for the \c H key (architecture-dependent)
    const unsigned int keyJ          = 50U;  //!< Keycode for the \c J key (architecture-dependent)
    const unsigned int keyK          = 51U;  //!< Keycode for the \c K key (architecture-dependent)
    const unsigned int keyL          = 52U;  //!< Keycode for the \c L key (architecture-dependent)
    const unsigned int keyENTER      = 53U;  //!< Keycode for the \c ENTER key (architecture-dependent)
    const unsigned int keySHIFTLEFT  = 54U;  //!< Keycode for the \c SHIFTLEFT key (architecture-dependent)
    const unsigned int keyZ          = 55U;  //!< Keycode for the \c Z key (architecture-dependent)
    const unsigned int keyX          = 56U;  //!< Keycode for the \c X key (architecture-dependent)
    const unsigned int keyC          = 57U;  //!< Keycode for the \c C key (architecture-dependent)
    const unsigned int keyV          = 58U;  //!< Keycode for the \c V key (architecture-dependent)
    const unsigned int keyB          = 59U;  //!< Keycode for the \c B key (architecture-dependent)
    const unsigned int keyN          = 60U;  //!< Keycode for the \c N key (architecture-dependent)
    const unsigned int keyM          = 61U;  //!< Keycode for the \c M key (architecture-dependent)
    const unsigned int keySHIFTRIGHT = 62U;  //!< Keycode for the \c SHIFTRIGHT key (architecture-dependent)
    const unsigned int keyARROWUP    = 63U;  //!< Keycode for the \c ARROWUP key (architecture-dependent)
    const unsigned int keyCTRLLEFT   = 64U;  //!< Keycode for the \c CTRLLEFT key (architecture-dependent)
    const unsigned int keyAPPLEFT    = 65U;  //!< Keycode for the \c APPLEFT key (architecture-dependent)
    const unsigned int keyALT        = 66U;  //!< Keycode for the \c ALT key (architecture-dependent)
    const unsigned int keySPACE      = 67U;  //!< Keycode for the \c SPACE key (architecture-dependent)
    const unsigned int keyALTGR      = 68U;  //!< Keycode for the \c ALTGR key (architecture-dependent)
    const unsigned int keyAPPRIGHT   = 69U;  //!< Keycode for the \c APPRIGHT key (architecture-dependent)
    const unsigned int keyMENU       = 70U;  //!< Keycode for the \c MENU key (architecture-dependent)
    const unsigned int keyCTRLRIGHT  = 71U;  //!< Keycode for the \c CTRLRIGHT key (architecture-dependent)
    const unsigned int keyARROWLEFT  = 72U;  //!< Keycode for the \c ARROWLEFT key (architecture-dependent)
    const unsigned int keyARROWDOWN  = 73U;  //!< Keycode for the \c ARROWDOWN key (architecture-dependent)
    const unsigned int keyARROWRIGHT = 74U;  //!< Keycode for the \c ARROWRIGHT key (architecture-dependent)
    const unsigned int keyPAD0       = 75U;  //!< Keycode for the \c PAD0 key (architecture-dependent)
    const unsigned int keyPAD1       = 76U;  //!< Keycode for the \c PAD1 key (architecture-dependent)
    const unsigned int keyPAD2       = 77U;  //!< Keycode for the \c PAD2 key (architecture-dependent)
    const unsigned int keyPAD3       = 78U;  //!< Keycode for the \c PAD3 key (architecture-dependent)
    const unsigned int keyPAD4       = 79U;  //!< Keycode for the \c PAD4 key (architecture-dependent)
    const unsigned int keyPAD5       = 80U;  //!< Keycode for the \c PAD5 key (architecture-dependent)
    const unsigned int keyPAD6       = 81U;  //!< Keycode for the \c PAD6 key (architecture-dependent)
    const unsigned int keyPAD7       = 82U;  //!< Keycode for the \c PAD7 key (architecture-dependent)
    const unsigned int keyPAD8       = 83U;  //!< Keycode for the \c PAD8 key (architecture-dependent)
    const unsigned int keyPAD9       = 84U;  //!< Keycode for the \c PAD9 key (architecture-dependent)
    const unsigned int keyPADADD     = 85U;  //!< Keycode for the \c PADADD key (architecture-dependent)
    const unsigned int keyPADSUB     = 86U;  //!< Keycode for the \c PADSUB key (architecture-dependent)
    const unsigned int keyPADMUL     = 87U;  //!< Keycode for the \c PADMUL key (architecture-dependent)
    const unsigned int keyPADDIV     = 88U;  //!< Keycode for the \c PADDDIV key (architecture-dependent)
#endif

These points to all keyboard keys available for use in creation of interactive filter. I don’t recall a page where you can see all available ones.

Also, I note no period or comma there. No '[' or ']' either.

Lazy Arabesques
Related to Post 76. It’s great grandfather is the Roses one liner. And, there is an appearance of epicycles, but written in G’MIC this time, and not Python. Epicycles constitute the grande finale graphic of the upcoming Cookbook, and then there is this:


If I was a decent fellow, I’d post the listing for this, but the listing for this is a mess at the moment. It will be constituted, in some way or sideways, in the Arabesque Cookbook, coming next week in a tutorial set near you. For now, let it be known that the wheelies (epicycles) which draw arabesques live in the alternate reality of the frequency domain, where the analogues drift about in a lazy way. Back here in the time domain, a little z-blurring across frames renders the arabesques ever more languid. That’s it for now. Time to finish this thing. I said ‘next week’ last September, dammit.

3 Likes

Resurgence of the screen saver? At least in the mind of @grosgood… With some tweaks and a randomizer, it has the potential to be a fun G’MIC demo, among the existing ones like the Tower of Hanoi, if you are willing to put it there.

Take your time. There are a lot of TODOs on my side. Mostly optimization and better coding to existing script which is plenty of fun and sometimes boring to do.

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…

4 Likes

Garry, that’s beautiful. I couldn’t resist sharing your post on Twitter :slight_smile:

Glad to see you back with new stuffs!

1 Like

@grosgood The warping of the cat is fine but the shaking gives me an eye-/headache. :face_with_spiral_eyes:

It’s an outgrowth of the warp field eventually spanning the entire image, pulling all pixels, and these subject to rapidly changing gradient directions. That seemed in keeping with the feline abuse theme, but — while aesthetically consistent — I myself don’t find it pleasing; I’ve put it in the kit for whenever I need a cheap earthquake effect.