Skip to content

Instantly share code, notes, and snippets.

@granolocks
Created September 20, 2022 12:49
Show Gist options
  • Save granolocks/f5677382fd2f9ebd1165e9c8a66ff8cd to your computer and use it in GitHub Desktop.
Save granolocks/f5677382fd2f9ebd1165e9c8a66ff8cd to your computer and use it in GitHub Desktop.
Identicon Generator in Elixir -- From "The Complete Elixir and Phoenix Bootcamp" on Udemy
defmodule Identicon do
@moduledoc """
Convert a string into an identicon image
"""
def main(input) do
%{%Identicon.Image{} | input: input}
|> get_hex
|> get_colors
|> get_grid
|> get_pixel_map
|> render
|> save
end
defp get_hex(%Identicon.Image{input: input} = image) do
hex =
:crypto.hash(:md5, input)
|> :binary.bin_to_list()
%Identicon.Image{image | hex: hex}
end
defp get_colors(%Identicon.Image{hex: [r, g, b | _]} = image) do
%Identicon.Image{image | color: {r, g, b}}
end
defp get_grid(%Identicon.Image{hex: hex} = image) do
grid =
Enum.slice(hex, 0..14)
# [[1,2,3],[4...],...]
|> Enum.chunk_every(3)
# [[1,2,3,2,1],[4...],...]
|> Enum.map(&mirror_row/1)
# [1,2,3,2,1,4...]
|> List.flatten()
# [false,true,false,true,false,true...]
|> Enum.map(&is_even?/1)
# [{false, 0}, {true, 1} ...]
|> Enum.with_index()
# [{true, 1}, {true, 3}...]
|> Enum.filter(fn {x, _} -> x end)
%Identicon.Image{image | grid: grid}
end
defp get_pixel_map(%Identicon.Image{grid: grid} = image) do
cells = 5
step = 50
pixel_map =
Enum.map(grid, fn {_, index} ->
x1 = rem(index, cells) * step
y1 = div(index, cells) * step
x2 = x1 + step
y2 = y1 + step
{{x1, y1}, {x2, y2}}
end)
%Identicon.Image{image | pixel_map: pixel_map}
end
defp render(%Identicon.Image{pixel_map: pixel_map, color: color} = image) do
img = :egd.create(250, 250)
color = :egd.color(color)
Enum.each(pixel_map, fn {top_left, bottom_right} ->
:egd.filledRectangle(
img,
top_left,
bottom_right,
color
)
end)
%Identicon.Image{image | render: :egd.render(img)}
end
defp save(%Identicon.Image{render: render, input: input}) do
File.write("#{input}.png", render)
end
defp mirror_row([a, b, c]) do
[a, b, c, b, a]
end
defp is_even?(num) do
rem(num, 2) == 0
end
end
defmodule Identicon.Image do
defstruct hex: nil, input: nil, color: nil, grid: nil, render: nil, pixel_map: nil
end
defmodule Identicon.MixProject do
use Mix.Project
def project do
[
app: :identicon,
version: "0.1.0",
elixir: "~> 1.13",
start_permanent: Mix.env() == :prod,
deps: deps()
]
end
def application do
[
extra_applications: [:logger, :crypto]
]
end
defp deps do
[
{:egd, github: "erlang/egd"}
]
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment