Current section
Files
Jump to
Current section
Files
src/blimp.erl
-module(blimp).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/blimp.gleam").
-export([rgb/3, render/4, simple_render/3]).
-export_type([pixel/0]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
-opaque pixel() :: {pixel, bitstring()}.
-file("src/blimp.gleam", 42).
-spec rgb(integer(), integer(), integer()) -> pixel().
rgb(Red, Green, Blue) ->
{pixel, <<Blue, Green, Red>>}.
-file("src/blimp.gleam", 46).
-spec file_header(integer(), integer()) -> {bitstring(), integer()}.
file_header(Width, Height) ->
Padding = (4 - ((Width * 3) rem 4)) rem 4,
Row_size = (Width * 3) + Padding,
File_size = 54 + (Row_size * Height),
Pixel_offset = 54,
Reserved = 0,
Bmp = <<"BM"/utf8,
File_size:32/little,
Reserved:16/little,
Reserved:16/little,
Pixel_offset:32/little>>,
{Bmp, Padding}.
-file("src/blimp.gleam", 62).
-spec dib_header(bitstring(), integer(), integer()) -> bitstring().
dib_header(Bmp, Width, Height) ->
Dib_header_size = 40,
Planes = 1,
Bits_per_pixel = 24,
Compression = 0,
Image_size = 0,
X_pixels_per_meter = 0,
Y_pixels_per_meter = 0,
Colours_in_palette = 0,
Important_colours = 0,
Height@1 = - Height,
<<Bmp/bitstring,
Dib_header_size:32/little,
Width:32/little,
Height@1:32/little,
Planes:16/little,
Bits_per_pixel:16/little,
Compression:32/little,
Image_size:32/little,
X_pixels_per_meter:32/little,
Y_pixels_per_meter:32/little,
Colours_in_palette:32/little,
Important_colours:32/little>>.
-file("src/blimp.gleam", 92).
-spec render_loop(
bitstring(),
integer(),
integer(),
integer(),
bitstring(),
DLC,
fun((DLC, integer(), integer()) -> {DLC, pixel()})
) -> {DLC, bitstring()}.
render_loop(Bmp, Width, X, Y, Padding, State, Render) ->
{State@1, {pixel, Pixel}} = Render(State, X, Y),
Bmp@1 = <<Bmp/bitstring, Pixel/bitstring>>,
X2 = case Width of
0 -> 0;
Gleam@denominator -> (X + 1) rem Gleam@denominator
end,
case {X2, Y} of
{0, 0} ->
{State@1, <<Bmp@1/bitstring, Padding/bitstring>>};
{0, _} ->
Bmp@2 = <<Bmp@1/bitstring, Padding/bitstring>>,
render_loop(Bmp@2, Width, 0, Y - 1, Padding, State@1, Render);
{_, _} ->
render_loop(Bmp@1, Width, X2, Y, Padding, State@1, Render)
end.
-file("src/blimp.gleam", 9).
?DOC(
" Build a BMP image by iterating over each pixel with some state.\n"
"\n"
" The callback gets the X and Y position of the pixel, where 0,0 is\n"
" bottom-left.\n"
"\n"
" Rendering starts at the top and goes over each row, left to right, top to\n"
" bottom.\n"
).
-spec render(
integer(),
integer(),
DLB,
fun((DLB, integer(), integer()) -> {DLB, pixel()})
) -> {DLB, bitstring()}.
render(Width, Height, State, Plot) ->
{Bmp, Padding_size} = file_header(Width, Height),
Bmp@1 = dib_header(Bmp, Width, Height),
Padding_bits = Padding_size * 8,
Padding = <<0:(lists:max([(Padding_bits), 0]))>>,
render_loop(Bmp@1, Width, 0, Height - 1, Padding, State, Plot).
-file("src/blimp.gleam", 30).
?DOC(
" Build a BMP image by iterating over each pixel.\n"
"\n"
" The callback gets the X and Y position of the pixel, where 0,0 is\n"
" bottom-left.\n"
"\n"
" Rendering starts at the top and goes over each row, left to right, top to\n"
" bottom.\n"
).
-spec simple_render(
integer(),
integer(),
fun((integer(), integer()) -> pixel())
) -> bitstring().
simple_render(Width, Height, Plot) ->
erlang:element(
2,
render(Width, Height, nil, fun(State, X, Y) -> {State, Plot(X, Y)} end)
).