Heya, I showed those color filling gifs to my dad and he was wondering what your algorithm for which color goes next was? (How does it decide to go pink instead of going purple etc.)
The original algorithm was really janky and consisted of incrementing different modes, where each mode was hardcoded to either increase or decrease the RGB values by one until the RGB value matched the target colour. Once the target was reached the next mode would be set.
The algorithm I'm currently using randomly chooses from a list of colours and then only increments one RGB value per iteration for a more gradual colour transition.
The tool I'm using is gifski, which works on the idea that gifs can reuse colours from previous frames (so long as they don't change position) to achieve any number of colours per frame.
Code snippets and gifs under the cut!
A really easy (rainbow!) colour gradient is Red > Yellow > Green > Cyan > Blue > Purple > Red
In Python (with the mode idea) it'd look something like:
Notice that the final `elif` statement sets the mode back to 0 so the process can repeat.
The issue with this idea is that extending it to more colours is really tedious (ask me how I know) and you don't get the best transitions.
For example, a transition from black (#000000) to white (#ffffff) would happen in 256 steps (#000000 > #010101 > #020202 > ...) which just isn't gradual enough. A better transition would only change one of R, G, and B at a time (#000000 > #010000 > #010100 > ...). We can implement that with a counter (`f`) and a modulo (`%`)!
The updated version is:
(Don't look too hard; I wrote this while sleep deprived. )
Where `ln` and `l` is how many times longer than tall the drawn pixel should be
`c` is just what character I'm on (the curve is constructed using an L-system)
`dw` and `dh` are the actual width and height of a pixel
`cR`, `cG`, and `cB` are how much the RGB values should change (0 or 1, unless you want an even more gradual or even more extreme transition)
`x` and `y` are where to put the pixel
`fx` and `fy` just set the next position (-1, 0, or 1)
`f` is a counter
`s` is how big a sample should be, that is, how many pixels we change per frame
`loops` is how many times the entire image should be filled (1 loop will draw the image and then erase itself; 2 loops will draw the image, draw over itself again, and then erase itself)
`o` is the order of the curve
The goal here is to pick a random colour from a list of colours (colours = [(25, 25, 25), (255, 255, 255), (255,0,0), (0,255,0), (0,0,255), (255,255,0), (255,0,255), (0,255,255), (255,127,127), (127,255,127), (127,127,255), (255,255,127), (255,127,255), (127,255,255)]) and then alternate (using `f%...`) which of `R`, `G`, and `B` you increment until you hit that colour.
Now let's have some fun!
colours = [(25, 25, 25), (255, 255, 255), (255,0,0), (255, 127, 127)]
dw = 4
dh = 4
l = 1
s = 5
o = 5
loops = 2
colours = [(25, 25, 25), (255, 255, 255), (255,0,0), (255, 127, 127)]
dw = 4
dh = 4
l = 2
s = 5
o = 5
loops = 2
colours = [(255, 0, 0), (0, 255, 0), (0, 0, 255)]
dw = 4
dh = 3
l = 2
s = 5
o = 5
loops = 2
This .gif has 450,537 different colours! A far cry from the 256 we typically see
Oh, one final thing: I'm using Numpy to create the image and OpenCV to write to a .mp4. Then I have a script that uses ffmpeg to pipe the frames to gifski. Sounds convoluted, but it's much faster than saving each frame by itself and then combining them later.
There is some neat tree-generation work in Charlie Hewitt’s recent dissertation. It starts with L-System and parametric approaches, and adds improvements.
The results look quite convincing as trees, plus seem to be nicely controllable. Oh, and the whole thing runs in Blender.