Appendix

-tiletex Script

This follows the first version, released 19-July-2017. If you are using a Unix-like operating system, copy/paste this script into your $HOME/.gmic file, or, for recent Microsoft Windows, your %APPDATA%/<user>.gmic file. If you don't have such, then let this script become the initial content of that file.

#@cli tiletex : _texscale=8 autoangle=-1 _keepimag=0
#@cli : Renders a tilable texture on selected images, taking polar formatted
#@cli : (magnitude, phase angle) seed values from pairs of selected,
#@cli : alternating "Magnitude" and "Angle" images or, if these are constant
#@cli : black, then from internally generated random values. Unless
#@cli : 'autoangle' is positive, input images must form "Magnitude" and
#@cli : "Angle" pairs and each pair must have an equal number of
#@cli : channels. Produces "real" and "imaginary" output images (But note
#@cli : _keepimag, below). 'texscale' sets the size of a square window around
#@cli : the spectral origin where random seeds are set. Larger 'texscales'
#@cli : settings admit higher frequency coefficients, giving rise to finer
#@cli : output details. 'texscale' ranges from 1 upward and defaults to 8. It
#@cli : is ignored if the user has preset coefficients within the input
#@cli : images. Setting 'autoangle' to a positive value in the range [0, 255]
#@cli : eliminates the need for providing "Angle" input images. The provided
#@cli : argument is applied as a default phase angle to all "Magnitude" data
#@cli : and input images are taken to be "Magnitude" data only. 'keepimag' is
#@cli : a trivalued flag: 0, 1 or 2. '0' requests both "Real" and "Imaginary"
#@cli : output pairs and is the default. '1' requests the "Real" output image
#@cli : only; '2' requests the "Imaginary" output image only.
#@cli : Output images are unnormalized and range from negative to positive
#@cli : values, Normalize data accordingly for use with bitmap editors.
tiletex : -check "${1=8}>0 && isval(${2=-1.0}) && ${3=0}>=0 && ${3}<3"
-verbose -
-if {$2>=0}
   addenda2="Common default angle: $2."
-else
   addenda2="Explicit angles from provided images."
-endif
addenda3="Real and imaginary"
-if {$3!=0}
   -if {$3==1}
      addenda3="Real"
   -else 
      addenda3="Imaginary"
   -endif
-endif
-verbose +
-echo[^-1] "Rendering tilable texture on $? at window size $1 "$addenda2". "$addenda3" output to be provided." 
-verbose -
rsz={$1}
impla={2*pi*$2/255.0}
all={$3}
iszed=1
ccc={s#0}
badccc="Selected images have different number of channels. Have you accidently included alpha channels in some (but not all) images?"
-repeat $!
  -if {round(ia#$>)!=0||round(iM#$>-im#$>)!=0}
    iszed=0
    -break
  -endif
-done
-if $iszed # Case 0: All images black. Generate random values
   -repeat $!
      -local[$<]
         -if {$ccc!={s#$<}
            -error $badccc
         -endif
         -input [-1]
         -append[-2,-1] c
         -input {2*$rsz+1},{2*$rsz+1},1,{s#-1},(2*u-1)*(w#-1*h#-1)
         -image[-2] [-1],{(w#-2-w#-1)/2},{(h#-2-h#-1)/2},0,0,1
         -remove[-1]
      -endlocal
   -done
-else # Case 1: Coefficients in polar format have been set in at least one selected image.
   -if {$impla<0} # Case 1.1: $impla not set (still negative guardian value). Images must be <radius>, <angle> image pairs.
      -if {$!%2!=0}
         -error "Selected images contain data, but selection count is odd. Cannot determine angles for some coefficients. Consider setting an implied angle or providing an even number of images."
      -endif
      -repeat {$!/2}
         -local[{2*$<},{2*$<+1}]
            -if {($ccc!=s#$<)||($ccc!=s#($<+1))}
               -error $badccc
            -endif
            -split[-2,-1] c
            -repeat {$!/2}
                -local[{$>},{$!/2+$>}]
                   -div[0,1] 255
                   -mul[1] {2*pi}
                   -polar2complex[0,1]
                -endlocal
            -done
            -append[0--1] c
         -endlocal
      -done
   -else # Case 1.2: Odd numbered selection permitted when $impla is not negative. Furnishes constant angle field.
      -repeat {$!}
         -local[$<]
            -if {$ccc!=s#$<}
               -error $badccc
            -endif
            -input [0]
            -split[-2,-1] c
            -repeat {$!/2}
               -local[{$>},{$!/2+$>}]
                  -div[0,1] 255
                  -mul[0] {cos($impla)} 
                  -mul[1] {sin($impla)}
               -endlocal
            -done
            -append[0--1] c
         -endlocal
      -done
   -endif
-endif
-repeat $!
   -local[$<]
      -shift[-1] -50%,-50%,0,0,2
      -split[-1] c,2
      -ifft[-2,-1]
      -if {$all!=0}
         -if {$all==1}
            -remove[-1]
         -else
            -remove[-2]
         -endif
      -endif
   -endlocal
-done
-verbose +

The Polar Form Used By -tiletex

Figure 14: Conversion between polar and rectangular forms.

Since most paint programs have difficulty with negative numbers, -tiletex interprets selected image pairs as <radius>, <angle> data sets instead of <real>, <imaginary> ones. This “polar form” consists entirely of non-negative numbers:

  1. We base <radius> data on the Pythagorean theorem, which always returns a non-negative measure. It regards the <real> and <imaginary> components as the sides of a right triangle; <radius> is then the hypotenuse.
  2. We derive <angle> from the arctangent relation, using the ratio <imaginary>:<real>to compute the angle subtended by the imaginary side. Resulting angles range over the interval [–180°, … +180°], ([–π, … π]) but no change in meaning occurs if we offset negative angles by 360° (2π), an identity relation. That means we can make images fully specifying complex coefficients, but without using negative values.

In practice, we express radial and angular data in separate images, scaling both to the range of 0 – 255, suitable for unsigned eight bit integers. Extension to color is straightforward, commonly employing a “radius” or “magnitude” image with three RGB channels, and another “angular” image, also with three RGB channels. The inverse Fourier transform performs independent transforms on the three channels.

To “paint” coefficients in spectral space, we start up our favorite paint program and create a new image with separate “Magnitude” and “Angle” layers. It is straightforward to plot both components in a coordinated way by keeping one or the other layer translucent during plotting. The canonical tool for coefficient painting is the Pencil tool with a brush size of one pixel, but the Airbrush tool operating in “Dissolve” mode sets a nice mess of coefficients en masse.

Setting -tiletex's second argument, “autoangle”, to a constant default angle eliminates the need for a custom “Angle” layer, albeit with some loss in flexibility. Only a “Magnitude” layer needs to be prepared; “Angle” defaults to the argument given for “autoangle.”

When finished, save (or export) the “Magnitude” and (possibly) “Angle” layers as separate images. These become selections for -tiletex, positioned on the image list in “Magnitude,” “Angle” order. If you didn't paint an explicit “Angle” image, set the second parameter “autoangle” to some default measure in the range of 0,255. Zero works well if you have no compelling preference. Setting “keepimag” to 0 returns both the real and imaginary components of the resulting spatial transform, 1 limits the return to just the real image, 2 limits the return to just the imaginary image.