Generating Noise Textures

Published:

My current play-with-random-web-tech side-project is is a solitaire game. Well actually it's a framework for implementing solitaire games because I'm a programmer and a side project is the right place to exercise my desires for needless abstraction. I want a nice felt-looking background texture and the way to do that is you add some noise to an image. Adding some subtle noise to an image is a really common approach to achieving a nice visual aesthetic - as I understand it - I mentioned I'm a programmer.

My project ships as a single HTML file. I'm developing it with in TypeScript with LESS styling but then I can bundle it all up as a single file to scp to a server. I'm not using any external images - Unicode includes plenty of handy symbols and the only other one I needed (a Mahjong bamboo symbol) was only a tiny snippet of SVG. Including a noise texture as an external image or inline as a data: URI is kind of gross. Noise textures by definition don't compress well.

I was able to build something pretty nice by combining HTML Canvas' raw pixel data access and Web Crypto's getRandomValues(). The window.crypto.getRandomValues() call fills a typed array with random data. Actually it's generated by a PRNG seeded with a little entropy so it's fast and won't waste all your hard earned entropy. Canvas'  createImageData() and putImageData() allow you to work with canvas pixels as typed arrays.

The only catch is that getRandomValues() only fills 64k of data. Canvas image data is 32bpp RGBA so all you can generate trivially (without repeated calls to getRandomValues()) is a 128x128 texture. When I use this subtly I don't notice the repetition.

The completed example is on JSFiddle: https://jsfiddle.net/ianloic/2uzhvg8h/