pretty voronoi diagrams
Here is an image to peak your interest:
Looks nice, does it not? I am super happy with how it turned out. These images are basically voronoi diagrams. Given a couple points on the image, it visualizes what pixels are closest to what points. Every point gets a color, and every pixel takes the color of the closest point. To make it look better I made pixels go darker if they are close to two points. I fiddled a lot with various parameters and calculations until I arrived here. My first images looked pretty much like a standard voronoi diagram:
Then I added some gloom. The further a pixel is away from its closest point, the darker the pixel gets:
And then some more:
Now it looks like bubbles. Pretty! It is a bit dark, so let me make it brighter:
Ooopsie. Happy little bugs! Looks cool but it is not what I aimed for. The issue here is, that I am working with unsinged 32bit integers, but the image stores the colors as unsigned 8bit integers. To convert them, I do some math to bring the values into the 8bit range, then I trim off the higher bits. If the value is just a little too large, say 260, and I convert it to 8 bits then it is now just 4. That is a huge difference for a 8bit value, which is why there is a sudden change in color. To be on the safe side, I make them darker than they have to be. Only In some cases, this is necessary however. In most cases it just makes the image look dark. And unless you try to make this bug happen like I did here it does not come up all that often. To fix this, any value over 255 is set to 255. Then we can safely convert the 32bit number to an 8bit number. Next I decided to remove the fade-to-black parts and just blend the colors of the two closest points together:
That looks nice but not very stunning. Now that I have the closest two points, I can make the pixels closer to the middle between the two points darker.
Looks likes gems now. However, the image has too many black parts. To solve this, let me explain how I calculate the brightness of the pixels. First, this is the information available:
color
is the color of the closest pointmiddle
is how far the pixel is away from the center between the two closest pointsbrightness
changes how bright the colors lookfade
changes the behavior of fade to black
The brightness of a color component (the r, g, or b value in rgb) is calculated like this:
color * (middle ^ fade) / (brightness ^ fade)
The color of the pixel is multiplied by the distance to the center. Now
all the colors are way to bright and definitly do not fit into 32bits
anymore. In order to make them fit again, they are divided by the
expected distance. The average of the width and height are right in most
cases and does not make the image darker than it needs to be. That is
what the brightness
parameter does. If we look only at one voronoi
cell (one polygon/shape in the picture) all of these variables are
constant, except for middle
. That means we have a function of order
fade
. I have only tried values greater than or equal to 1. What
happens when fade is set to 0.2? The function looks like this:
And generates images that look like this:
We have arrived at the very pretty images. yay. Hey, remember the u8 conversion bug? This is what it looks like here:
This generator is written with rust, using the image crate. For my next project I will try the processing crate. The source is freely available and currently hosted at
https://git.sr.ht/~digital/digital-dreams/tree/master/voronoi.You might have noticed that the images change everytime you reload the website. That's right, I put the image generator behind a webserver and now you can get freshly generated pictures right in your browser, without installing anything! I encourage you to click at the images, look at the urls and play around with it. There are limitations to what requests the webserver will fulfill. Large images with lots of cells can take a couple multiple minutes to finish. For more control, better fine tuning, or higher quality you will need to run it locally on your device. Here is a list of possible arguments for the webserver:
name | default | what does it do |
---|---|---|
size_x | 512 | width in pixels |
size_y | size_x | height in pixels |
bubbles | 5 | the number of bubbles/cells |
fade | 0.1 | how fast colors fade to black |
mix | 2 | how to calculate the colors, one of 0, 1 or 2 |
brightness | size_x + size_y / 2.0 | how bright the colors are |
u8_bug | false | whether 32bit to u8bit conversion is buggy |
And here are some short links to common formats:
Please don't notice the white dots
Oh no you probably have, haven't you? I, uhm, I do not know why but there are sometimes white dots in the black regions. I spend some time trying to figure this out but have not been successful so far. And I want to move on to new things. Which is why there is no animation and only 8 bits per channel per pixel. Maybe I will come back and rewrite this. Before I do that, I have some more ideas for other art pieces I want to try out and processing looks really interesting.