Packages
vix
0.13.0
0.40.0
0.39.0
0.38.0
0.37.0
0.36.0
0.35.0
0.34.0
0.33.1
0.33.0
0.32.0
0.31.1
0.31.0
0.30.0
0.29.0
0.28.0
0.27.0
0.26.0
0.25.0
0.24.0
0.23.1
0.22.0
0.21.0
0.20.0
0.19.0
0.18.0
0.17.0
0.16.4
0.16.3
0.16.2
0.16.1
0.16.0
0.15.1
0.15.0
0.14.0
0.13.0
0.12.0
0.11.0
0.10.1
0.10.0
0.9.0
0.8.0
0.7.0
0.6.1
0.6.0
0.5.0
0.4.0
0.3.0
0.2.1
0.2.0
retired
0.1.0
NIF based bindings for libvips
Current section
Files
Jump to
Current section
Files
lib/vix/vips/mutable_image.ex
defmodule Vix.Vips.MutableImage do
defstruct [:pid]
alias __MODULE__
alias Vix.Vips.Image
alias Vix.Type
@moduledoc """
Vips Mutable Image
See `Vix.Vips.Image.mutate/2`
"""
alias Vix.Nif
@behaviour Type
@typedoc """
Represents a mutable instance of VipsImage
"""
@type t() :: %MutableImage{pid: pid}
@impl Type
def typespec do
quote do
unquote(__MODULE__).t()
end
end
@impl Type
def default(nil) do
raise "default/1 for Vix.Vips.MutableImage is not supported"
end
@impl Type
def to_nif_term(%Image{} = image, data) do
Image.to_nif_term(image, data)
end
def to_nif_term(%MutableImage{}, _data) do
raise "to_nif_term/2 for Vix.Vips.MutableImage is not supported"
end
@impl Type
def to_erl_term(_term) do
raise "to_erl_term/1 for Vix.Vips.MutableImage is not supported"
end
# Create mutable image
@doc false
@spec new(Vix.Vips.Image.t()) :: {:ok, __MODULE__.t()} | {:error, term()}
def new(%Image{} = image) do
GenServer.start_link(__MODULE__, image)
|> wrap_type()
end
@doc """
Set the value of existing metadata item on an image. Value is converted to match existing value GType
"""
@spec update(__MODULE__.t(), String.t(), term()) :: :ok | {:error, term()}
def update(%MutableImage{pid: pid}, name, value) do
GenServer.call(pid, {:update, name, value})
end
@supported_gtype ~w(gint guint gdouble gboolean gchararray VipsArrayInt VipsArrayDouble VipsArrayImage VipsRefString VipsBlob VipsImage VipsInterpolate)a
@doc """
Create a metadata item on an image of the specifed type.
Vix converts value to specified GType
Supported GTypes
#{Enum.map(@supported_gtype, fn type -> " * `#{inspect(type)}`\n" end)}
"""
@spec set(__MODULE__.t(), String.t(), atom(), term()) :: :ok | {:error, term()}
def set(%MutableImage{pid: pid}, name, type, value) do
if type in @supported_gtype do
type = to_string(type)
GenServer.call(pid, {:set, name, type, cast_value(type, value)})
else
{:error, "invalid gtype. Supported types are #{inspect(@supported_gtype)}"}
end
end
@doc """
Remove a metadata item from an image.
"""
@spec remove(__MODULE__.t(), String.t()) :: :ok | {:error, term()}
def remove(%MutableImage{pid: pid}, name) do
GenServer.call(pid, {:remove, name})
end
@doc """
Returns metadata from the image
"""
@spec get(__MODULE__.t(), String.t()) :: {:ok, term()} | {:error, term()}
def get(%MutableImage{pid: pid}, name) do
GenServer.call(pid, {:get, name})
end
@doc false
def to_image(%MutableImage{pid: pid}) do
GenServer.call(pid, :to_image)
end
@doc false
def stop(%MutableImage{pid: pid}) do
GenServer.stop(pid, :normal)
end
use GenServer
@impl true
def init(image) do
case Image.copy_memory(image) do
{:ok, copy} -> {:ok, %{image: copy}}
{:error, error} -> {:stop, error}
end
end
@impl true
def handle_call({:update, name, value}, _from, %{image: image} = state) do
{:reply, Nif.nif_image_update_metadata(image.ref, name, value), state}
end
@impl true
def handle_call({:set, name, type, value}, _from, %{image: image} = state) do
{:reply, Nif.nif_image_set_metadata(image.ref, name, type, value), state}
end
@impl true
def handle_call({:remove, name}, _from, %{image: image} = state) do
{:reply, Nif.nif_image_remove_metadata(image.ref, name), state}
end
@impl true
def handle_call({:get, name}, _from, %{image: image} = state) do
{:reply, Image.header_value(image, name), state}
end
@impl true
def handle_call(:to_image, _from, %{image: image} = state) do
{:reply, Image.copy_memory(image), state}
end
@impl true
def handle_call({:operation, callback}, _from, %{image: image} = state) do
{:reply, callback.(image), state}
end
defp wrap_type({:ok, pid}), do: {:ok, %MutableImage{pid: pid}}
defp wrap_type(value), do: value
defp cast_value(type, value) do
Vix.Type.to_nif_term(type, value, nil)
end
end