Current section
Files
Jump to
Current section
Files
src/og_image_native.erl
-module(og_image_native).
-export([render_image/6]).
-on_load(init/0).
-define(APPNAME, og_image).
-define(LIBNAME, og_image_nif).
-define(VERSION, "1.1.0").
-define(GITHUB_REPO, "bigmoves/og_image").
init() ->
PrivDir = get_priv_dir(),
{Os, Arch} = detect_platform(),
NifName = lists:flatten(io_lib:format("~s-~s-~s.so", [?LIBNAME, Os, Arch])),
NifPath = filename:join(PrivDir, NifName),
%% Download if not present
case filelib:is_file(NifPath) of
true -> ok;
false -> download_nif(PrivDir, NifName, Os, Arch)
end,
%% Load the NIF (without .so extension)
NifPathNoExt = filename:join(PrivDir, lists:flatten(io_lib:format("~s-~s-~s", [?LIBNAME, Os, Arch]))),
erlang:load_nif(NifPathNoExt, 0).
get_priv_dir() ->
case code:priv_dir(?APPNAME) of
{error, bad_name} ->
case file:read_file_info("priv") of
{ok, _} -> "priv";
_ ->
EbinDir = filename:dirname(code:which(?MODULE)),
filename:join(filename:dirname(EbinDir), "priv")
end;
Dir -> Dir
end.
detect_platform() ->
Os = case os:type() of
{unix, darwin} -> "macos";
{unix, linux} -> "linux";
{unix, _} -> "linux"; % Assume linux-compatible for other unix
_ -> "unknown"
end,
Arch = case erlang:system_info(system_architecture) of
"aarch64" ++ _ -> "arm64";
"arm64" ++ _ -> "arm64";
"x86_64" ++ _ -> "x86_64";
"amd64" ++ _ -> "x86_64";
_ -> "x86_64" % Default fallback
end,
{Os, Arch}.
download_nif(PrivDir, NifName, Os, Arch) ->
Url = lists:flatten(io_lib:format(
"https://github.com/~s/releases/download/v~s/~s",
[?GITHUB_REPO, ?VERSION, NifName]
)),
io:format("og_image: Downloading NIF for ~s-~s...~n", [Os, Arch]),
%% Ensure priv dir exists
ok = filelib:ensure_dir(filename:join(PrivDir, "dummy")),
%% Start required applications
{ok, _} = application:ensure_all_started(ssl),
{ok, _} = application:ensure_all_started(inets),
NifPath = filename:join(PrivDir, NifName),
%% GitHub releases redirect to S3, so we need to follow redirects
HttpOpts = [
{ssl, [{verify, verify_none}]},
{autoredirect, true}
],
Opts = [{body_format, binary}],
case httpc:request(get, {Url, []}, HttpOpts, Opts) of
{ok, {{_, 200, _}, _, Body}} ->
ok = file:write_file(NifPath, Body),
io:format("og_image: Downloaded ~s (~.1f MB)~n", [NifName, byte_size(Body) / 1048576]);
{ok, {{_, Code, Reason}, _, _}} ->
error({nif_download_failed, Code, Reason, Url});
{error, Reason} ->
error({nif_download_failed, Reason, Url})
end.
%% NIF stub - replaced when NIF loads
render_image(_JsonStr, _Width, _Height, _Format, _Quality, _Resources) ->
erlang:nif_error(nif_not_loaded).