defmodule Fledex.Functions do import Bitwise use Fledex.Color.Types alias Fledex.Color.Conversion alias Fledex.Color.Correction @spec step(boolean, byte) :: integer # Depending whether we want to reverse we move hue forward or backwards defp step(reversed, hue) defp step(false, hue), do: hue defp step(true, hue), do: -hue @spec create_rainbow_circular_hsv(pos_integer, byte, boolean) :: list(hsv) def create_rainbow_circular_hsv(num_leds, initialHue \\ 0, reversed \\ false) def create_rainbow_circular_hsv(0, _, _), do: [] def create_rainbow_circular_hsv(num_leds, initialHue, reversed) do hueChange = Kernel.trunc(65535 / num_leds) for n <- 0..(num_leds-1) do {(initialHue + step(reversed, n*hueChange>>>8)) &&& 0xFF, 240, 255} end end @spec create_rainbow_circular_rgb(pos_integer, byte, boolean) :: list(rgb) def create_rainbow_circular_rgb(num_leds, initialHue \\ 0, reversed \\ false) do create_rainbow_circular_hsv(num_leds, initialHue, reversed) |> hsv2rgb() end @spec create_gradient_rgb(pos_integer, rgb, rgb) :: list(rgb) def create_gradient_rgb(num_leds, {sr, sg, sb} = _start_color, {er, eg, eb} = _end_color) when num_leds > 0 do rdist87 = (er-sr) <<< 7 gdist87 = (eg-sg) <<< 7 bdist87 = (eb-sb) <<< 7 steps = num_leds+1 rdelta = (trunc(rdist87 / steps))*2 gdelta = (trunc(gdist87 / steps))*2 bdelta = (trunc(bdist87 / steps))*2 r88 = sr <<< 8 g88 = sg <<< 8 b88 = sb <<< 8 for n <- 1..steps-1 do {(r88 + rdelta*n) >>> 8, (g88 + gdelta*n) >>> 8, (b88 + bdelta*n) >>> 8} end end @spec hsv2rgb(list(hsv), (hsv, (rgb -> rgb) -> rgb), (rgb -> rgb)) :: list(rgb) def hsv2rgb(leds, conversion_function \\ &Conversion.Rainbow.hsv2rgb/2, color_correction \\ &Correction.color_correction_none/1 ) do Enum.map(leds, fn (hsv) -> conversion_function.(hsv, color_correction) end) end end