@grosgood Awesome, that could be a good G’MIC demo.
Examine ribbons
; these set up splinefun
argument lists. The set up entails defining how many curves comprise the image (ccnt
) the size of an image upon which to draw curves (canvas
) and the succession of colors through which curves progress as they are drawn first-to-last (palette
).
splinefun
’s argument list:
splinefun[canvas] [palette],curve_plot_count,complexity_level,thickness,pen_width,pen_angle,opacity
- Controlling Color
[palette]
is an
×1
×1
×3
RGB “row vector” image, n×1 , which establishes (1) how many curves comprise the image (n
), and (2) the sequence of colors they assume. As an aside, this overloaded argument is not user friendly, embodying as it does two distinct pieces of information: curve count and how curves are to be colored. You could make a decent case for separating these data into distinct arguments.- In light of the previous point, perhaps
1400,1400,1,3,0 +fc 55,128,128
is an unanticipated approach to setting uppalette
, for the second image on the list, thepalette
, is1440
×1440
, three channels, and all pixels have the same color: R=55, G=128, B=128, a darkish, desaturated cyan. The mono-colored curves might not be that interesting. The anticipated palette generating approaches are:
** Mapping and sizing black-to-white ramps:
$ gmic run 'curve_count=128 -input $curve_count,1,1,1,255*x/(w-1) map. haline' …
Consult gmic -help map
for a list of palette names, from which haline
is drawn.
** Stretching a few color samples
$ gmic run 'curve_count=240 -input (0,70,255^70,215,250^255,170,170) -name. palette -resize[palette] $curve_count,{h},{d},{s},3'
$ gmic run 'curve_count=240 -input (0,70,255^70,215,170^255,250,170) -permute cyzx -name. palette -resize[palette] $curve_count,{h},{d},{s},3'
This approach was used in the various ribbon
exercises. Both pipelines, above, are equivalent; both stretch tiny 3×1×1×3 images into 240,1,1,3 palettes. The second pays a tiny performance price (permute cyzx
) so that data may be conveniently written as (RGB^RGB^RGB) in the initial palette specification. Prior to a resize stretch, permute cyzx
rotates the image’s pixmap to (RRR,GGG,BBB)
.
Here is another variant that harnesses @Reptorian 's pal
palette command. That command provides a library of named palettes drawn from a variety of sources. There are more than 370 distinct palettes.
$ gmic run 'curve_count=1024 +pal clouds_sunset -name. palette -resize[palette] $curve_count,{h},{d},{s},3'
Consult gmic -help pal
for the current list.
** Palettes from arbitrary sequences of Internet Color Names
Let inetnames.gmic
be:
inetnames:
$=cnames
-repeat $# {
cn=${cnames{$>+1}}
-input (${"-name2color "$cn})
}
-append c
-permute. cyzx
Then:
$ gmic run '-command inetnames.gmic color_count=256 inetnames "citron","alice_blue","french_raspberry","lapis_lazuli" -resize. $color_count,{h},{d},{s},5' -name. palette -normalize[palette] 0,255
produces a cubic blended, 256 element palette from four well known names for internet colors. See X11 color names for some of the more commonly used internet colors; G’MIC’s list is a superset of that.
I am sure there are other ways to set up palettes; this gives you some approaches.
- Controlling Geometry
This being a toy, I wasn’t that keen on furnishing easy means to manage curve geometry, content to have random processes (u()
) surprise me. That said, if you are earnest about explicitly specifying geometry, first give Post 18 another read, for you will need to intervene in the script and rewrite a portion of it. Pay particular mind tosplinefun's
two-stage plotting workflow, and, specifically, the first stage: the creation of a “plotting data set” —plotcoords
. When complete, the columns of this two-channel image furnish (x,y) plotting data, one column of data for each curve. The width of this two channel image specifies the number of curves.
For the prototype of this data set, the script first chooses a randomly selected number ($lvls
⇒ complexity_level
) of four channel pixels; these constitute explicit sample pixels along the lines of those comprising the data set image, serving the rôles of sheet metal “rivets”, or “coordinates”, or “keyspoints”… see the prologue, Post #18. The script then asks G’MIC’s rbf
(“radial basis function”) command to estimate all the remaining pixels of the $crvcnt
× $res
(curve_count
× curve_plot_count
) sized data set image, given the keypoints and the thin plate spline radial basis function, the estimator for unspecified pixels.
The second stage is more prosaic than the first: a straightforward column-by-column iteration over plotcoords
, plotting each column as a curve on canvas.
At the outset, the curve coordinates reference a generic (x,y) \in [-1 \dots 1] \times [-1 \dots 1] plotting space; For each column of curve data taken from plotcoords
, the script maps these generic coordinates into canvas
pixel coordinates through an affine homogeneous transform.
Of note here is that the plotting set for one curve is initially incomplete, accommodating only one edge of the convex hull comprising a complete stroke. To complete the stroke, the script (1) duplicates, (2) reverses, and (3) offsets the data set, using pen_width
and pen_angle
to set the magnitude and direction of the offset. This action makes up the second, “return edge,” of the convex hull. The script concatenates the offset data to the original, establishing the complete convex hull. The script passes the entire data set in one call to the math expression function polygon(),
which also acquires an RGB pixel from the stretched palette
image and the opacity from the final argument to splinefun
So, for select plots of select curves, you specify coordinates where that plot point must be: you “peg” the curve at a specific location.
For that end, this is the portion of the splinefun.gmic
where you intervene. At line 97, replace:
97 : -input $lvl,1,1,4,[u($crvcnt),u($res),u(-1,1),u(-1,1)]
with something like:
-input (\
0,0,-0.875,-0.9125^\
16,250,-0.5,0.75^\
63,32,-0.75,-0.375^\
80,255,1.0,1.0^\
127,153,0.4,0.675^\
193,250,0.875,-0.9375^\
255,240,0.5,0.875\
)
These are explicit sample pixels from which rbf
interpolates. The pixels have four channels:
channel 0: selects a curve n, an index between [0,…,curve_count–1]
channel 1: selects a (x_k,y_k), the kth plot point from curve n, an index between [0,…,curve_plot_count–1]
channel 2: and
channel 3: specifies the (x,y), generic coordinate pair that pegs the location of the kth plot point of curve n
For example, the seventh, and final peg point in this list pegs curve 255, its 240th plot point, at the generic coordinate (0.5,0.875). You — autocrat that you are — declare that the 240th plot point of curve 255 must pass through location (0.5,0.875). rbf
figures out the twists and turns to make that so.
You may write as many peg points as you please. Here is the image formed by this data set:
Have fun!
I think I am now thinking prawnsushi is overwhelmed. Hopefully not. I’ll keep my response a slight shorter in a bit.
All is well.
I just wanted a thick spline (as the title says) with OK transparency that i could use to draw stuff Calispline was cool though. If i have to draw everything on a separate layer to have working alpha transparency, so be it! Maybe the performance will not suffer that much… What will it be: Grindcore or Funeral Doom? But I have other stuff to finish first, or everything will just slowly rot away.
BTW I don’t have the memory chips, only 8 GB so rendering large is kinda hard, laptop crashes often ( see paper cuts in GMiC-qt).
I tried to read the Arabesque tutorial (had a 3h train ride) but again this is a bit too complex (and the page was bugged on my phone lines were going out of the screen for 10km: not fun ).
I’m not that advanced so I don’t think i’ll be able to use this any time soon but thanks for the time and explanations. I like to read anyway.
I just got back to work today, and for some reason tonight everyone is replying to me at the same time. That’s a lot of things to process indeed. But all is well!