james
95d4475271
All checks were successful
continuous-integration/drone/push Build is passing
Co-authored-by: James Harton <james@harton.nz> Reviewed-on: https://code.harton.nz/james/vivid_png/pulls/13
48 lines
1.2 KiB
Elixir
48 lines
1.2 KiB
Elixir
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_every(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)
|
|
<<r::integer-size(8), g::integer-size(8), b::integer-size(8), a::integer-size(8)>>
|
|
end
|
|
end
|