Mix.install([
{:kino, "~> 0.8.1"},
{:chunky_svg, "~> 0.2.0"},
{:ex_png, github: "mikowitz/ex_png"}
])
defmodule Colours do
def colour(:brown), do: ExPng.Color.rgb(23, 9, 3)
def colour(:red), do: ExPng.Color.rgb(120, 54, 26)
def colour(:lilac), do: ExPng.Color.rgb(105, 100, 158)
def colour(:grey), do: ExPng.Color.rgb(138, 124, 107)
def colour(:white), do: ExPng.Color.rgb(237, 205, 164)
end
defmodule Constants do
def stitch_gauge, do: 19 / 10
def row_gauge, do: 21 / 10
# cm
def width, do: 14
def length, do: 170
def pixels_per_cm, do: 16
def image_width, do: pixels_per_cm() * width()
def total_rows, do: (row_gauge() * length()) |> round()
def line_height, do: (pixels_per_cm() * length() / total_rows()) |> round()
end
defmodule Render do
def render(section, rows) do
section
|> render_part()
|> Stream.cycle()
|> Enum.take(rows * Constants.line_height())
end
def render_part({colour}), do: List.duplicate(render_line(colour), Constants.line_height())
def render_part({a, b}) do
List.duplicate(render_line(a), Constants.line_height()) ++
List.duplicate(render_line(b), Constants.line_height())
end
def render_line(colour), do: Colours.colour(colour) |> List.duplicate(Constants.image_width())
end
sections = [
{51, {:grey}},
{71, {:grey, :lilac}},
{41, {:lilac, :white}},
{31, {:white}},
{28, {:white, :red}},
{74, {:red, :brown}},
{61, {:brown}}
]
image =
sections
|> Enum.map(fn {rows, section} ->
Render.render(section, rows)
end)
|> Enum.concat()
|> Enum.zip_with(& &1)
|> ExPng.Image.new()
:ok
{:ok, bin} = ExPng.Image.to_binary(image)
Kino.Image.new(bin, "image/png")
rows =
sections
|> Enum.map(&elem(&1, 0))
|> Enum.sum()
missing_rows = Constants.total_rows() - rows
"""
Current pattern is <%= rows %> out of <%= Constants.total_rows() %> rows
<%= if missing_rows != 0 do %>
<%= missing_rows %> rows missing
<% end %>
"""
|> EEx.eval_string(rows: rows, missing_rows: missing_rows)
|> Kino.Markdown.new()