I created a little web page (<10kB) that generates a random 4K (3840*2160px) wallpaper image using Javascript and the <canvas> element. Right-click to save the image (desktop only for now).
No two images are the same. You may need a few refreshes to get an interesting result.
Ideas for optimization:
- use some kind of seed from a URL, so that people can share them.
- How about multi-monitor setups?
The multi-monitor setup is something I struggled a bit. My two monitors are stacked vertically. So I use SVG images, render them in 2x4k height + 80px or so and cut the relevant parts out.
The width and height can be changed in the code. If you also increase the number of layers (vertical) and line segments (horizontal) accordingly, you should be able to get similar results at different resolutions/aspects.
I would also second the idea of putting the seed in the URL, even with just an anchor link so that all processing is done in the browser. So if someone visits https://tanck.nl/wallpaper/#12345, use this number as the seed. You could also add a link under the image.
edit: here's a hacky way to do it, since you can't seed Math.random() in JavaScript; add this at the start of the "draw()" function.
const url = new URL(location.href);
const match = /#([0-9]+)$/.exec(url.hash);
if (match) {
var seed = parseInt(match[1]);
Math.random = function() {
var x = Math.sin(seed++) * 10000;
return x - Math.floor(x);
};
}
Based on a StackOverflow answer to the commonly-asked question of how to seed the PRNG in JavaScript, by all means not a perfect solution but appropriately concise for this short script: https://stackoverflow.com/a/19303725
I've done something similar in another project (avatar generator based on username). That code would always use a seed, and generate a new one when none was supplied.
The main issue I see is that all the non-random numbers in the code would need to remain fixed. I love tweaking those to improve the results. The link you'd share would have to be something like /v1/hash, where 'v1' is a folder with the 'frozen' version of the algorithm.
I also think the results would be less random/erratic, and since the images this generates are only around 150 kilobytes, they are also easy to share :).
I see you've added a sharing feature! Thanks for this.
It really says something about the elegance of the image generation algorithm when the sharing code is about as long as the code to generate images. I was surprised when I first saw this draw() function, only a few lines long. Great job!
Though one question popped up in my mind while looking at this... Given the trend of ever increasing screen resolutions with no end in sight, why don't OSes support using vector images (svg, etc) as wallpapers?
Your claim that no operating systems support this seems extremely unlikely. I’m pretty much certain there are multiple Linux desktop environments that support vector based background images.
Well, I had assumed none had support since none of the OSes I use regularly had support. I stand corrected.
That said, I do still wonder why none of the OSes that I use (Windows, MacOS, Android, iOS, accounting for pretty much 100% of the OSes regular people use) have support for it.
My current desktop has an SVG as the wallpaper for my main display and a webp on the second one. I guess I could switch them over to a png or something, but I'm too lazy and I haven't noticed any issues with it.
Love the minimalist execution. Personally, I consider your tool having no user-facing options a plus (less decision making for me and excitement from complete randomness). I just set one of the wallpapers as my desktop background. Thank you
On Safari (macOS) it is as impossible to download this easy-to-download-picture as it is possible to download the impossible-to-download-picture[1] from yesterday.
If you can't get the download to work, but are still interested in something similar, @victorgama put together what appears to be a pretty neat macOS implementation. It runs the algorithm on the desktop and automagically refreshes the wallpaper on startup, etc (unfortunately I don't know swift or have a mac, so this is just based on the readme).
Nice! Feature suggestion: an (optional) colour picker would be a nice touch, so you can pick (or perhaps enter #RGB) one that should appear and the others are then a fitting palette. Occurred to me because I was refreshing through a few, liked the colours on one, but not so much the pattern. (Perhaps alternative implementation would be a 'hold colour palette' or 'hold pattern' toggles, so only the other varies.)
Thank you. Those are great suggestions, but I also like the simplicity of it being completely random. Perhaps I'll do an interactive wallpaper designer at some point, where you're more in control.
I do like the simplicity of completely random, but my first instinct was definitely to want some sliders or toggles. Personally prefer desktops to be extremely dark, and many of them were nice, but way too bright on a section. User control would definitely end up with a different experience, and totally respect the simplicity.
Might end up tweaking it to my tastes and a few other resolutions, like for my ultra wide.
A fun alternative would be to run this on the desktop and generate a new wallpaper every time your computer starts up (This is not a feature request, though -- you've had plenty of those here already, and since you've helpfully released the code under GPL, I'm sure anyone interested could easily do this conversion on their own end).
This is just brilliant. I’ve been looking for ways to generate spanning wallpapers for two 4k screens, or two 4k’s + a laptop screen. Looks like this could be adapted for that.
Unfortunately, no. There seems to be some issue with saving canvas elements as PNG on mobile browsers. Since the generated images are landscape aspect anyway, I didn't spend a lot of time figuring out exactly what's causing this.
My bad. Seems that a number of browsers block saving canvas elements as a security precaution. For now, I can only recommend trying a different browser as a workaround.
Completely random. It picks a hue value (0-360) and then adds or subtracts a second random value from this for each layer. The maximum value of this increment is relatively small, so the colors are usually similar within the same image.
The colour schemes and limited amount of colours reminds me of the old VUE and CDE backgrounds :)
And that reminds me of xfishtank. I still use that sometimes for old school cool and also because it is pretty optimized (when it was written many X terminals shared a 10mbit coax) and great way to see if a remote X desktop session is still responsive.
My favourite part of this is that the wallpapers will look super sharp on my 4k display. It's quite difficult to find wallpapers that don't look blurry when blown up, even quality landscape photography. Very neat! Thanks for sharing :)
This unfortunately, is a known issue. I tried adding a download button, but that also only worked on desktop. Probably some browser policy thing. The same is true for Android (Chrome and Firefox Nightly).
You can convert the canvas to a Blob with HTMLCanvasElement.toBlob(), then create a blob URL from that with URL.createObjectURL(). You can then replace the canvas with an <img src="blob://...">, which can be long press saved; add a download button linking to that blob URL; or whatever. Works on all non-ancient mobile browsers I've tested.
Do note that Firefox’s privacy.resistFingerprinting can block you from reading canvas image data, giving you garbage instead, and the permission prompt is basically unnoticeable if the user isn’t actively looking for it.
Thank you. I tried to implement this, but I got empty/missing images on mobile browsers. It basically worked everywhere where right-clicking also worked. I'll look into it more when I have more time.
No two images are the same. You may need a few refreshes to get an interesting result.
Code: https://github.com/roytanck/wallpaper-generator