defmodule Abatap do @moduledoc """ Generate a basic PNG avatar from first name and last name. Largely based on https://github.com/zhangsoledad/alchemic_avatar and code by Sergio Tapia. """ defp to_rgb(color) do [r, g, b] = color "rgb(#{r},#{g},#{b})" end defp rgb_to_hex(r, g, b) when r in 0..255 when g in 0..255 when b in 0..255 do "~2.16.0B" |> List.duplicate(3) |> Enum.join() |> :io_lib.format([r, g, b]) |> to_string end @doc """ Generates an image using first name and last name of a user using imagemagick's convert command line tool. This function was cribbed from Sergio Tapia (https://sergiotapia.com/) https://elixirforum.com/t/generate-images-with-name-initials-using-elixir-and-imagemagick/12668 ## Examples ## default options # - palette: :google # - shape: :square # - size: 512 # - padding: size * 0.546875 iex> Abatap.create_from_initials("John", "Doe") {:ok, "/var/folders/bq/v60646nd7370n3lffmgfh94r00016k/T/JD-google-1731556906832.png"} iex> Abatap.create_from_initials("John", "Doe", palette: :google) {:ok, "/var/folders/bq/v60646nd7370n3lffmgfh94r00016k/T/JD-google-1731556436238.png"} iex> Abatap.create_from_initials("John", "Doe", palette: :iwanthue, shape: :circle) {:ok, "/var/folders/bq/v60646nd7370n3lffmgfh94r00016k/T/JD-iwanthue-1731557222647.png"} iex> Abatap.create_from_initials("John", "Doe", palette: :google, shape: :squircle, size: 1024, padding: 400) {:ok, "/var/folders/bq/v60646nd7370n3lffmgfh94r00016k/T/JD-google-1731556436238.png"} """ def create_from_initials(first_name, last_name, options \\ []) when byte_size(first_name) > 0 and byte_size(last_name) > 0 do palette = case Keyword.get(options, :palette) do nil -> :google value -> value end shape = case Keyword.get(options, :shape) do nil -> :square value -> value end size = case Keyword.get(options, :size) do nil -> 512 value -> value end padding = case Keyword.get(options, :padding) do nil -> trunc(size * 0.546875) value -> value end bg_color = case palette do :google -> rgb_list = Abatap.Color.google_random() "#" <> "#{rgb_to_hex(Enum.at(rgb_list, 0), Enum.at(rgb_list, 1), Enum.at(rgb_list, 2))}" :iwanthue -> rgb_list = Abatap.Color.iwanthue_random() "#" <> "#{rgb_to_hex(Enum.at(rgb_list, 0), Enum.at(rgb_list, 1), Enum.at(rgb_list, 2))}" end initials = "#{String.at(first_name, 0)}#{String.at(last_name, 0)}" image_path = System.tmp_dir!() |> Path.join( "#{initials}-#{Atom.to_string(palette)}-#{:os.system_time(:milli_seconds)}.png" ) {:ok, avatar} = Image.Text.text!(initials, background_fill_color: bg_color, font_size: size, padding: padding) |> Image.avatar(shape: shape, size: size) Image.write!(avatar, image_path) {:ok, image_path} end end