Tech
Ågren Dag
Jul 1, 2019
How we came to create a new image placeholder algorithm, BlurHash
BlurHash is a compact representation of a placeholder for an image. Read on as our iOS Engineer Dag Ågren tells the story of how we came to create it!
Here’s the problem: You have designed and implemented a beautiful new way to browse your content, full of colourful images that really catch the eye. It is a beautiful, perfect gem. But you’ve been testing it on your nice and fast internet connection. As soon as you try to show it to your designer on your phone the internet hiccups and you are stuck staring at a page of bland, grey and empty boxes, with bits of text forlornly scattered around. Your designer starts crying at what you did with all his hard work.
“I could not let go of this, though, and could not shake the feeling that there should exist a good solution to this dilemma.”
Not a big problem, you think, recalling that some people have dealt with this problem by taking highly compressed, tiny thumbnails of their images, including them in their server data, scaling them up and blurring them to use as placeholders. You only need to add maybe a few hundred bytes of data for each one if you use every trick in the book! You tell your database engineer about this plan, and now he is crying because you want to stuff all this binary gunk into his beautifully designed and optimised database schema.
I may exaggerate slightly, but this is essentially what happened to me at my first project at Wolt. It was our new Discover tab, which was to be the new face of our application from there onwards. I had to admit that everyone involved had good points, and I had no solution that pleased everyone. I could not let go of this, though, and could not shake the feeling that there should exist a good solution to this dilemma.
“This turned out to be a good guess, and with a few tweaks I eventually got something that looked good. I spent about two days on this initial implementation.”
So once the project was otherwise ready for release I sat down to do some experiments with a few ideas I had. I figured all that was needed for a good-looking placeholder is a handful of colours, if presented in a pleasing way. One option would be to just encode a small number of pixels and scale them up smoothly. The second step can be tricky to get right, though.
So what I decided to try was, in a sense, to combine the data representation with the presentation by using a DCT (Discrete Cosine Transform), the same representation used internally by formats like JPEG. It is both good for lossily compressing data, a big plus for this project, and the cosine functions it uses turns out to produce some pleasantly smooth gradients in the resulting image. This turned out to be a good guess, and with a few tweaks I eventually got something that looked good. I spent about two days on this initial implementation. (If you are curious about all the technical details, check out the repo at GitHub, which contains much more detailed explanations!)
The DCT scheme combined with a custom encoding to ASCII characters that are easy to store in any database or server response, was enough to create aesthetically pleasing images using only 20-30 characters of text, an amount small enough to make everybody happy. It was quickly rolled out into the backend code and all of our different client applications now use these hashes while waiting for the real images to load. This was helped by the fact that the code for the algorithm ended up being quite simple, short, and could easily be ported to new languages.
It’s been tweaked and improved a few times since and we now finally had the time to put it together into an actual open-source project! So:
You can play around with it yourself and see how it looks at our demo site: blurha.sh
You can grab the source code in various languages at the official repo: github.com/woltapp/blurhash
And we are of course hiring: wolt.com/jobs
If you’re a programmer we’d love to see you use this in your own projects! We’d also love to see it ported to new programming languages, or used in new and creative ways. The code is very short and simple, so feel free to play around with it. If you have a good improvement you want to include in the official project, feel free to file a PR. Or just publish your own. We hope you star the repo and enjoy it!