Skip to main content

src/sparklinekit@internal@png.erl

-module(sparklinekit@internal@png).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/sparklinekit/internal/png.gleam").
-export([encode/3]).

-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.

?MODULEDOC(false).

-file("src/sparklinekit/internal/png.gleam", 73).
?DOC(false).
-spec prepend_row(list(sparklinekit@internal@color:rgba()), list(integer())) -> list(integer()).
prepend_row(Row, Acc) ->
    case Row of
        [] ->
            Acc;

        [{rgba, R, G, B, A} | Rest] ->
            prepend_row(Rest, [A, B, G, R | Acc])
    end.

-file("src/sparklinekit/internal/png.gleam", 66).
?DOC(false).
-spec do_build_scanlines(
    list(list(sparklinekit@internal@color:rgba())),
    list(integer())
) -> list(integer()).
do_build_scanlines(Rows, Acc) ->
    case Rows of
        [] ->
            lists:reverse(Acc);

        [Row | Rest] ->
            do_build_scanlines(Rest, prepend_row(Row, [0 | Acc]))
    end.

-file("src/sparklinekit/internal/png.gleam", 62).
?DOC(false).
-spec build_scanlines(list(list(sparklinekit@internal@color:rgba()))) -> list(integer()).
build_scanlines(Rows) ->
    do_build_scanlines(Rows, []).

-file("src/sparklinekit/internal/png.gleam", 120).
?DOC(false).
-spec take_bytes(list(integer()), integer(), list(integer())) -> {list(integer()),
    list(integer())}.
take_bytes(Values, Count, Acc) ->
    case {Values, Count} of
        {Rest, 0} ->
            {lists:reverse(Acc), Rest};

        {[Value | Rest@1], _} ->
            take_bytes(Rest@1, Count - 1, [Value | Acc]);

        {[], _} ->
            {lists:reverse(Acc), []}
    end.

-file("src/sparklinekit/internal/png.gleam", 188).
?DOC(false).
-spec byte_list_to_bit_array(list(integer())) -> bitstring().
byte_list_to_bit_array(Bytes) ->
    _pipe = Bytes,
    _pipe@1 = gleam@list:map(_pipe, fun(Byte) -> <<Byte>> end),
    gleam_stdlib:bit_array_concat(_pipe@1).

-file("src/sparklinekit/internal/png.gleam", 194).
?DOC(false).
-spec prepend_reversed(list(DRO), list(DRO)) -> list(DRO).
prepend_reversed(Values, Acc) ->
    case Values of
        [] ->
            Acc;

        [Value | Rest] ->
            prepend_reversed(Rest, [Value | Acc])
    end.

-file("src/sparklinekit/internal/png.gleam", 201).
?DOC(false).
-spec u32_bytes(integer()) -> list(integer()).
u32_bytes(Value) ->
    [erlang:'band'(erlang:'bsr'(Value, 24), 16#FF),
        erlang:'band'(erlang:'bsr'(Value, 16), 16#FF),
        erlang:'band'(erlang:'bsr'(Value, 8), 16#FF),
        erlang:'band'(Value, 16#FF)].

-file("src/sparklinekit/internal/png.gleam", 210).
?DOC(false).
-spec low_byte(integer()) -> integer().
low_byte(Value) ->
    erlang:'band'(Value, 16#FF).

-file("src/sparklinekit/internal/png.gleam", 214).
?DOC(false).
-spec high_byte(integer()) -> integer().
high_byte(Value) ->
    erlang:'band'(erlang:'bsr'(Value, 8), 16#FF).

-file("src/sparklinekit/internal/png.gleam", 90).
?DOC(false).
-spec do_deflate_store_blocks(list(integer()), list(integer())) -> list(integer()).
do_deflate_store_blocks(Data, Acc) ->
    case Data of
        [] ->
            case Acc of
                [] ->
                    [1, 0, 0, 255, 255];

                _ ->
                    lists:reverse(Acc)
            end;

        _ ->
            {Chunk_bytes, Rest} = take_bytes(Data, 65535, []),
            Final_flag = case Rest of
                [] ->
                    1;

                _ ->
                    0
            end,
            Length = erlang:length(Chunk_bytes),
            Complement = 65535 - Length,
            Header = [Final_flag,
                low_byte(Length),
                high_byte(Length),
                low_byte(Complement),
                high_byte(Complement)],
            do_deflate_store_blocks(
                Rest,
                prepend_reversed(lists:append(Header, Chunk_bytes), Acc)
            )
    end.

-file("src/sparklinekit/internal/png.gleam", 86).
?DOC(false).
-spec deflate_store_blocks(list(integer())) -> list(integer()).
deflate_store_blocks(Data) ->
    do_deflate_store_blocks(Data, []).

-file("src/sparklinekit/internal/png.gleam", 156).
?DOC(false).
-spec crc32_byte(integer(), integer()) -> integer().
crc32_byte(Crc, Remaining) ->
    case Remaining =< 0 of
        true ->
            Crc;

        false ->
            Next = case erlang:'band'(Crc, 1) =:= 1 of
                true ->
                    erlang:'bxor'(erlang:'bsr'(Crc, 1), 16#EDB88320);

                false ->
                    erlang:'bsr'(Crc, 1)
            end,
            crc32_byte(Next, Remaining - 1)
    end.

-file("src/sparklinekit/internal/png.gleam", 148).
?DOC(false).
-spec do_crc32(list(integer()), integer()) -> integer().
do_crc32(Bytes, Crc) ->
    case Bytes of
        [] ->
            Crc;

        [Byte | Rest] ->
            do_crc32(Rest, crc32_byte(erlang:'bxor'(Crc, Byte), 8))
    end.

-file("src/sparklinekit/internal/png.gleam", 143).
?DOC(false).
-spec crc32(list(integer())) -> integer().
crc32(Bytes) ->
    _pipe = do_crc32(Bytes, 16#FFFFFFFF),
    erlang:'bxor'(_pipe, 16#FFFFFFFF).

-file("src/sparklinekit/internal/png.gleam", 132).
?DOC(false).
-spec chunk(list(integer()), list(integer())) -> list(integer()).
chunk(Type_bytes, Data_bytes) ->
    Crc = crc32(lists:append(Type_bytes, Data_bytes)),
    lists:append(
        u32_bytes(erlang:length(Data_bytes)),
        lists:append(Type_bytes, lists:append(Data_bytes, u32_bytes(Crc)))
    ).

-file("src/sparklinekit/internal/png.gleam", 177).
?DOC(false).
-spec do_adler32(list(integer()), integer(), integer()) -> integer().
do_adler32(Bytes, S1, S2) ->
    case Bytes of
        [] ->
            (S2 * 65536) + S1;

        [Byte | Rest] ->
            Next_s1 = case 65521 of
                0 -> 0;
                Gleam@denominator -> (S1 + Byte) rem Gleam@denominator
            end,
            Next_s2 = case 65521 of
                0 -> 0;
                Gleam@denominator@1 -> (S2 + Next_s1) rem Gleam@denominator@1
            end,
            do_adler32(Rest, Next_s1, Next_s2)
    end.

-file("src/sparklinekit/internal/png.gleam", 173).
?DOC(false).
-spec adler32(list(integer())) -> integer().
adler32(Bytes) ->
    do_adler32(Bytes, 1, 0).

-file("src/sparklinekit/internal/png.gleam", 80).
?DOC(false).
-spec zlib_store(list(integer())) -> list(integer()).
zlib_store(Data) ->
    Checksum = adler32(Data),
    _pipe = lists:append([120, 1], deflate_store_blocks(Data)),
    lists:append(_pipe, u32_bytes(Checksum)).

-file("src/sparklinekit/internal/png.gleam", 28).
?DOC(false).
-spec encode(
    list(list(sparklinekit@internal@color:rgba())),
    integer(),
    integer()
) -> bitstring().
encode(Pixels, Width, Height) ->
    Actual_width = case Width < 1 of
        true ->
            1;

        false ->
            Width
    end,
    Actual_height = case Height < 1 of
        true ->
            1;

        false ->
            Height
    end,
    Scanlines = build_scanlines(Pixels),
    Ihdr = lists:append(
        u32_bytes(Actual_width),
        lists:append(u32_bytes(Actual_height), [8, 6, 0, 0, 0])
    ),
    Idat = zlib_store(Scanlines),
    _pipe = lists:append(
        [137, 80, 78, 71, 13, 10, 26, 10],
        lists:append(
            chunk([73, 72, 68, 82], Ihdr),
            lists:append(
                chunk([73, 68, 65, 84], Idat),
                chunk([73, 69, 78, 68], [])
            )
        )
    ),
    byte_list_to_bit_array(_pipe).