ident
A Go library for rendering identicons from 32-bit integers.
Rationale and overview
Computers are great at comparing long strings of digits for equality. Humans? Not so much. Anyone who has tried to compare hash codes by hand knows how easy it is to accidentally transpose two digits in your head or mistake a 5
for an 8
.
Identicons help out us humans by providing visual "fingerprints" for small pieces of data, such as numbers, checksums, or hashes. Typically an identicon is composed of a handful of primitive shapes arranged in a grid. A good identicon algorithm will generate a different image for each unique input, which allows a person to quickly determine whether two values are in fact equal.
The algorithm
(In the interest of simplicity, this explanation avoids talking about rotation techniques applied in the code so that even small numbers have "interesting" identicons.)
This library produces 8x8 identicons for a given 32-bit unsigned integer. Every identicon has horizontal symmetry, which both looks aesthetically pleasing and avoids creating embarrassing shapes like swastikas.
The great thing about 32-bit integers is that they're small and there's more than four billion of them to choose from. They're also widely available:
- Checksums like CRC-32 can take arbitrary data and spit out a 32-bit integer.
- IP (v4) addresses are just 32-bit integers with glasses and a fake mustache.
- 64-bit integers are two 32-bit integers cozied up to one another. Buy one 32-bit integer, get the second free!
To build the image, we divide the integer into eight four-bit blocks. The three least significant bits of each block are used to pick from a list of eight 2x2 patterns. The most significant bits of each block are combined to form the red, green, and blue components of the icon's color.
For the number 0x89234def
, we get the following:
red 01
│└─────────────┐
green 110 │ │
││└────────────┼─────────┐ │
blue 101 │└────────┐ │ │ │
││└──┼─────────┼────┼────┐ │ │
│└───┼────┐ │ │ │ │ │
│ │ │ │ │ │ │ │
bits 1000 1001 0010 1011 0100 1101 0110 1111
─┬─ ─┬─ ─┬─ ─┬─ ─┬─ ─┬─ ─┬─ ─┬─
│ │ │ │ │ │ │ │
──┴─ │ │ │ │ │ │ ──┴─
block0 ██░░ │ │ │ │ │ │ ░░██ block7
░░██ │ │ │ │ │ │ ██░░
──┴─ │ │ │ │ ──┴─
block1 ██░░ │ │ │ │ ░░██ block6
██░░ │ │ │ │ ░░██
──┴─ │ │ ──┴─
block2 ████ │ │ ████ block5
░░██ │ │ ██░░
──┴─ ──┴─
block3 ░░██ ██░░ block4
████ ████
The foreground and background colors are created by multiplying the red, green, and blue values by some number to bring them into a reasonable range and ensure that close values do not produce indistinguishable colors. Currently the background color is merely a darker shade of the foreground color. Other color-selection strategies may be explored in the future.
The eight pattern blocks selected by the three-bit pattern sequences are assigned to the left half of the image in left-to-right, top-to-bottom order. For the right half of the image, we mirror the patterns on the left. (The mapping of numbers to patterns is done so that taking the complement of the three-bit number yields the mirrored pattern.) For the above number, this gives us the following identicon, which can be scaled up or down as needed to produce an identicon of the desired size:
██░░██░░░░██░░██
░░████░░░░████░░
████░░████░░████
░░████████████░░
██░░████████░░██
██████░░░░██████
░░██░░████░░██░░
░░████░░░░████░░
Prior art and other implementations
- Sigil: Also written in Go; generates 5x5 identicons from an MD5 hash.
- Pydenticon: Sigil ported to Python.
- NIdenticon: .NET library with multiple size, color, and shape options, oh my!
Documentation
Installation
go get -u gitlab.com/eightsquared/ident
License
MIT