Skip to content

Commit

Permalink
Add vips_foreign_find_load_source & vips_foreign_find_save_target
Browse files Browse the repository at this point in the history
  • Loading branch information
akash-akya committed Jan 3, 2025
1 parent aeeb849 commit a9a6a58
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 2 deletions.
65 changes: 65 additions & 0 deletions c_src/vips_foreign.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,71 @@ ERL_NIF_TERM nif_foreign_find_save(ErlNifEnv *env, int argc,
return ret;
}


ERL_NIF_TERM nif_foreign_find_load_source(ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]) {
ASSERT_ARGC(argc, 1);

ErlNifTime start;
ERL_NIF_TERM ret;
VipsSource *source;
const char *name;

start = enif_monotonic_time(ERL_NIF_USEC);

if (!erl_term_to_g_object(env, argv[0], (GObject **)&source)) {
ret = make_error(env, "Failed to get VipsSource");
goto exit;
}

name = vips_foreign_find_load_source(source);

if (!name) {
error("Failed to find the loader for the source. error: %s", vips_error_buffer());
vips_error_clear();
ret = make_error(env, "Failed to find loader for the source");
goto exit;
}

ret = make_ok(env, make_binary(env, name));

exit:
notify_consumed_timeslice(env, start, enif_monotonic_time(ERL_NIF_USEC));
return ret;
}

ERL_NIF_TERM nif_foreign_find_save_target(ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]) {
ASSERT_ARGC(argc, 1);

ErlNifTime start;
ERL_NIF_TERM ret;
char suffix[VIPS_PATH_MAX];
const char *name;

start = enif_monotonic_time(ERL_NIF_USEC);

if (!get_binary(env, argv[0], suffix, VIPS_PATH_MAX)) {
ret = make_error(env, "Failed to get suffix");
goto exit;
}

name = vips_foreign_find_save_target(suffix);

if (!name) {
error("Failed to find saver for the target. error: %s", vips_error_buffer());
vips_error_clear();
ret = make_error(env, "Failed to find saver for the target");
goto exit;
}

ret = make_ok(env, make_binary(env, name));

exit:
notify_consumed_timeslice(env, start, enif_monotonic_time(ERL_NIF_USEC));
return ret;
}

ERL_NIF_TERM nif_foreign_get_suffixes(ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]) {
ASSERT_ARGC(argc, 0);
Expand Down
6 changes: 6 additions & 0 deletions c_src/vips_foreign.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ ERL_NIF_TERM nif_foreign_find_load(ErlNifEnv *env, int argc,
ERL_NIF_TERM nif_foreign_find_save(ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]);

ERL_NIF_TERM nif_foreign_find_load_source(ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]);

ERL_NIF_TERM nif_foreign_find_save_target(ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]);

ERL_NIF_TERM nif_foreign_get_suffixes(ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]);

Expand Down
4 changes: 3 additions & 1 deletion c_src/vix.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,10 +153,12 @@ static ErlNifFunc nif_funcs[] = {
0},

/* VipsForeign */
{"nif_foreign_find_load", 1, nif_foreign_find_load, 0},
{"nif_foreign_find_load", 1, nif_foreign_find_load, ERL_NIF_DIRTY_JOB_IO_BOUND}, // it might read bytes form the file
{"nif_foreign_find_save", 1, nif_foreign_find_save, 0},
{"nif_foreign_find_load_buffer", 1, nif_foreign_find_load_buffer, 0},
{"nif_foreign_find_save_buffer", 1, nif_foreign_find_save_buffer, 0},
{"nif_foreign_find_load_source", 1, nif_foreign_find_load_source, ERL_NIF_DIRTY_JOB_IO_BOUND}, // it might read bytes from source
{"nif_foreign_find_save_target", 1, nif_foreign_find_save_target, 0},
{"nif_foreign_get_suffixes", 0, nif_foreign_get_suffixes, 0},
{"nif_foreign_get_loader_suffixes", 0, nif_foreign_get_loader_suffixes, 0},

Expand Down
6 changes: 6 additions & 0 deletions lib/vix/nif.ex
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,12 @@ defmodule Vix.Nif do
def nif_foreign_find_save(_filename),
do: :erlang.nif_error(:nif_library_not_loaded)

def nif_foreign_find_load_source(_source),
do: :erlang.nif_error(:nif_library_not_loaded)

def nif_foreign_find_save_target(_suffix),
do: :erlang.nif_error(:nif_library_not_loaded)

def nif_foreign_get_suffixes,
do: :erlang.nif_error(:nif_library_not_loaded)

Expand Down
25 changes: 24 additions & 1 deletion lib/vix/vips/foreign.ex
Original file line number Diff line number Diff line change
@@ -1,23 +1,46 @@
defmodule Vix.Vips.Foreign do
alias Vix.Nif
@moduledoc false

alias Vix.Nif

@type operation_name :: String.t()

@spec find_load_buffer(binary) :: {:ok, operation_name} | {:error, String.t()}
def find_load_buffer(bin) do
Nif.nif_foreign_find_load_buffer(bin)
end

@spec find_save_buffer(String.t()) :: {:ok, operation_name} | {:error, String.t()}
def find_save_buffer(suffix) do
Nif.nif_foreign_find_save_buffer(suffix)
end

@doc """
Returns Vips operation name which can load the passed file
"""
@spec find_load(String.t()) :: {:ok, operation_name} | {:error, String.t()}
def find_load(filename) do
Nif.nif_foreign_find_load(filename)
end

@doc """
Returns Vips operation name which can save an image to passed format
"""
@spec find_save(String.t()) :: {:ok, operation_name} | {:error, String.t()}
def find_save(filename) do
Nif.nif_foreign_find_save(filename)
end

@spec find_load_source(Vix.Vips.Source.t()) :: {:ok, operation_name} | {:error, String.t()}
def find_load_source(source) do
Nif.nif_foreign_find_load_source(source)
end

@spec find_save_target(String.t()) :: {:ok, operation_name} | {:error, String.t()}
def find_save_target(suffix) do
Nif.nif_foreign_find_save_target(suffix)
end

def get_suffixes do
with {:ok, suffixes} <- Nif.nif_foreign_get_suffixes() do
{:ok, Enum.uniq(suffixes)}
Expand Down
14 changes: 14 additions & 0 deletions test/vix/foreign_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,18 @@ defmodule Vix.Vips.ForeignTest do
test "find_save" do
assert {:ok, "VipsForeignSaveJpegFile"} = Foreign.find_save("puppies.jpg")
end

test "find_load_source" do
bin = File.read!(img_path("puppies.jpg"))

assert {pipe, source} = Vix.SourcePipe.new()
assert :ok = Vix.SourcePipe.write(pipe, bin)
assert :ok = Vix.SourcePipe.stop(pipe)

assert {:ok, "VipsForeignLoadJpegSource"} = Foreign.find_load_source(source)
end

test "find_save_target" do
assert {:ok, "VipsForeignSaveJpegTarget"} = Foreign.find_save_target(".jpg")
end
end

0 comments on commit a9a6a58

Please sign in to comment.