Current section
Files
Jump to
Current section
Files
lib/identicon.ex
defmodule Identicon do
@moduledoc """
Documentation for Identicon.
## Example
The folder `generated_identicon/` must exist
iex>Identicon.main "test", 250, "generated_identicon/"
:ok
"""
@doc """
Main function to run the identicon
* `input` Text to generate the pattern
* `size` size of the image
* `directory` path to the folder to put the image
"""
def main(input, size \\ 250, directory \\ "") do
input
|> hash_input
|> pick_color
|> build_grid
|> filter_odd
|> build_pixel_map(size)
|> draw_image(size)
|> save_image(input, directory)
end
@doc """
Takes in the data struct `%Identicon.Image{}` and saves it in `image`
Then atribues to `r`, `g`, `b` the values of the first 3 items in the `hex: []` on the list and leaves the rest
%Identicon.Image{hex: [r, g, b | _]} = image
Never change a variable, only create a new one with diferent values
%Identicon.Image{image | color: {r, g, b}}
"""
def pick_color(%Identicon.Image{hex: [r, g, b | _]} = image) do
%Identicon.Image{image | color: {r, g, b}}
end
@doc """
Creates a hashed list from the input and returns the result as `%Identicon.Image{hex: hex}`
"""
def hash_input(input) do
hex = :crypto.hash(:md5, input)
|> :binary.bin_to_list
%Identicon.Image{hex: hex}
end
@doc """
Adds a grid to `%Identicon.Image{}` as a list of tuples with the values and the index
`Enum.map(&mirror_row/1)` same as `Enum.map(&mirror_row(&1))`
"""
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
@doc """
Adds a mirror of the row to it self
"""
def mirror_row([first, second | _] = row) do
row ++ [second, first]
end
@doc """
Removes odd numbers from the grid
"""
def filter_odd(%Identicon.Image{grid: grid} = image) do
grid = Enum.filter grid, fn
{number, _} -> rem(number, 2) == 0
end
%Identicon.Image{image | grid: grid}
end
@doc """
Extends the index of the grid to 50px squares as `{{x_top_left, y_top_left}, {x_bot_right, y_bot_right}}`
"""
def build_pixel_map(%Identicon.Image{grid: grid} = image, size) do
pixel_map = Enum.map grid, fn
{_, index} ->
size = div(size, 5)
x = rem(index, 5) * size
y = div(index, 5) * size
top_left = {x, y}
bot_right = {x + size, y + size}
{top_left, bot_right}
end
%Identicon.Image{image | pixel_map: pixel_map}
end
@doc """
Uses a erlang image library to create a image with the rectangles from pixel_map
"""
def draw_image(%Identicon.Image{color: color, pixel_map: pixel_map}, size) do
image = :egd.create(size, size)
fill = :egd.color(color)
Enum.each pixel_map, fn {top_left, bot_right} ->
:egd.filledRectangle(image, top_left, bot_right, fill)
end
:egd.render(image)
end
@doc """
Saves the image to a file
"""
def save_image(image, input, directory) do
File.write "#{directory}#{input}.png", image
end
end