Packages

Gleam library for generating identicon images.

Current section

Files

Jump to
glidicon src glidicon.erl
Raw

src/glidicon.erl

-module(glidicon).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([color/1, hash/1, image/1, create/1]).
-export_type([identicon/0]).
-opaque identicon() :: {identicon,
bitstring(),
{integer(), integer(), integer()},
binary()}.
-spec color(identicon()) -> {integer(), integer(), integer()}.
color(Identicon) ->
erlang:element(3, Identicon).
-spec hash(identicon()) -> bitstring().
hash(Identicon) ->
erlang:element(2, Identicon).
-spec image(identicon()) -> binary().
image(Identicon) ->
erlang:element(4, Identicon).
-spec identicon() -> identicon().
identicon() ->
{identicon, <<>>, {0, 0, 0}, <<""/utf8>>}.
-spec set_hash(identicon(), binary()) -> identicon().
set_hash(Identicon, Input) ->
erlang:setelement(
2,
Identicon,
gleam_crypto_ffi:hash(md5, gleam_stdlib:identity(Input))
).
-spec set_color(identicon()) -> identicon().
set_color(Identicon) ->
_assert_subject = erlang:element(2, Identicon),
<<R, G, B, _/bitstring>> = case _assert_subject of
<<_, _, _, _/bitstring>> -> _assert_subject;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"glidicon"/utf8>>,
function => <<"set_color"/utf8>>,
line => 45})
end,
erlang:setelement(3, Identicon, {R, G, B}).
-spec chunk(bitstring()) -> list({integer(), integer(), integer()}).
chunk(Bits) ->
case Bits of
<<A, B, C, Rest/bitstring>> ->
[{A, B, C} | chunk(Rest)];
_ ->
[]
end.
-spec mirror_chunks(list({integer(), integer(), integer()})) -> list(list(integer())).
mirror_chunks(Chunks) ->
gleam@list:map(
Chunks,
fun(Chunk) ->
{A, B, C} = Chunk,
[A, B, C, B, A]
end
).
-spec add_indices(list(integer())) -> list({integer(), integer()}).
add_indices(Bits) ->
_pipe = Bits,
gleam@list:index_map(_pipe, fun(Val, Index) -> {Index, Val} end).
-spec remove_odd_values(list({integer(), integer()})) -> list({integer(),
integer()}).
remove_odd_values(Bits) ->
gleam@list:filter(
Bits,
fun(Bit) -> gleam@int:is_even(erlang:element(2, Bit)) end
).
-spec calculate_diagonals(list({integer(), integer()})) -> list({{integer(),
integer()},
{integer(), integer()}}).
calculate_diagonals(Bits) ->
gleam@list:map(
Bits,
fun(Bit) ->
{Index, _} = Bit,
Horizontal = (Index rem 5) * 50,
Vertical = (Index div 5) * 50,
Top_left = {Horizontal, Vertical},
Bottom_right = {Horizontal + 50, Vertical + 50},
{Top_left, Bottom_right}
end
).
-spec draw_image(
list({{integer(), integer()}, {integer(), integer()}}),
{integer(), integer(), integer()}
) -> binary().
draw_image(Diagonals, Color) ->
Image = egd:create(250, 250),
Fill_color = egd:color(Color),
gleam@list:each(
Diagonals,
fun(Diagonal) ->
{Top_left, Bottom_right} = Diagonal,
egd:'filledRectangle'(Image, Top_left, Bottom_right, Fill_color)
end
),
egd:render(Image).
-spec set_image(identicon()) -> identicon().
set_image(Identicon) ->
erlang:setelement(
4,
Identicon,
begin
_pipe = erlang:element(2, Identicon),
_pipe@1 = chunk(_pipe),
_pipe@2 = mirror_chunks(_pipe@1),
_pipe@3 = gleam@list:flatten(_pipe@2),
_pipe@4 = add_indices(_pipe@3),
_pipe@5 = remove_odd_values(_pipe@4),
_pipe@6 = calculate_diagonals(_pipe@5),
draw_image(_pipe@6, erlang:element(3, Identicon))
end
).
-spec create(binary()) -> identicon().
create(Input) ->
_pipe = identicon(),
_pipe@1 = set_hash(_pipe, Input),
_pipe@2 = set_color(_pipe@1),
set_image(_pipe@2).