The fill expression equivalent would be just +f bool(i)
.
Even more confusing. +f !!i
The fill expression equivalent would be just +f bool(i)
.
Even more confusing. +f !!i
I was far from all that… I was going for fill "i>0"
but didn’t know what to put next, like how to tell it to fill with this or that color. I should re- read all the tutorial.
EDIT : so in the end i have these two solutions :
Flood with alpha 0:
+blend alpha,1 to_a.
flood. 0,100%,0,255,0,1,255,255,255,0
blend[-1,-2] alpha,1
label_fg (I still had to flood it because fill would make the background white):
[0],[0],1,3,255 mv. 1 +blend[-1,-2] alpha,1
+label_fg. 20,0,0 fill. !!i
flood. 0,100%,0,0,0,1,0,0,0 n. 0,255 d a[0] [-1],c keep[0,2]
There is a difference though:
Flood ( there is still some kind of color outline):
Label+fill (no color outline left yay!).
deform
on the source image before label+fill changes the output. Some regions are not filled):Changed the design a bit, so it’s a bit more stretched and rounder on the top:
Seems like you have moved up your game.
Well, in the end it’s still just a bunch of splines in a repeat loop. I’m trying to put things together until i get what i’m looking for. I think i’m more lucky than anything else
And i was tired of circles hahaha…
Not wasted for me. I’m a writer. I explain stuff — just for the sheer jollies. And — who knows? — I might trigger one of your famously light-hearted and insouciant animations that brings such songs to my heart.
What kind of songs — ? Um. Let’s not go there…
Ah! So, the typewriter game. Hit a key. The face of the typebar strikes the paper, impressing some glyph upon it. Then the carriage translates at a set displacement, as is the wont for monspaced fonts. At the right margin, a carriage return removes all those displacements, translating back to the start point, then translates to the next row by the same set displacement, but vertical. So goes the catalogue of translations, cyclically applied, uniform: perhaps left-left-left-left-4-times-right-and-down, then again, and again, and again `til arms are bloody stumps, perhaps.
Game pieces:
2.
of Game play.curve
command consumes glyphs and plays a connect-the-dots game with these plots, drawing the glyph.Game play:
Implementation:
A custom command, stampit
in steprepeat.gmic
carries out the game play. For example, here is a 5 × 3 stamping of a glyph rotated at 11° on a 979 × 1104 image.
gmic -m steprepeat.gmic {979*2},{1103*2+1},1,4 stampit. 5,3,11 r2dx. 50%,5 o. stampit_5-3-11.png
Output image [0] as png file 'stampit_5-3-11.png' (1 image 979x1104x1x4).
The smallest stride arises along the horizontal dimension, so there are large top-and-bottom margins.
A custom command, steprepeat
, implemented below, performs the step-and-repeat pattern. It harnesses a fixed path image — the glyph — here rendered orange and generated by a gtutor_mkspectral
/gtutor_specplot
command pair. These ABN Filigree extracts fabricate paths from spinner chains (aka “wheelies”). How they come about is a story full of prodigious interest and indelible charm, but it is not the story here. The story here is playing the typewriter game with glyphs: the step-wise transit of these from place to place and how one might do that without bloodying oneself at a keyboard.
stampit: check isint(${1=1})" && "\
${1}>0" && "\
isint(${2=1})" && "\
${2}>0" && "\
isnum(${3=0})
stpx,stpy,rot=${1-3} # stepx, stepy and rotation in degrees.
foreach {
-name. canvas
# mkspectral + specplot: Plots the path made by the tip of the last
# spinner on a chain of spinners.
# Path is in an origin-centered, ±unit square and is 2 units
# on a side, each straddling the x or y axes. Arguments: 250
# plots: path computed from three linked spinners each ≈1/3 in
# length, all with 0° orientation and each spinning at 1, 3 and -13
# Hertz, respectively.
-gtutor_mkspectral 250,{0.95/3},0,1,{0.95/3},0,3,{0.95/3},0,-13 # filigree
# -gtutor_mkspectral 120,{0.95/2},0,1,{0.95/2},0,3 # 3-petal rose
# -gtutor_mkspectral 60,{0.95/3},0,1,{0.95/3},0,2,{0.95/3},0,-4 # bowtie
# -gtutor_mkspectral 20,{0.95},0,1 # circle
-gtutor_specplot. # Spectral ⇒ temporal conversion. Selected now a path.
-name. plots
-steprepeat[canvas] [plots],$stpx,$stpy,$rot
-remove[plots]
}
steprepeat : check ${"is_image_arg $1"}" && "\
isint(${2=1})" && "\
${2}>=0" && "\
isint(${3=1})" && "\
${3}>=0" && "\
isint(${3=1})" && "\
${4}>=0
sx,sy,srot=${2-4} # Horizontal, vertical step counts and rotation angle, degrees.
e[^-1] "Step and repeat given path $1 on image$? $2 times across and $3 times down."
pass$1
foreach {
nm={n}
-name. canvas
w,h:=w#$canvas,h#$canvas # canvas dimensions: pels
dx:=round($w/$sx,1,-1) # across step length in pels, nearest lower whole pel.
dy:=round($h/$sy,1,-1) # down step length in pels, nearest lower whole pel.
s:=min($dx,$dy) # minimum across or down step lengths. s: stride. s × s: bounding box.
mx:=($w-$s*$sx)/2 # across margin: (img. width – ( step length × horiz.step count.))/2
my:=($h-$s*$sy)/2 # down margin: (img. height – ( step length × vert. step count.))/2
pass. # path plotted in the origin-centered ±unit square
-name. plots
# Plots for a box that is just a slight smidgen smaller than
# the bounding box. Visualization aid. Rotate, scale, shear,
# translate along with any other path.
-input (-0.99,-0.99^-0.99,0.99^0.99,0.99^0.99,-0.99^-0.99,-0.99)
-name. box
-permute[box] cyzx # swap x,y pairs from width-wise to spectral- (channel-) wise.
# Set up initial transform from ± unit square to bounding box
-moveglyph[plots,box] {$s/2},{-$s/2},{$mx+$s/2},{$my+$s/2},$srot
-repeat {$sy} {
-repeat {$sx} {
-curve[canvas] [plots],4,0,0,1,1,255,200,0,255
-curve[canvas] [box],4,0,0,1,1,0,200,255,64
-moveglyph[plots,box] 1,1,$s,0 # Step plots, box, once, +horizonal
}
-moveglyph[plots,box] 1,1,{-$sx*$s},$s # Step plots, box, -horizontal by one row,
# then step +vertical, once.
}
-keep[canvas]
-name[canvas] $nm
}
remove.
# Compose an affine transformation matrix and apply same
# to a path.
moveglyph : skip ${1=1},${2=1},${3=0},${4=0},${5=0}
sx,sy,tx,ty,r=${1-5}
foreach {
nm={n}
-name. plots
-fill[plots] ">
begin(
M=eye(3);
M[0]=$sx;
M[2]=$tx;
M[4]=$sy;
M[5]=$ty;
$r>0?M=mul(M,rot([0,0,1],$r°),3)
);
(M*[I(x,y),1])[0,2]
"
-name[plots] $nm
}
camtrak:
foreach {
name. canvas
bbs:=min(w#$canvas,h#$canvas)
steps=200
# Make glyph
-gtutor_mkspectral {$steps},0.7,0,1,0.3,0,-4
-name. glyph
-gtutor_specplot[glyph]
# Make path
-gtutor_mkspectral {0.375*$steps},0.9,0,1,0.1,0,-3
-name. track
-gtutor_specplot[track]
# Scale and translate glyph and track into position
-moveglyph[track] {0.4*$bbs},{-0.4*$bbs},{0.4375*w#$canvas},{0.4375*h#$canvas}
-moveglyph[glyph] {0.1*$bbs},{-0.1*$bbs},{I(#$track,0,0)}
# Make (Δx,Δy) displacements to step glyph along track
+shift[track] -1,0,0,0,2
-sub[-1] [-2]
-crop. 1,100%
-name. tangents
# Step and repeat
-repeat {w#$tangents} {
-curve[canvas] [glyph],5,30,50%,0,1,255,64,200
dx,dy:=I(#$tangents,$>+1,0)
-moveglyph[glyph] 1,1,$dx,$dy
}
}
Here’s a key bit. Applying affine transforms to path images can translate them from place to place. Or rotate them around a center point. Or scale them outward or toward critical points. Or shear them vertically or horizontally along center lines. Or do, as an indivisible action, any combination of these affine transformations. Here, the verb “apply”, stands for the action of rewriting the x and y coordinates taken from an initial path image and altering these, in place, to reflect the desired motion. Plotting the revised path image follows, perhaps using curve or some such.
Here’s another key bit. By the agency of revising x and y coordinates, path images retain “memory” of all applied transforms, these back to the initially created tabula rasa. path image. This gives step-and-repeat tasks like the typewriter game a straight forward play:
Get glyph A (made by hand, like box
, or, like plots
, obtained wholesale from a
gtutor_mkspectral
/gtutor_specplot
or similar glyph-generating toolset).
Scale and translate glyph A from the origin-centered, ±unit square to the bounding box
interior. By virtue of their rewriting, the path image coordinates retain these
scalings and translations.
repeat for vertical_steps:
a. repeat for horizontal_steps:
i. plot glyph A
ii. translate glyph A horizontally 1 × stride
Done
b. translate glyph A –(horizontal_steps × stride)
c. translate glyph A vertically 1 × stride
Done
The custom command that does the ‘Apply affine transform’ operation is moveglyph
. It is a wrapper that hides the mechanics of manipulating affine matrices. Give it a scaling, translation or a rotation (or all three). moveglyph
sets up the appropriate affine transform matrix and applies the encoded transforms to the selected image, which is expected to be a path. Plot the path. apply another transform, plot the revised path. Apply another transform. ⇒ ∞. In a sense, the path retains the cumulative effect of the entire sequence of applied transforms.
Affine transforms descend from the garden variety 2×2 rotational/scaling matrices which David illustrated in Post 178 and Post 179 but are “augmented” in the sense that they are denizens of three dimensions and nominally operate on 3D points: (x, y, z) . The outcome of such augmented machinery are projections of 3D points onto 2D surfaces. The extra mechanics permit the inclusion of translation to the pantheon of rotational and scaling transforms, so that affine matrices can, in a uniform way, encode sequences of all three transforms, engendering shapes or motion of a subline character. But users of moveglyph
need not worry about this back story; just provide a path image and ask for some transformation flavor and build up composite transforms in their path images.
Such augmentation opens up new possibilities for ABN Filigrees. In future incantations, that filter will furnish filigreed borders of the ilk shown in Squaring the Circle, except that the border need not be square, nor the filigree element a circle, and the whole enterprise can operate in resolution-independent vector graphics, a way of working that is opening up in G’MIC. The logistics of having a shape follow another shape as a guiding path is not difficult to achieve in this scheme of stepping path images with sequences of affine transforms, as the following toy, camtrak
illustrates (see steprepeat.gmic
, above, for the implementation):
gmic -m steprepeat.gmic 2048,2048,1,3 camtrak. r2dx[0] 50%,5 o. filigree.jpg
Paths:
EDIT: Originally posted with wrong glyph-and-track graphic.
Hi, thanks for the help.
I’m just testing your solution but it seems i’ll have to buy a NASA computer to run it.
On my mac m1:
gmic -m gmic_scripts/steprepeat.gmic run 'tic {979*2},{1103*2+1},1,4 stampit. 6,3,0 r2dx. 50%,5 toc d'
[gmic]./ Start G'MIC interpreter (v.3.3.4).
[gmic]./ Import commands from file 'gmic_scripts/steprepeat.gmic', with debug info (4 new, total: 4740).
[gmic]./run/__run/ Initialize timer.
[gmic]./run/__run/ Input black image at position 0 (1 image 1958x2207x1x4).
[gmic]./run/__run/ Resize 2D image [0] to 50% pixels along the x-axis, while preserving 2D ratio.
[gmic]./run/__run/ Elapsed time: 48.558 s.
[gmic]./run/__run/ Display image [0] = 'canvas'.
Could you test this command? I switched to spectral “circle” BTW:
gmic -m gmic_scripts/steprepeat.gmic run 'tic {979*2},{1103*2+1},1,4 stampit. 5,7,0 r2dx. 50%,5 toc d'
It’s been running for more than 10 minutes i think, and i’m still waiting for it to finish lol.
You’re right. Even with a simple glyph:
# -gtutor_mkspectral 250,{0.95/3},0,1,{0.95/3},0,3,{0.95/3},0,-13 # filigree
# -gtutor_mkspectral 120,{0.95/2},0,1,{0.95/2},0,3 # 3-petal rose
-gtutor_mkspectral 60,{0.95/3},0,1,{0.95/3},0,2,{0.95/3},0,-4 # bowtie
# -gtutor_mkspectral 20,{0.95},0,1 # circle
And bracketing with tic/toc here:
-repeat {$sx} {
-tic
-curve[canvas] [plots],4,0,0,1,1,255,200,0,255
-toc
-curve[canvas] [box],4,0,0,1,1,0,200,255,64
-moveglyph[plots,box] 1,1,$s,0 # Step plots, box, once, +horizonal
I get these elapse times:
gosgood@lydia ~ $ gmic run '-m steprepeat.gmic {979*2},{1103*2+1},1,4 stampit. 6,3,0 r2dx. 50%,5'
[gmic]./ Start G'MIC interpreter (v.3.3.5).
[gmic]./run/__run/ Import commands from file 'steprepeat.gmic', with debug info (4 new, total: 4750).
[gmic]./run/__run/ Input black image at position 0 (1 image 1958x2207x1x4).
[gmic]./run/__run/stampit/*foreach#7/steprepeat/*foreach#37/*repeat#58/*repeat#59/ Elapsed time: 0.002 s.
[gmic]./run/__run/stampit/*foreach#7/steprepeat/*foreach#37/*repeat#58/*repeat#59/ Elapsed time: 0.001 s.
[gmic]./run/__run/stampit/*foreach#7/steprepeat/*foreach#37/*repeat#58/*repeat#59/ Elapsed time: 0.001 s.
[gmic]./run/__run/stampit/*foreach#7/steprepeat/*foreach#37/*repeat#58/*repeat#59/ Elapsed time: 0.001 s.
[gmic]./run/__run/stampit/*foreach#7/steprepeat/*foreach#37/*repeat#58/*repeat#59/ Elapsed time: 0.001 s.
[gmic]./run/__run/stampit/*foreach#7/steprepeat/*foreach#37/*repeat#58/*repeat#59/ Elapsed time: 0.001 s.
[gmic]./run/__run/stampit/*foreach#7/steprepeat/*foreach#37/*repeat#58/*repeat#59/ Elapsed time: 0.001 s.
[gmic]./run/__run/stampit/*foreach#7/steprepeat/*foreach#37/*repeat#58/*repeat#59/ Elapsed time: 0.001 s.
[gmic]./run/__run/stampit/*foreach#7/steprepeat/*foreach#37/*repeat#58/*repeat#59/ Elapsed time: 0.001 s.
[gmic]./run/__run/stampit/*foreach#7/steprepeat/*foreach#37/*repeat#58/*repeat#59/ Elapsed time: 0.001 s.
[gmic]./run/__run/stampit/*foreach#7/steprepeat/*foreach#37/*repeat#58/*repeat#59/ Elapsed time: 0 s.
[gmic]./run/__run/stampit/*foreach#7/steprepeat/*foreach#37/*repeat#58/*repeat#59/ Elapsed time: 0.001 s.
[gmic]./run/__run/stampit/*foreach#7/steprepeat/*foreach#37/*repeat#58/*repeat#59/ Elapsed time: 0.001 s.
[gmic]./run/__run/stampit/*foreach#7/steprepeat/*foreach#37/*repeat#58/*repeat#59/ Elapsed time: 0.001 s.
[gmic]./run/__run/stampit/*foreach#7/steprepeat/*foreach#37/*repeat#58/*repeat#59/ Elapsed time: 0.001 s.
[gmic]./run/__run/stampit/*foreach#7/steprepeat/*foreach#37/*repeat#58/*repeat#59/ Elapsed time: 0.001 s.
[gmic]./run/__run/stampit/*foreach#7/steprepeat/*foreach#37/*repeat#58/*repeat#59/ Elapsed time: 0.001 s.
[gmic]./run/__run/stampit/*foreach#7/steprepeat/*foreach#37/*repeat#58/*repeat#59/ Elapsed time: 0.001 s.
[gmic]./run/__run/stampit/*foreach#7/steprepeat/*foreach#37/*repeat#58/*repeat#59/ Elapsed time: 0 s.
[gmic]./run/__run/stampit/*foreach#7/steprepeat/*foreach#37/*repeat#58/*repeat#59/ Elapsed time: 0 s.
[gmic]./run/__run/stampit/*foreach#7/steprepeat/*foreach#37/*repeat#58/*repeat#59/ Elapsed time: 0.001 s.
[gmic]./run/__run/stampit/*foreach#7/steprepeat/*foreach#37/*repeat#58/*repeat#59/ Elapsed time: 0.001 s.
[gmic]./run/__run/stampit/*foreach#7/steprepeat/*foreach#37/*repeat#58/*repeat#59/ Elapsed time: 0.002 s.
[gmic]./run/__run/stampit/*foreach#7/steprepeat/*foreach#37/*repeat#58/*repeat#59/ Elapsed time: 0.003 s.
[gmic]./run/__run/stampit/*foreach#7/steprepeat/*foreach#37/*repeat#58/*repeat#59/ Elapsed time: 0.005 s.
[gmic]./run/__run/stampit/*foreach#7/steprepeat/*foreach#37/*repeat#58/*repeat#59/ Elapsed time: 0.015 s.
[gmic]./run/__run/stampit/*foreach#7/steprepeat/*foreach#37/*repeat#58/*repeat#59/ Elapsed time: 0.022 s.
[gmic]./run/__run/stampit/*foreach#7/steprepeat/*foreach#37/*repeat#58/*repeat#59/ Elapsed time: 0.037 s.
[gmic]./run/__run/stampit/*foreach#7/steprepeat/*foreach#37/*repeat#58/*repeat#59/ Elapsed time: 0.075 s.
[gmic]./run/__run/stampit/*foreach#7/steprepeat/*foreach#37/*repeat#58/*repeat#59/ Elapsed time: 0.152 s.
[gmic]./run/__run/stampit/*foreach#7/steprepeat/*foreach#37/*repeat#58/*repeat#59/ Elapsed time: 0.321 s.
[gmic]./run/__run/stampit/*foreach#7/steprepeat/*foreach#37/*repeat#58/*repeat#59/ Elapsed time: 0.694 s.
[gmic]./run/__run/stampit/*foreach#7/steprepeat/*foreach#37/*repeat#58/*repeat#59/ Elapsed time: 1.913 s.
[gmic]./run/__run/stampit/*foreach#7/steprepeat/*foreach#37/*repeat#58/*repeat#59/ Elapsed time: 5.137 s.
[gmic]./run/__run/stampit/*foreach#7/steprepeat/*foreach#37/*repeat#58/*repeat#59/ Elapsed time: 24.351 s.
[gmic]./run/__run/stampit/*foreach#7/steprepeat/*foreach#37/*repeat#58/*repeat#59/ Elapsed time: 81.997 s.
[gmic]./run/__run/ Resize 2D image [0] to 50% pixels along the x-axis, while preserving 2D ratio.
[gmic]./ Display image [0] = 'canvas'.
where the time required by curve
grows exponentially in the final iterations.
`tis an odd one, that. Eventually, I do get this image:
Lydia is my knockabout laptop. 16 GB i5-8250 Mobile running at 1.6 gHz, but I bet my workstation won’t fare better. That `hocky-stick time profile is strange indeed…
Time to walk little Vinnie (the dog). Maybe can investigate during morning coffee and a bagel (with cream cheese).
Enjoy the walk & breakfast It’s lunch time here.
I didn’t expect such a slowdown though by just adding a glyph on the line.
Good catch, @prawnsushi. The plot [th/s]ickens! (As always, I much appreciate you breaking my toys — because then the bug hunt is on!)
Here’s the curious bit. If I append
together all my plotting images into one looong! image, then call curve
with ten thousand plots, then tic/toc
returns about 0.008 seconds.
Big glyph:
-gtutor_mkspectral 500,{0.95/3},0,1,{0.95/3},0,3,{0.95/3},0,-13 # filigree
Hacked steprepeat
steprepeat : check ${"is_image_arg $1"}" && "\
isint(${2=1})" && "\
${2}>=0" && "\
isint(${3=1})" && "\
${3}>=0" && "\
isint(${3=1})" && "\
${4}>=0
sx,sy,srot=${2-4} # Horizontal, vertical step counts and rotation angle, degrees.
e[^-1] "Step and repeat given path $1 on image$? $2 times across and $3 times down."
pass$1
foreach {
nm={n}
-name. canvas
w,h:=w#$canvas,h#$canvas # canvas dimensions: pels
dx:=round($w/$sx,1,-1) # across step length in pels, nearest lower whole pel.
dy:=round($h/$sy,1,-1) # down step length in pels, nearest lower whole pel.
s:=min($dx,$dy) # minimum across or down step lengths. s: stride. s × s: bounding box.
mx:=($w-$s*$sx)/2 # across margin: (img. width – ( step length × horiz.step count.))/2
my:=($h-$s*$sy)/2 # down margin: (img. height – ( step length × vert. step count.))/2
pass. # path plotted in the origin-centered ±unit square
-name. glyphplot
# Plots for a box that is just a slight smidgen smaller than
# the bounding box. Visualization aid. Rotate, scale, shear,
# translate along with any other path.
-input (-0.99,-0.99^-0.99,0.99^0.99,0.99^0.99,-0.99^-0.99,-0.99)
-name. boxplot
-permute[boxplot] cyzx # swap x,y pairs from width-wise to spectral- (channel-) wise.
# Set up initial transform from ± unit square to bounding box
-moveglyph[glyphplot,boxplot] {$s/2},{-$s/2},{$mx+$s/2},{$my+$s/2},$srot
-repeat {$sy} {
-repeat {$sx} {
# -tic
# -curve[canvas] [plots],4,0,0,1,1,255,200,0,255
# -toc
# -curve[canvas] [box],4,0,0,1,1,0,200,255,64
+moveglyph.. 1,1,$s,0 # Step plots once +horizonal
-name. glyphplot
+moveglyph.. 1,1,$s,0 # Step box once +horizonal
-name. boxplot
-echo "sx: "$>
}
-if $><($sy-1)
+moveglyph.. 1,1,{-$sx*$s},$s # Step glyphplot -sx*horizontal,
-name. glyphplot # then step glyphplot +sy*vertical.
+moveglyph.. 1,1,{-$sx*$s},$s # Step boxplot -sx*horizontal,
-name. boxplot # then step boxplot +sy*vertical.
-echo "sy: "$>
-fi
}
-append[glyphplot] x
-append[boxplot] x d ,
-tic
-curve[canvas] [glyphplot],4,0,0,1,1,255,200,0,255
-curve[canvas] [boxplot],4,0,0,1,1,0,200,255,64
-toc
-keep[canvas]
-name[canvas] $nm
}
remove.
Produces:
The zig-zags happen because glomming together all of the plots gives no opportunity for a “pen lift” operation. Also, the image management/movement is a bit screwed up, I am printing one image twice.
Don’t know why, yet, why curve
becomes bogged down when called repeatedly with the data set divided, but behaves well when called once with the same data appended together. Stay tuned.
Oh btw, you said :
Blockquote
We’d rather not go off edges
But in my case I want to since the pattern should be seamless.
( Why is it so freaking hard to quote someone on a smartphone? Will fix later if I have to)
Pattern is seamless if you don’t try to extend the border to fit all circles. Unfortunately, so you have to make that option. Just the nature of raster graphics and their discrete units.
Well, what I actually needed to say was that the circles overlap.
What do you mean by that?
Just that the circles in my script are not just drawn side by side but over each other, with a step of 1 radius. In Gary’s example they are drawn side by side.
Because the plot [th/s]ickens every day
And the pieces of my puzzle keep crumblin’ away
But I know, there’s a picture beneath
FNM, Falling to Pieces
Could it be that curve
is afraid of heights and doesn’t want to go down from the abscissa and descend into the abyss?
( Yeah I know, that didn’t help you at all )
Brightens my day, though. Improving the general aspects of a dreary late winter day in Brooklyn is worth some points.
FNM, Falling to Pieces FNM ⇒ Faith No More. Almost went over my head.
Goodness, gracious! Night falls on the eastern shores of the Atlantic pond, and I haven’t given @prawnsushi anything new to break. Probably even now the poor, listless sod could be idly twirling the big dial of some vintage Sears Silvertone 10 transistor radio, looking for `80’s rock-and-roll that might be radiating out into the aether somewhere.
And so it did. Ah — I wasn’t managing steprepeat
’s foreach loop
very well. Under supervised, it looped over the path image arguments as well as those intended to be drawn on. One unintended consequences of such entailed curve being called thirty, forty, maybe fifty times, always with path images containing hundreds of identical (x,y) point pairs. Since curve
takes time to cull plots falling within a close proximity, things rather bogged down. Fixed now.
Post 241 is still pertinent. I decided that Commenting/Uncommenting code line to choose glyphs is too gauche even for demo toys, so spent Sunday Morning After Breakfast rigging ways of calling path images by name. So:
gmic -run '-m steprepeat.gmic 512,256,1,3 4096,2048,1,3 stampit atomicage,256,13,17,63'
plasters 221 1950’s retro atoms, in seventeen rows and thirteen columns, on a couple of variable-sized images. Have fun…
gmic -run '-m steprepeat.gmic 1024,1024,1,3 stampit. knot3210,256,1,1,0 r2dx. 50%,5 o. knot3210.jpg,80'
#@cli stampit : [glyph] | "glyphname",stepx,stepy,rotation
#@cli : Fill selected image with a rectangular array of rotated glyphs.
stampit: skip ${1='circle'}
check isint(${2=100})" && "\ # pcnt => plot count: +integer.
${2}>0" && "\
isint(${3=1})" && "\ # stpx => col count: +integer.
${3}>0" && "\
isint(${4=1})" && "\ # stpy => row count: +integer.
${4}>0" && "\
isnum(${5=0}) # glyph rotation
-if !$!
-return
-fi
pcnt,stpx,stpy,rot=${2-5}
foreach {
nm={n}
-name. canvas
# First argument can be an path image,
# name (string) or index (number)
-if ${"is_image_arg $1"}
-pass$1 0
-else # name or index
gnames=${-_glyphnames}
numargs:=narg($gnames)
-local[] {
-if isint("$1")
glyphname=${"arg0 ($1%"$numargs"),"$gnames}
-else
glyphname=$1
-fi
-_glyph_$glyphname $pcnt
-gtutor_specplot.
-onfail
glyphname=$1
error "Unknown\ glyph:\ "$glyphname
}
-fi
e[^-1] "Draw glyph "$glyphname" with $2 plots in $3 columns & $4 rows with a $5° rotation."
-name. glyphplot
-crop[glyphplot] -1,{w#-1-1},1 # Close loop: duplicate first plot to last
-shift[glyphplot] -1,0,0,0,2
-steprepeat[canvas] [glyphplot],$stpx,$stpy,$rot
-remove[glyphplot]
}
# -----------------------------------------------------------------
# Spectral generators. Post: gtutor_specplot to convert to path
# image. Plots the path made by the tip of the last spinner on a
# chain given to gtutor_mkspectral as an argument. Path is in an
# origin-centered, ±unit square, 2 units on a side, each
# straddling the x or y axes.
_glyph_atomicage : -check isint($1) -gtutor_mkspectral $1,{1/3},0,1,{2/5},0,10,{1/5},0,-20
_glyph_bowtie : -check isint($1) -gtutor_mkspectral $1,{1/4},0,1,{1/4},0,2,{1/4},0,-4
_glyph_circle : -check isint($1) -gtutor_mkspectral $1,{2/3},0,1
_glyph_eightpetal : -check isint($1) -gtutor_mkspectral $1,{1/3},0,1,{1/3},0,-8
_glyph_eightrose : -check isint($1) -gtutor_mkspectral $1,{1/3},0,1,{1/3},0,8
_glyph_ellipseh : -check isint($1) -gtutor_mkspectral $1,{1/4},90,1,{1/2},180,-2
_glyph_ellipsev : -check isint($1) -gtutor_mkspectral $1,{1/4},0,1,{1/2},180,-2
_glyph_filigree : -check isint($1) -gtutor_mkspectral $1,{1/4},0,1,{1/4},0,3,{1/4},0,-13
_glyph_fivepetal : -check isint($1) -gtutor_mkspectral $1,{1/3},0,1,{1/3},0,-5
_glyph_fiverose : -check isint($1) -gtutor_mkspectral $1,{1/3},0,1,{1/3},0,5
_glyph_fourpetal : -check isint($1) -gtutor_mkspectral $1,{1/3},0,1,{1/3},0,-4
_glyph_fourrose : -check isint($1) -gtutor_mkspectral $1,{1/3},0,1,{1/3},0,4
_glyph_knot328 : -check isint($1) -gtutor_mkspectral $1,{1/4},0,1,{1/5},0,2,{1/4},0,-8
_glyph_knot3210 : -check isint($1) -gtutor_mkspectral $1,{1/4},0,1,{1/5},0,2,{1/4},0,-10
_glyph_ninepetal : -check isint($1) -gtutor_mkspectral $1,{1/3},0,1,{1/3},0,-9
_glyph_ninerose : -check isint($1) -gtutor_mkspectral $1,{1/3},0,1,{1/3},0,9
_glyph_palmette : -check isint($1) -gtutor_mkspectral $1,{1/4},90,1,{1/4},0,15,{1/4},0,1
_glyph_sevenpetal : -check isint($1) -gtutor_mkspectral $1,{1/3},0,1,{1/3},0,-7
_glyph_sevenrose : -check isint($1) -gtutor_mkspectral $1,{1/3},0,1,{1/3},0,7
_glyph_sixpetal : -check isint($1) -gtutor_mkspectral $1,{1/3},0,1,{1/3},0,-6
_glyph_sixrose : -check isint($1) -gtutor_mkspectral $1,{1/3},0,1,{1/3},0,6
_glyph_spiralrose : -check isint($1) -gtutor_mkspectral $1,{1/4},0,1,{sqrt(2)/4},-135,-6,{sqrt(2)/4},-90,3
_glyph_tenpetal : -check isint($1) -gtutor_mkspectral $1,{1/3},0,1,{1/3},0,-10
_glyph_tenrose : -check isint($1) -gtutor_mkspectral $1,{1/3},0,1,{1/3},0,10
_glyph_threepetal : -check isint($1) -gtutor_mkspectral $1,{1/3},0,1,{1/3},0,-3
_glyph_threerose : -check isint($1) -gtutor_mkspectral $1,{1/3},0,1,{1/3},0,3
_glyph_trispiral : -check isint($1) -gtutor_mkspectral $1,{1/4},0,1,{sqrt(2)/4},-135,-18,{sqrt(2)/4},-90,9
# -----------------------------------------------------------------
_glyphnames :
-status atomicage,bowtie,circle,eightpetal,eightrose,ellipseh,ellipsev,filigree,fivepetal,fiverose,fourpetal,fourrose,knot328,ninepetal,ninerose,palmette,sevenpetal,sevenrose,sixpetal,sixrose,spiralrose,tenpetal,tenrose,threepetal,threerose,trispiral
# -----------------------------------------------------------------
steprepeat: check ${"is_image_arg $1"}" && "\
isint(${2=1})" && "\
${2}>=0" && "\
isint(${3=1})" && "\
${3}>=0" && "\
isint(${3=1})" && "\
${4}>=0
sx,sy,srot=${2-4}
e[^-1] "Step and repeat given path $1 on image$? $2 times across and $3 times down."
-pass$1 0 # path plots
-foreach[^-1] {
nm={n}
-name. stepcanvas
w,h:=w#$stepcanvas,h#$stepcanvas # stepcanvas dimensions
dx:=round($w/$sx,1,-1) # across step length in image pels, nearest lower whole pel.
dy:=round($h/$sy,1,-1) # down step length in image pels, nearest lower whole pel.
s:=min($dx,$dy) # minimum across or down step lengths. This: square's side.
mx:=($w-$s*$sx)/2 # across margin
my:=($h-$s*$sy)/2 # down margin
pass. 0 # path plotted in the origin-centered ±unit square
-name. glyphplot
-input (-0.99,-0.99^-0.99,0.99^0.99,0.99^0.99,-0.99^-0.99,-0.99)
-name. boxplot
-permute[boxplot] cyzx
# Set up initial transform from ± unit square to bounding box
-moveglyph[glyphplot,boxplot] {$s/2},{-$s/2},{$mx+$s/2},{$my+$s/2},$srot
-repeat {$sy} {
row=$>
-repeat {$sx} {
-curve[stepcanvas] [glyphplot],5,0,0,1,1,255,200,0,255
-curve[stepcanvas] [boxplot],5,0,0,1,1,0,200,255,64
-moveglyph[glyphplot,boxplot] 1,1,$s,0
}
-if $row<$sy
-moveglyph[glyphplot,boxplot] 1,1,{-$sx*$s},$s
-fi
}
-keep[stepcanvas]
-name[stepcanvas] $nm
}
remove.
# -----------------------------------------------------------------
#@cli moveglyph : _tsx,_tsy,_ttx,_tty,_rot
#@cli : Compose an affine transformation matrix & apply to
#@cli : the selected path image. Defaults to an identity matrix.
moveglyph : skip ${1=1},${2=1},${3=0},${4=0},${5=0}
e[^-1] "Transform of the day: Scale: $1,$2; Translate: $3,$4; Rotate: $5"
sx,sy,tx,ty,r=${1-5}
foreach {
nm={n}
-name. plots
-fill[plots] ">
begin(
M=eye(3);
M[0]=$sx;
M[2]=$tx;
M[4]=$sy;
M[5]=$ty;
$r>0?M=mul(M,rot([0,0,1],$r°),3)
);
(M*[I(x,y),1])[0,2]
"
-name[plots] $nm
}
# -----------------------------------------------------------------
camtrak:
foreach {
name. canvas
bbs:=min(w#$canvas,h#$canvas)
steps=200
# Make glyph
-gtutor_mkspectral {$steps},0.7,0,1,0.3,0,-4
-name. glyph
-gtutor_specplot[glyph]
# Make path
-gtutor_mkspectral {0.375*$steps},0.9,0,1,0.1,0,-3
-name. track
-gtutor_specplot[track]
# Scale and translate glyph and track into position
-moveglyph[track] {0.4*$bbs},{-0.4*$bbs},{0.4375*w#$canvas},{0.4375*h#$canvas}
-moveglyph[glyph] {0.1*$bbs},{-0.1*$bbs},{I(#$track,0,0)}
# Make (Δx,Δy) displacements to step glyph along track
+shift[track] -1,0,0,0,2
-sub[-1] [-2]
-crop. 1,100%
-name. tangents
# Step and repeat
-repeat {w#$tangents} {
-curve[canvas] [glyph],5,30,50%,0,1,255,64,200
dx,dy:=I(#$tangents,$>+1,0)
-moveglyph[glyph] 1,1,$dx,$dy
}
}
Well, i do enjoy the Garypedia articles and usually await them like the rich sods waitng in line for the new iphone. But even I have stuff to do every now and then
That FNM song isn’t even one i really like, it’s rather cheesy. Try this one instead
Note that i never listen willingly to the radio. I’ve been buying cds for 33-34 years now, at this point i could start my own radio. But anyway i’m not against 80’s music, and it’s easy to find on the radio, i think half of what i hear (see? i didn’t say listen) in the car is quite old indeed.
But the math amputee that i am can sill solve this :
Good music + good recording + good production = Eternal enjoyment
I was learning tricks about 90° rotations and looking to adapt them to G’mic since i can’t use negative numbers without leaving the canvas:
gmic run '1000,1000,1,3,0 repeat 100 sx:=$> sy:=$>%($<+1) repeat 4 circle. $sx%,$sy%,.5%,1,255,0,0 tmpx,tmpy=$sx,$sy sx:=100-$sy sy=$tmpx line. $tmpx%,$tmpy%,$sx%,$sy%,1,255 done w. wait 50 done d'
I see. So with plot points being added each pass it would take more and more time to process, hence the weird tic toc
results.
Thanks for the update, i’ll go test break it now.
Hello, I have a new question to get out of my head… For the sake of learning a bit of math parser syntax… I’ve been roaming the forum and tutorials but I only see syntax for fill.
How do I iterate over pixels in a (binary or grayscale containing just edges or an outlined shape) image to check their values ( i ) and get their positions? I know their are predefined vars like i, x ,y etc, but I can’t seem to figure out how to write what I want to do. I just want to draw a line going outward to image border were i>0. Just for fun.