defimpl Vivid.PNG, for: Vivid.Buffer do alias Vivid.{Buffer, RGBA} @moduledoc """ Convert a Vivid buffer to a PNG file. """ @doc """ Convert a Vivid buffer into a PNG file. """ @spec to_png(Buffer.t(), Path.t()) :: :ok | {:error, any} def to_png(buffer, path) do with {:ok, file} <- File.open(path, [:write]), png <- create_png(buffer, file), :ok <- :png.close(png), do: File.close(file) end defp config(%Buffer{rows: height, columns: width}, file) do %{ size: {width, height}, mode: {:rgba, 8}, file: file } end defp create_png(%Buffer{columns: width} = buffer, file) do png = buffer |> config(file) |> :png.create() buffer |> Stream.map(&colour_to_binary(&1)) |> Stream.chunk(width) |> Stream.map(&Enum.join(&1)) |> Enum.reverse() |> Enum.reduce(png, &:png.append(&2, {:row, &1})) end defp colour_to_binary(%RGBA{red: r, green: g, blue: b, alpha: a}) do r = round(r * 255) g = round(g * 255) b = round(b * 255) a = round(a * 255) <> end end