Skip to content

Commit

Permalink
Merge pull request #8 from akash-akya/new-op
Browse files Browse the repository at this point in the history
Add vips_image_new_from_image
  • Loading branch information
akash-akya authored May 4, 2021
2 parents 0b1f62b + 770eeff commit 5c4128e
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 13 deletions.
60 changes: 60 additions & 0 deletions c_src/vips_image.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,66 @@ ERL_NIF_TERM nif_image_new_from_file(ErlNifEnv *env, int argc,
return ret;
}

ERL_NIF_TERM nif_image_new_from_image(ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]) {
assert_argc(argc, 2);

VipsImage *image;
VipsImage *copy;
ErlNifTime start;
ERL_NIF_TERM list, head;
double *array;
guint size;
ERL_NIF_TERM ret;

start = enif_monotonic_time(ERL_NIF_USEC);

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

list = argv[1];

if (!enif_get_list_length(env, list, &size)) {
error("Failed to get list length");
ret = enif_make_badarg(env);
goto exit;
}

array = g_new(double, size);

for (guint i = 0; i < size; i++) {
if (!enif_get_list_cell(env, list, &head, &list)) {
ret = make_error(env, "Failed to get list entry");
goto free_and_exit;
}

if (!enif_get_double(env, head, &array[i])) {
ret = make_error(env, "Failed to get double");
goto free_and_exit;
}
}

copy = vips_image_new_from_image(image, array, size);

if (!copy) {
error("Failed to create new image. error: %s", vips_error_buffer());
vips_error_clear();
ret = make_error(env, "Failed to create new image");
goto free_and_exit;
}

ret = make_ok(env, g_object_to_erl_term(env, (GObject *)copy));

free_and_exit:
g_free(array);

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

ERL_NIF_TERM nif_image_copy_memory(ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]) {
assert_argc(argc, 1);
Expand Down
3 changes: 3 additions & 0 deletions c_src/vips_image.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
ERL_NIF_TERM nif_image_new_from_file(ErlNifEnv *env, int argc,
const ERL_NIF_TERM argv[]);

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

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

Expand Down
2 changes: 2 additions & 0 deletions c_src/vix.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ static ErlNifFunc nif_funcs[] = {
/* VipsImage */
{"nif_image_new_from_file", 1, nif_image_new_from_file,
ERL_NIF_DIRTY_JOB_IO_BOUND},
{"nif_image_new_from_image", 2, nif_image_new_from_image,
ERL_NIF_DIRTY_JOB_IO_BOUND},
{"nif_image_copy_memory", 1, nif_image_copy_memory,
ERL_NIF_DIRTY_JOB_IO_BOUND},
{"nif_image_write_to_file", 2, nif_image_write_to_file,
Expand Down
12 changes: 4 additions & 8 deletions lib/vix/g_object/double.ex
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,7 @@ defmodule Vix.GObject.Double do
def to_nif_term(value, data) do
case value do
value when is_number(value) ->
value =
if !is_float(value) do
# convert to float
value * 1.0
else
value
end

value = normalize(value)
validate_number_limits!(value, data)
value

Expand All @@ -37,6 +30,9 @@ defmodule Vix.GObject.Double do
@impl Type
def to_erl_term(value), do: value

def normalize(num) when is_float(num), do: num
def normalize(num) when is_integer(num), do: num * 1.0

defp validate_number_limits!(_value, nil), do: :ok

defp validate_number_limits!(value, {min, max, _default}) do
Expand Down
18 changes: 13 additions & 5 deletions lib/vix/nif.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,25 @@ defmodule Vix.Nif do
end

# GObject
def nif_g_object_type_name(_obj), do: :erlang.nif_error(:nif_library_not_loaded)
def nif_g_object_type_name(_obj),
do: :erlang.nif_error(:nif_library_not_loaded)

# GType
def nif_g_type_from_instance(_instance), do: :erlang.nif_error(:nif_library_not_loaded)
def nif_g_type_from_instance(_instance),
do: :erlang.nif_error(:nif_library_not_loaded)

def nif_g_type_name(_type), do: :erlang.nif_error(:nif_library_not_loaded)
def nif_g_type_name(_type),
do: :erlang.nif_error(:nif_library_not_loaded)

# VipsImage
def nif_image_new_from_file(_src), do: :erlang.nif_error(:nif_library_not_loaded)
def nif_image_new_from_file(_src),
do: :erlang.nif_error(:nif_library_not_loaded)

def nif_image_copy_memory(_vips_image), do: :erlang.nif_error(:nif_library_not_loaded)
def nif_image_new_from_image(_vips_image, _value),
do: :erlang.nif_error(:nif_library_not_loaded)

def nif_image_copy_memory(_vips_image),
do: :erlang.nif_error(:nif_library_not_loaded)

def nif_image_write_to_file(_vips_image, _dst),
do: :erlang.nif_error(:nif_library_not_loaded)
Expand Down
9 changes: 9 additions & 0 deletions lib/vix/vips/image.ex
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,15 @@ defmodule Vix.Vips.Image do
Nif.nif_image_new_from_file(normalize_string(path))
end

@doc """
Creates a new image with width, height, format, interpretation, resolution and offset taken from the input image, but with each band set from `value`.
"""
@spec new_from_image(__MODULE__.t(), [float()]) :: {:ok, __MODULE__.t()} | {:error, term()}
def new_from_image(vips_image, value) do
float_value = Enum.map(value, &Vix.GObject.Double.normalize/1)
Nif.nif_image_new_from_image(vips_image, float_value)
end

# Copy an image to a memory area.
# If image is already a memory buffer, just ref and return. If it's
# a file on disc or a partial, allocate memory and copy the image to
Expand Down
9 changes: 9 additions & 0 deletions test/vix/vips/image_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -115,4 +115,13 @@ defmodule Vix.Vips.ImageTest do

assert <<_::binary-size(size), "\a">> = image_data
end

test "new image from other image", %{dir: _dir} do
{:ok, im} = Image.new_from_file(img_path("puppies.jpg"))
{:ok, new_im} = Image.new_from_image(im, [250])

assert Image.width(im) == Image.width(new_im)
assert Image.height(im) == Image.height(new_im)
assert Image.bands(new_im) == 1
end
end

0 comments on commit 5c4128e

Please sign in to comment.