identicon-0.1.0: Flexible generation of identicons

Copyright© 2016 Mark Karpov
LicenseBSD 3 clause
MaintainerMark Karpov <>
Safe HaskellNone




Core types and definitions for flexible generation of identicons. Please see the Graphics.Identicon.Primitive module for collection of building blocks to code layers of your identicon.

A basic complete example looks like this:

import Codec.Picture
import Data.ByteString (ByteString)
import Data.Proxy
import Data.Word (Word8)
import Graphics.Identicon
import Graphics.Identicon.Primitive

myImageType :: Proxy (Identicon 4 :+ Consumer 4)
myImageType = Proxy

myImpl = Identicon :+ a
    a :: Word8 -> Word8 -> Word8 -> Word8 -> Layer
    a r g b n = rsym $ onGrid 6 6 n $
      circle $ gradientLR (edge . mid) black (PixelRGB8 r g b)

myGenerator :: Int -> Int -> ByteString -> Maybe (Image PixelRGB8)
myGenerator = renderIdenticon myImageType myImpl

myGenerator takes desired width, height, and hash that should have at least 4 bytes in it and returns an identicon corresponding to that hash or Nothing if the hash has less than 4 bytes in it or width or height don't make sense. The identicon has randomly placed circle with gradient filling changing (horizontally) from black to some color and back to black. The circle is mirrored 4 times, and every repetition is rotated by 90°. This identicon consumes 4 bytes and has one layer.


Basic types

data Identicon n Source

Identicon is a type that represents an identicon consisting of zero layers. The type is parametrized over the phantom type n which is a natural number on type level that represents the number of bytes that should be provided to generate this type of identicon. Bytes typically come from some sort of hash that has fixed size.




data Consumer n Source

Consumer is a type that represents an entity that consumes bytes that are available for identicon generation. It's parametrized over the phantom type n which is a natural number on type level that represents the number of bytes that this entity consumes. At this moment, a Consumer always adds one Layer to identicon when attached to it. The number of bytes, specified as type parameter of Identicon type must be completely consumed by a collection of consumers attached to it. To attach a consumer to Identicon, you use the :+ type operator, see below.


data a :+ b infixl 8 Source

The :+ type operator is used to attach Consumers to Identicon, thus adding layers to it and exhausting bytes that are available for identicon generation. An example of identicon that can be generated from 16 byte hash is shown below:

type Icon = Identicon 16 :+ Consumer 5 :+ Consumer 5 :+ Consumer 6

The identicon above has three layers.


a :+ b infixl 8 


newtype Layer Source

Layer is the basic building block of an identicon. It's a function that takes the following arguments (in order):

  • Width of identicon
  • Height of identicon
  • Position on X axis
  • Position on Y axis

…and returns a PixelRGB8 value. In this library, an identicon is generated as “superposition” of several Layers.




unLayer :: Int -> Int -> Int -> Int -> PixelRGB8

type family BytesAvailable a :: Nat Source

The BytesAvailable type function calculates how many bytes available for consumption in a given identicon.

type family BytesConsumed a :: Nat Source

The BytesConsumed type function calculates how many bytes is consumed in a given identicon.

type family Implementation a Source

The Implementation type function returns type of the code which can implement the given identicon.

type family ToLayer n :: k Source

The ToLayer type function calculates type that layer-producing function should have to consume given number of bytes n.


ToLayer 0 = Layer 
ToLayer n = Word8 -> ToLayer (n - 1) 

Identicon rendering

class Renderable a where Source

Identicons that can be rendered as an image implement this class.


render Source


:: Proxy a

A Proxy clarifying identicon type

-> Implementation a

Corresponding implementation

-> Int

Width in pixels

-> Int

Height in pixels

-> ByteString

Bytes to consume

-> (ByteString, Int -> Int -> PixelRGB8)

The rest of bytes and producing function

class ApplyBytes a where Source

Consume bytes from strict ByteString and apply them to a function that takes Word8 until it produces a Layer.


applyWords Source


:: a

Function that produces a layer

-> ByteString

Bytes to consume

-> (ByteString, Layer)

The rest of ByteString and produced Layer

renderIdenticon Source


:: (Renderable a, KnownNat (BytesAvailable a), BytesAvailable a ~ BytesConsumed a) 
=> Proxy a

Type that defines an identicon

-> Implementation a

Implementation that generates layers

-> Int

Width in pixels

-> Int

Height in pixels

-> ByteString

Collection of bytes to use, should be long enough

-> Maybe (Image PixelRGB8)

Rendered identicon, or Nothing if there is not enough bytes

Render an identicon. The function returns Nothing if given ByteString is too short or when width or height is lesser than 1.