defmodule Identicon do
@moduledoc """
Create your Identicon similar to github profiles by providing your name
## Examples
iex> Identicon.main "your_name"
## Installation
iex> def deps do
[{:elasticachex, "~> 1.1"}]
end
## Deps To Install to work as expected
iex> {:egd, github: "erlang/egd"}
"""
@doc """
Create a Identicon by providing the name to the main function
## Examples
iex> Identicon.main "your_name"
"""
def main(input) do
input
|> hash_input
|> pick_color
|> build_grid
|> filter_odd_squares
|> build_pixel_map
|> draw_image
|> save_image(input)
end
def save_image(image, input) do
File.write("#{input}.png", image)
end
def draw_image(%Identicon.Image{color: color, pixel_map: pixel_map}) do
image = :egd.create(250,250)
fill = :egd.color(color)
Enum.each(pixel_map, fn({start, stop}) ->
:egd.filledRectangle(image,start,stop,fill)
end)
:egd.render(image)
end
def pick_color(%Identicon.Image{hex: [r,g,b | _tail]} = image) do
%Identicon.Image{image | color: {r,g,b}}
end
def build_grid(%Identicon.Image{hex: hex} = image) do
grid =
hex
|> Enum.chunk_every(3,3,:discard)
|> Enum.map(&mirror_row/1)
|> List.flatten
|> Enum.with_index
%Identicon.Image{image | grid: grid}
end
def mirror_row([a,b | _tail] = grid) do
grid ++ [a,b]
end
def filter_odd_squares(%Identicon.Image{grid: grid} = image) do
grid = Enum.filter(grid, fn {num, _index} -> rem(num,2) == 0 end)
%Identicon.Image{image | grid: grid}
end
def hash_input(input) do
hex = :crypto.hash(:md5, input)
|> :binary.bin_to_list
%Identicon.Image{hex: hex}
end
def build_pixel_map(%Identicon.Image{grid: grid} = image) do
pixel_map = Enum.map(grid, fn ({_num, index }) ->
horizontal = rem(index,5) * 50
vertical = div(index,5) * 50
top_left = {horizontal,vertical}
bottom_right = {horizontal + 50, vertical + 50}
{top_left,bottom_right}
end)
%Identicon.Image{image | pixel_map: pixel_map}
end
end