Copyright | © 2016 Mark Karpov |
---|---|

License | BSD 3 clause |

Maintainer | Mark Karpov <markkarpov@openmailbox.org> |

Stability | experimental |

Portability | portable |

Safe Haskell | None |

Language | Haskell2010 |

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 where 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.

- data Identicon n = Identicon
- data Consumer n
- data a :+ b = a :+ b
- newtype Layer = Layer {}
- type family BytesAvailable a :: Nat
- type family BytesConsumed a :: Nat
- type family Implementation a
- type family ToLayer n :: k
- class Renderable a where
- render :: Proxy a -> Implementation a -> Int -> Int -> ByteString -> (ByteString, Int -> Int -> PixelRGB8)

- class ApplyBytes a where
- applyWords :: a -> ByteString -> (ByteString, Layer)

- renderIdenticon :: forall a. (Renderable a, KnownNat (BytesAvailable a), BytesAvailable a ~ BytesConsumed a) => Proxy a -> Implementation a -> Int -> Int -> ByteString -> Maybe (Image PixelRGB8)

# Basic types

`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.

`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.

(Renderable a, ApplyBytes (ToLayer * n)) => Renderable ((:+) a (Consumer n)) Source |

The `:+`

type operator is used to attach `Consumer`

s 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 |

(Renderable a, ApplyBytes (ToLayer * n)) => Renderable ((:+) a (Consumer n)) Source |

type family BytesAvailable a :: Nat Source

The `BytesAvailable`

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

BytesAvailable (Identicon n) = n | |

BytesAvailable (x :+ y) = BytesAvailable x |

type family BytesConsumed a :: Nat Source

The `BytesConsumed`

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

BytesConsumed (Identicon n) = 0 | |

BytesConsumed (Consumer n) = n | |

BytesConsumed (x :+ y) = BytesConsumed x + BytesConsumed y |

type family Implementation a Source

The `Implementation`

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

Implementation (Identicon n) = Identicon n | |

Implementation (a :+ Consumer n) = Implementation a :+ ToLayer n |

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`

.

# Identicon rendering

class Renderable a where Source

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

:: Proxy a | A |

-> 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 |

Renderable (Identicon n) Source | |

(Renderable a, ApplyBytes (ToLayer * n)) => Renderable ((:+) a (Consumer n)) Source |

class ApplyBytes a where Source

Consume bytes from strict `ByteString`

and apply them to a function
that takes `Word8`

until it produces a `Layer`

.

:: a | Function that produces a layer |

-> ByteString | Bytes to consume |

-> (ByteString, Layer) | The rest of |

ApplyBytes Layer Source | |

ApplyBytes f => ApplyBytes (Word8 -> f) 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 |

Render an identicon. The function returns `Nothing`

if given
`ByteString`

is too short or when width or height is lesser than 1.