From 770eeffb51ab168ffc397b86d213423bbbaa26df Mon Sep 17 00:00:00 2001 From: akash-akya Date: Mon, 3 May 2021 21:28:56 +0530 Subject: [PATCH] Add vips_image_new_from_image --- c_src/vips_image.c | 60 ++++++++++++++++++++++++++++++++++++ c_src/vips_image.h | 3 ++ c_src/vix.c | 2 ++ lib/vix/g_object/double.ex | 12 +++----- lib/vix/nif.ex | 18 ++++++++--- lib/vix/vips/image.ex | 9 ++++++ test/vix/vips/image_test.exs | 9 ++++++ 7 files changed, 100 insertions(+), 13 deletions(-) diff --git a/c_src/vips_image.c b/c_src/vips_image.c index 93f7aa8..52170e9 100644 --- a/c_src/vips_image.c +++ b/c_src/vips_image.c @@ -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); diff --git a/c_src/vips_image.h b/c_src/vips_image.h index eb2582d..a825c45 100644 --- a/c_src/vips_image.h +++ b/c_src/vips_image.h @@ -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[]); diff --git a/c_src/vix.c b/c_src/vix.c index 41964df..befe147 100644 --- a/c_src/vix.c +++ b/c_src/vix.c @@ -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, diff --git a/lib/vix/g_object/double.ex b/lib/vix/g_object/double.ex index a681852..8655d92 100644 --- a/lib/vix/g_object/double.ex +++ b/lib/vix/g_object/double.ex @@ -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 @@ -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 diff --git a/lib/vix/nif.ex b/lib/vix/nif.ex index 426ed6f..2136998 100644 --- a/lib/vix/nif.ex +++ b/lib/vix/nif.ex @@ -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) diff --git a/lib/vix/vips/image.ex b/lib/vix/vips/image.ex index 4cf98e7..c278ede 100644 --- a/lib/vix/vips/image.ex +++ b/lib/vix/vips/image.ex @@ -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 diff --git a/test/vix/vips/image_test.exs b/test/vix/vips/image_test.exs index ef309ce..83969dc 100644 --- a/test/vix/vips/image_test.exs +++ b/test/vix/vips/image_test.exs @@ -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