Skip to content

Instantly share code, notes, and snippets.

@bo0tzz
Created May 9, 2024 13:14
Show Gist options
  • Save bo0tzz/eb7818f7db3542ec540965252a3442d9 to your computer and use it in GitHub Desktop.
Save bo0tzz/eb7818f7db3542ec540965252a3442d9 to your computer and use it in GitHub Desktop.

Scarf pattern image

Mix.install([
  {:kino, "~> 0.8.1"},
  {:chunky_svg, "~> 0.2.0"},
  {:ex_png, github: "mikowitz/ex_png"}
])

Section

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()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment