#!/usr/bin/env escript %% -*- erlang -*- %%! debug verbose % an example shape. spec() -> {{frame_size, 2000, 3000}, {frame_rate, 10}, {frame_count, 10}, [{set_background_color, {rgb, 250, 100, 100}}, {show_frame}, {end_tag}]}. main(_) -> Filename = "simple.swf", {ok, S} = file:open(Filename, [binary, write]), file:write(S, swf(spec())), file:close(S). % SWF Structure swf(Spec) -> Version = 10, Rest = swf_rest(Spec), FileLength = size(Rest) + 8, <<"FWS", Version:8/unsigned-little, FileLength:32/unsigned-little, Rest/binary>>. swf_rest({{frame_size, Width, Height}, {frame_rate, FrameRate}, {frame_count, FrameCount}, Tags}) -> FrameSize = rectangle({rectangle, 0, Width, 0, Height}), FrameRateData = fixed8dot8(FrameRate), TagsData = list_to_binary([tag(X) || X <- Tags]), <>. % Basic Data Types nbits_unsigned(XS) -> % Necessary bits size for a list of integer values. Max = lists:max([abs(X) || X <- XS]), trunc(math:log(Max) / math:log(2)) + 1. nbits_signed(XS) -> nbits_unsigned(XS) + 1. fixed8dot8(N)-> IntegerPart = trunc(N), SmallPart = trunc((N - IntegerPart) / 1 * 256), <>. rectangle({rectangle, Xmin, Xmax, Ymin, Ymax}) -> Nbits = nbits_signed([Xmin, Xmax, Ymin, Ymax]), padding(<< Nbits:5, Xmin:Nbits/signed-big, Xmax:Nbits/signed-big, Ymin:Nbits/signed-big, Ymax:Nbits/signed-big>>). rgb({rgb, R, G, B}) -> <>. % Tag Format record_header_body(Type, Body) -> record_header_body(Type, Body, size(Body)). record_header_body(Type, Body, Length) when Length < 63 -> <> = <>, [<>, Body]; record_header_body(Type, Body, Length) -> <> = <>, [<>, <>, Body]. % Control Tags tag({end_tag}) -> record_header_body(0, <<>>); tag({show_frame}) -> record_header_body(1, <<>>); tag({set_background_color, RGB}) -> record_header_body(9, rgb(RGB)). %% bitstring utilities padding(Bits) -> Padding = 8 - bit_size(Bits) rem 8, <>.