Packages
image
0.54.2
0.72.0
0.71.0
0.70.0
0.69.0
0.68.0
0.67.0
0.67.0-dev
retired
0.66.0
0.65.0
0.64.0
0.63.0
0.62.1
0.62.0
0.61.1
0.61.0
0.60.0
0.59.3
0.59.2
0.59.1
0.59.0
0.58.0
0.57.0
0.56.1
0.56.0
0.55.2
0.55.1
retired
0.55.0
0.54.4
0.54.3
0.54.2
0.54.1
0.54.0
0.53.0
0.52.3
0.52.2
0.52.1
0.52.0
retired
0.51.0
0.50.0
0.49.0
0.48.1
0.48.0
0.47.0
0.46.0
0.45.0
0.44.0
0.43.2
0.43.1
0.43.0
0.42.0
0.41.0
0.40.0
0.39.3
0.39.2
0.39.1
0.39.0
0.38.4
0.38.3
0.38.2
0.38.1
0.38.0
0.37.0
0.36.2
0.36.1
0.36.0
0.35.0
0.34.0
0.33.0
0.32.0
0.31.1
0.31.0
0.30.0
0.29.0
0.28.2
0.28.1
0.28.0
0.27.0
0.26.0
0.25.1
0.25.0
0.24.1
0.24.0
0.23.2
0.23.1
0.23.0
0.22.1
0.22.0
0.21.0
0.20.0
retired
0.19.0
0.18.1
0.18.0
0.17.0
0.16.0
0.15.0
0.14.4
0.14.2
0.14.1
0.14.0
retired
0.13.1
0.13.0
0.12.0
0.11.0
0.10.0
0.10.0-rc.0
retired
0.9.0
retired
0.8.0
0.7.0
0.6.0
0.5.0
0.4.0
0.3.0
0.2.0
0.1.0
An approachable image processing library primarily based upon Vix and libvips that is NIF-based, fast, multi-threaded, pipelined and has a low memory footprint.
Current section
Files
Jump to
Current section
Files
lib/image/matrix.ex
defmodule Image.Matrix do
@moduledoc false
# Adapted from [Nx.tensor/2](https://hexdocs.pm/nx/Nx.html#tensor/2)
def image_from_matrix(list) when is_list(list) do
type = infer_type(list)
[width, height] = dimensions(list)
with {:ok, format} <- Image.BandFormat.image_format_from_nx(type),
{:ok, image} = Vix.Vips.Image.new_matrix_from_array(width, height, list) do
Vix.Vips.Operation.cast(image, format)
end
end
### Helpers
defp dimensions(list) do
dimensions(list, [])
end
defp dimensions([], dimensions) do
[0 | dimensions]
end
defp dimensions([head | rest], parent_dimensions) when is_list(head) do
child_dimensions = dimensions(head, [])
n =
Enum.reduce(rest, 1, fn list, count ->
case dimensions(list, []) do
^child_dimensions ->
count + 1
other_dimensions ->
raise ArgumentError,
"cannot build image because lists have different shapes, got " <>
inspect(List.to_tuple(child_dimensions)) <>
" at position 0 and " <>
inspect(List.to_tuple(other_dimensions)) <> " at position #{count + 1}"
end
end)
child_dimensions ++ [n | parent_dimensions]
end
defp dimensions(list, dimensions) do
[length(list) | dimensions]
end
defp infer_type([head | tail]) when is_list(tail) do
Enum.reduce(tail, infer_type(head), &merge(infer_type(&1), &2))
end
defp infer_type(number) when is_number(number) do
infer(number)
end
defp infer_type(value) do
raise ArgumentError,
"invalid value given to Image.Matrix.binary_from_list/1, got: #{inspect(value)}"
end
defp infer(value) when is_integer(value), do: {:s, 64}
defp infer(value) when is_float(value), do: {:f, 32}
defp merge({type, left_size}, {type, right_size}) do
{type, max(left_size, right_size)}
end
defp merge(left, right) do
case sort(left, right) do
{{:u, size1}, {:s, size2}} -> {:s, max(min(size1 * 2, 64), size2)}
{_, type2} -> type2
end
end
defp sort({left_type, _} = left, {right_type, _} = right) do
if type_to_int(left_type) < type_to_int(right_type) do
{left, right}
else
{right, left}
end
end
defp type_to_int(:c), do: 4
defp type_to_int(:f), do: 3
defp type_to_int(:bf), do: 2
defp type_to_int(:s), do: 1
defp type_to_int(:u), do: 0
end