defmodule Fledex.Color.Names do
defmacro __using__(_opts) do
colors = load_color_file()
# TODO: Do some more transformations to the color data, so that we get fast access
quote do
@colors unquote(Macro.escape(colors))
def colors() do
@colors
end
def names() do
Enum.map(@colors, fn %{name: name} = _colorinfo -> name end)
end
def get_color_int(name) do
colorinfo = Enum.find(@colors, fn colorinfo -> colorinfo.name == name end)
colorinfo.hex
end
end
end
def load_color_file() do
# Name ,Hex (RGB) ,Red (RGB) ,Green (RGB) ,Blue (RGB) ,Hue (HSL/HSV) ,Satur. (HSL) ,Light (HSL) ,Satur.(HSV) ,Value (HSV),Source
"#{Path.dirname(__DIR__)}/color/names.csv"
|> File.stream!()
|> Stream.drop(1)
|> Stream.with_index()
|> Stream.map(fn {line,index} -> parse_line(index, line) end)
|> Stream.map(fn [index, name, hex, r, g, b, h, s1, l1, s2, v2, _sources] ->
%{
index: index,
name: convert_to_atom(name),
hex: clean_and_convert(hex),
rgb: {to_byte(r), to_byte(g), to_byte(b)},
hsl: {to_byte(h), to_byte(s1), to_byte(l1)},
hsv: {to_byte(h), to_byte(s2), to_byte(v2)}
}
end)
|> Enum.to_list()
end
def parse_line(index, line) do
[index] ++ String.split(line, ",", parts: 11)
end
defp convert_to_atom(name) do
name
|> String.trim()
|> String.normalize(:nfd)
|> String.replace(~r/[^a-zA-Z0-9_]/, "_")
|> String.replace(~r/__+/, "_")
|> String.downcase(:ascii)
|> String.to_atom()
end
defp clean_and_convert(hex_string) do
hex_string = String.replace(hex_string, "#", "")
{hex_int,_} = Integer.parse(hex_string, 16)
hex_int
end
defp to_byte(value) do
value = String.trim(value)
|> String.replace("—", "0")
case Float.parse(value) do
{value, "%"} -> trunc((value/100) * 255)
{value, "°"} -> trunc((value/360) * 255)
_ -> raise "Error in converting to byte value (#{value})"
end
end
end