-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, <>}. -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, <>. -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 = <>, X2 = case Width of 0 -> 0; Gleam@denominator -> (X + 1) rem Gleam@denominator end, case {X2, Y} of {0, 0} -> {State@1, <>}; {0, _} -> Bmp@2 = <>, 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) ).