Skip to content

Commit 7791de5

Browse files
committed
Generate and Save the Identicon image
1 parent 6c5f9c3 commit 7791de5

File tree

5 files changed

+85
-2
lines changed

5 files changed

+85
-2
lines changed

identicon.iml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,6 @@
3636
<orderEntry type="library" name="benchee" level="project" />
3737
<orderEntry type="library" name="benchee_markdown" level="project" />
3838
<orderEntry type="library" name="stream_data" level="project" />
39+
<orderEntry type="library" name="vix" level="project" />
3940
</component>
4041
</module>

lib/identicon.ex

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ defmodule Identicon do
1111
|> hash_input()
1212
|> pick_color()
1313
|> build_grid()
14+
|> filter_odd_squares()
15+
|> build_pixel_map()
16+
|> draw_image()
17+
|> save_image("images/#{input}.png")
1418
end
1519

1620
@doc """
@@ -58,4 +62,77 @@ defmodule Identicon do
5862
[first, second | _rest] = row
5963
row ++ [second, first]
6064
end
65+
66+
@doc """
67+
Filters out the grid cells with odd codes, keeping only those with even codes.
68+
69+
## Examples
70+
71+
iex> image = %Identicon.Image{grid: [{0, 0}, {1, 1}, {2, 2}, {3, 3}]}
72+
iex> Identicon.filter_odd_squares(image)
73+
%Identicon.Image{grid: [{0, 0}, {2, 2}]}
74+
"""
75+
def filter_odd_squares(%Identicon.Image{grid: grid} = image) do
76+
even_cells_grid =
77+
Enum.filter(grid, fn {code, _index} ->
78+
rem(code, 2) == 0
79+
end)
80+
81+
%Identicon.Image{image | grid: even_cells_grid}
82+
end
83+
84+
@doc """
85+
Builds the pixel map for the identicon by calculating the top-left and bottom-right
86+
coordinates for each cell in the grid.
87+
88+
## Examples
89+
90+
iex> image = %Identicon.Image{grid: [{0, 0}, {1, 1}, {2, 2}]}
91+
iex> Identicon.build_pixel_map(image)
92+
%Identicon.Image{grid: [{0, 0}, {1, 1}, {2, 2}], pixel_map: [{{0, 0}, {60, 60}}, {{60, 60}, {120, 120}}, {{120, 120}, {180, 180}}]}
93+
"""
94+
def build_pixel_map(%Identicon.Image{grid: grid} = image) do
95+
pixel_map =
96+
Enum.map(grid, fn {_code, index} ->
97+
x = rem(index, 5) * 60
98+
y = div(index, 5) * 60
99+
100+
top_left = {x, y}
101+
bottom_right = {x + 60, y + 60}
102+
103+
{top_left, bottom_right}
104+
end)
105+
106+
%Identicon.Image{image | pixel_map: pixel_map}
107+
end
108+
109+
@doc """
110+
Draws the identicon image and saves it to the specified filename.
111+
Uses the Vix library to create and manipulate the image.
112+
"""
113+
def draw_image(%Identicon.Image{color: color, pixel_map: pixel_map}) do
114+
{r, g, b} = color
115+
116+
# Create a black image
117+
{:ok, img} = Vix.Vips.Operation.black(300, 300, bands: 3)
118+
# Make it white
119+
{:ok, img} = Vix.Vips.Operation.linear(img, [1, 1, 1], [255, 255, 255])
120+
121+
# Draw each colored rectangle
122+
Enum.reduce(pixel_map, img, fn {{x1, y1}, {x2, y2}}, acc_img ->
123+
width = x2 - x1
124+
height = y2 - y1
125+
{:ok, rect} = Vix.Vips.Operation.black(width, height, bands: 3)
126+
{:ok, rect} = Vix.Vips.Operation.linear(rect, [1, 1, 1], [r, g, b])
127+
{:ok, result} = Vix.Vips.Operation.insert(acc_img, rect, x1, y1)
128+
result
129+
end)
130+
end
131+
132+
@doc """
133+
Saves the image to the specified filename.
134+
"""
135+
def save_image(img, filename) do
136+
Vix.Vips.Image.write_to_file(img, filename)
137+
end
61138
end

lib/image.ex

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ defmodule Identicon.Image do
55

66
defstruct hex: nil,
77
color: nil,
8-
grid: nil
8+
grid: nil,
9+
pixel_map: nil
910
end

mix.exs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ defmodule Identicon.MixProject do
2323
[
2424
# {:dep_from_hexpm, "~> 0.3.0"},
2525
# {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
26-
{:ex_doc, "~> 0.40.0"}
26+
{:ex_doc, "~> 0.40.0"},
27+
{:vix, "~> 0.35.0"}
2728
]
2829
end
2930
end

mix.lock

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
%{
2+
"cc_precompiler": {:hex, :cc_precompiler, "0.1.11", "8c844d0b9fb98a3edea067f94f616b3f6b29b959b6b3bf25fee94ffe34364768", [:mix], [{:elixir_make, "~> 0.7", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "3427232caf0835f94680e5bcf082408a70b48ad68a5f5c0b02a3bea9f3a075b9"},
23
"earmark_parser": {:hex, :earmark_parser, "1.4.44", "f20830dd6b5c77afe2b063777ddbbff09f9759396500cdbe7523efd58d7a339c", [:mix], [], "hexpm", "4778ac752b4701a5599215f7030989c989ffdc4f6df457c5f36938cc2d2a2750"},
4+
"elixir_make": {:hex, :elixir_make, "0.9.0", "6484b3cd8c0cee58f09f05ecaf1a140a8c97670671a6a0e7ab4dc326c3109726", [:mix], [], "hexpm", "db23d4fd8b757462ad02f8aa73431a426fe6671c80b200d9710caf3d1dd0ffdb"},
35
"ex_doc": {:hex, :ex_doc, "0.40.0", "2635974389b80fd3ca61b0f993d459dad05b4a8f9b069dcfbbc5f6a8a6aef60e", [:mix], [{:earmark_parser, "~> 1.4.44", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "c040735250e2752b6e1102eeb4aa3f1dca74c316db873ae09f955d42136e7e5b"},
46
"makeup": {:hex, :makeup, "1.2.1", "e90ac1c65589ef354378def3ba19d401e739ee7ee06fb47f94c687016e3713d1", [:mix], [{:nimble_parsec, "~> 1.4", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "d36484867b0bae0fea568d10131197a4c2e47056a6fbe84922bf6ba71c8d17ce"},
57
"makeup_elixir": {:hex, :makeup_elixir, "1.0.1", "e928a4f984e795e41e3abd27bfc09f51db16ab8ba1aebdba2b3a575437efafc2", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "7284900d412a3e5cfd97fdaed4f5ed389b8f2b4cb49efc0eb3bd10e2febf9507"},
68
"makeup_erlang": {:hex, :makeup_erlang, "1.0.3", "4252d5d4098da7415c390e847c814bad3764c94a814a0b4245176215615e1035", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "953297c02582a33411ac6208f2c6e55f0e870df7f80da724ed613f10e6706afd"},
79
"nimble_parsec": {:hex, :nimble_parsec, "1.4.2", "8efba0122db06df95bfaa78f791344a89352ba04baedd3849593bfce4d0dc1c6", [:mix], [], "hexpm", "4b21398942dda052b403bbe1da991ccd03a053668d147d53fb8c4e0efe09c973"},
10+
"vix": {:hex, :vix, "0.35.0", "f6319b715e3b072e53eba456a21af5f2ff010a7a7b19b884600ea98a0609b18c", [:make, :mix], [{:cc_precompiler, "~> 0.1.4 or ~> 0.2", [hex: :cc_precompiler, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.7.3 or ~> 0.8", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:kino, "~> 0.7", [hex: :kino, repo: "hexpm", optional: true]}], "hexpm", "a3e80067a89d0631b6cf2b93594e03c1b303a2c7cddbbdd28040750d521984e5"},
811
}

0 commit comments

Comments
 (0)